01圖像色彩空間概述
色彩本質(zhì)上是不同頻率的光,人眼對于不同頻率光線的不同感受產(chǎn)生主觀感知,從而得以區(qū)分不同的顏色。盡管從客觀上而言,色彩僅僅是不同頻率的光,但從視覺角度而言,不同顏色的認知難度很大,因此引入色彩空間(Color Space)以便圖像色彩的深入研究。
常見的色彩空間主要有:RGB、YUV(YCbCr)、Lab、HSV和CMY(CMYK)等。
1.1 RGB空間
RGB空間是基于人眼識別的顏色所定義的色彩空間,以紅(R,Red)、綠(G,Green)、藍(B,Blue)三種基本色為基礎進行不同程度的疊加而成。紅、綠、藍作為三原色按亮度分別劃分為256個等級,從而可以表示一千六百多萬種不同的顏色,且每種顏色是唯一的。
RGB色彩空間的豐富性使其成為數(shù)字圖像處理與顯示的重要格式。通??蓪GB色彩空間模型建立在笛卡爾坐標系中,采用空間坐標的形式表示出超過人眼分辨程度數(shù)量的顏色信息。
RGB色彩空間直觀且易于理解,然而R、G、B三個分量是高度相關(guān)的,由于人眼對于常見的紅綠藍三色的敏感程度不同,所以導致RGB顏色空間的均勻性非常差,且兩種顏色之間的知覺差異色差不能表示為該顏色空間中兩點間的距離,不過利用線性或非線性變換,可以從RGB顏色空間推導出其他的顏色特征空間。
1.2 YUV(YCbCr)空間
YUV色彩空間是彩色設備顯示指定的色彩空間,Y表示亮度分量,U和V表示色度分量。YCbCr色彩空間是從YUV色彩空間的基礎上演變而來的,與YUV相似,但存在一定差異。
YUV最初是北美NTSC系統(tǒng)和歐洲PAL系統(tǒng)中模擬電視信號編碼的基礎,采用亮度與色度分離的方式更易于圖像處理;YCbCr則是在世界數(shù)字組織視頻標準研制過程中作為ITU - R BT1601建議的一部分,是YUV經(jīng)過縮放和偏移的變種。在YUV系列中,YCbCr是在數(shù)字圖像處理系統(tǒng)中應用最為廣泛的格式,JPEG、MPEG、H.264均基于此格式進行處理。
YCbCr色彩空間中,Y表示亮度分量,Cb表示藍色色度分量,Cr表示紅色色度分量。亮度和色度分量相互獨立的方式,有利于利用人眼特性降低數(shù)字圖像所需的存儲容量,從而實現(xiàn)圖像的壓縮編碼等處理。
1.3 Lab空間
Lab色彩空間是基于生理特征的顏色系統(tǒng),與設備無關(guān),即采用數(shù)字化的方法描述人的視覺感知。L表示亮度,取值范圍為0~100,表示從黑~白;a分量取值范圍為 -128~127,表示從綠~紅;b分量取值范圍為 -128~127,表示從藍~黃。
Lab色彩空間致力于感知均勻性,它的L分量密切匹配人類亮度感知。因此,可以被用來通過修改a和b分量的輸出色階來做精確的顏色平衡,或使用L分量來調(diào)整亮度對比。
Lab色彩空間所描述的色域是最大的,因此Lab色彩空間存在大量色彩超出人類視域范圍,甚至無法在物理世界再現(xiàn)。同時,RGB等色彩空間的設備依賴性也使得Lab色彩空間無法直接與其他色彩空間進行轉(zhuǎn)換。
1.4 HSV空間
HSV色彩空間是根據(jù)顏色的直觀特性色調(diào)(H,Hue)、飽和度(S,Saturation)和亮度(V,Value)建立的色彩模型。由于H、S、V可以構(gòu)成錐形坐標系,所以HSV模型通常也稱為六角錐體模型(Hexcone Model)。
色調(diào)H:圖像色彩信息,描述光譜顏色所在位置。采用角度度量,取值范圍為0°~360°。若從紅色開始按逆時針方向計算:紅色為0°,綠色為120°,藍色為240°,互補色之間相差180°;
飽和度S:圖像純度信息,描述顏色接近光譜色的程度。采用比例值度量,取值范圍為0~1。顏色通常可看作某種光譜色與白色的混合結(jié)果,飽和度越高,光譜色所占比例越大,顏色越接近光譜色,表現(xiàn)為顏色深;飽和度越低,光譜色所占比例越小,顏色越遠離光譜色,表現(xiàn)為顏色淺。飽和度為0時,表現(xiàn)出顏色僅有灰度;
亮度V:圖像亮度信息,描述色彩的明亮程度。采用比例值度量,取值范圍為0~1。對于光源色,明度值與發(fā)光體的光亮度有關(guān);對于物體色,此值和物體的透射比或反射比有關(guān)。
1.5 CMY(CMYK)空間
CMYK色彩空間是一種減色模式色彩空間,常用于彩色印刷。CMYK是基于C(Cyan)、M(Megenta)、Y(Yellow)和K(Black)四種顏色疊加而成的,由于在實際應用中青色(Cyan)、洋紅色(Megenta)和黃色(Yellow)疊加很難形成真正的黑色(Black),而是褐色,因此引入黑色K(Black)強化暗調(diào),加深暗部色彩。
CMYK與RGB根本的區(qū)別在于CMYK采用減色色彩模式——當陽光照射到一個物體上時,物體將吸收一部分光線并反射剩下的光線,反射的光線就是所看見的物體顏色,即減色色彩模式。因此,CMYK色彩模式更接近于真實效果,盡管不如RGB模式下的色彩多,但更適合印刷。
02
色彩空間轉(zhuǎn)換原理
盡管RGB是日常生活中彩色視頻圖像最常用的圖像格式,但RGB格式圖像將色調(diào)、亮度和飽和度綜合在一起,細節(jié)上難以進行數(shù)字化調(diào)整,因此在科學研究中通常采用YUV(YCbCr)或灰度圖格式,掌握RGB與YUV(YCbCr)/灰度圖之間的轉(zhuǎn)換原理有利于后續(xù)數(shù)字圖像處理分析。
2.1 RGB與YUV轉(zhuǎn)換原理
RGB與YUV依據(jù)以下公式進行轉(zhuǎn)換:
RGB轉(zhuǎn)為YUV:
Y = 0.299*R + 0.587*G + 0.114*B
U = - 0.169*R - 0.331*G + 0.5*B + 128
V = 0.5*R - 0.419*G - 0.081*B + 128
YUV轉(zhuǎn)為RGB:
R = Y + 1.402*(V-128)
G = Y - 0.344*(U-128) - 0.714*(V-128)
B = Y + 1.772*(U-128)
Matlab轉(zhuǎn)換代碼:
%**********************************************************************
% -------------------------------------------------------------------
% Company: Cascatrix
% Engineer: Carson
%
% Create Date: 2023/02/11
% Design Name: rgb_yuv
% Module Name: rgb_yuv
% Tool Versions: v1.0
% Description: Convert RGB888 into YUV
%-------------------------------------------------------------------
%*********************************************************************/
clear;clear all;clc;
% Load image
image_in = imread('cascatrix.jpg');
% Seperate R G B
image_r = int16(image_in(:,:,1));
image_g = int16(image_in(:,:,2));
image_b = int16(image_in(:,:,3));
% Get image size
[row,col,n] = size(image_in);
% Calculate Y U V
image_y = 0.299*image_r + 0.587*image_g + 0.114*image_b;
image_u = - 0.169*image_r - 0.331*image_g + 0.5*image_b + 128;
image_v = 0.5*image_r - 0.419*image_g - 0.081*image_b + 128;
% Recover R G B
image_out_r = image_y + 1.402*(image_v - 128);
image_out_g = image_y - 0.344*(image_u - 128) - 0.714*(image_v - 128);
image_out_b = image_y + 1.772*(image_u - 128);
% Output processed RGB image
image_out = cat(3,image_out_r,image_out_g,image_out_b);
% Display before/after processed image
figure(1)
subplot(121);
imshow(uint8(image_in)), title('Image in');
subplot(122);
imshow(uint8(image_out));title('Image out');
% Display Y U V
figure(2)
subplot(131);
imshow(uint8(image_y)),title('Image Y');
subplot(132);
imshow(uint8(image_u)),title('Image U');
subplot(133);
imshow(uint8(image_v)),title('Image V');
Matlab代碼將輸出結(jié)果:
1. 轉(zhuǎn)換前/后圖像對比:
2. Y、U、V三通道圖像顯示:
2.2 RGB與YCbCr轉(zhuǎn)換原理
RGB與YCbCr依據(jù)以下公式進行轉(zhuǎn)換:
RGB轉(zhuǎn)為YCbCr:
Y = 0.257*R + 0.504*G + 0.098*B + 16
Cb = - 0.148*R - 0.291*G + 0.439*B + 128
Cr = 0.439*R - 0.368*G - 0.071*B + 128
YCbCr轉(zhuǎn)為RGB:
R = 1.164*(Y-16) + 1.596*(Cr-128)
G = 1.164*(Y-16) - 0.392*(Cb-128) - 0.813*(Cr-128)
B = 1.164*(Y-16) + 2.017*(Cb-128)
通過Matlab對轉(zhuǎn)換算法進行驗證:
Matlab轉(zhuǎn)換代碼:
%**********************************************************************
% -------------------------------------------------------------------
% Company: Cascatrix
% Engineer: Carson
%
% Create Date: 2023/02/11
% Design Name: rgb_ycbcr
% Module Name: rgb_ycbcr
% Tool Versions: v1.0
% Description: Convert RGB888 into YCbCr
%-------------------------------------------------------------------
%*********************************************************************/
clear;clear all;clc;
% Load image
image_in = imread('cascatrix.jpg');
% Seperate R G B
image_r = int16(image_in(:,:,1));
image_g = int16(image_in(:,:,2));
image_b = int16(image_in(:,:,3));
% Get image size
[row,col,n] = size(image_in);
% Calculate Y Cb Cr
image_y = 0.257*image_r + 0.504*image_g + 0.098*image_b + 16;
image_cb = - 0.148*image_r - 0.291*image_g + 0.439*image_b + 128;
image_cr = 0.439*image_r - 0.368*image_g - 0.071*image_b + 128;
% Recover R G B
image_out_r = 1.164*(image_y - 16) + 1.596*(image_cr - 128);
image_out_g = 1.164*(image_y - 16) - 0.392*(image_cb - 128) - 0.813*(image_cr - 128);
image_out_b = 1.164*(image_y - 16) + 2.017*(image_cb - 128);
% Output processed RGB image
image_out = cat(3,image_out_r,image_out_g,image_out_b);
% Display before/after processed image
figure(1)
subplot(121);
imshow(uint8(image_in)), title('Image in');
subplot(122);
imshow(uint8(image_out));title('Image out');
% Display Y Cb Cr
figure(2)
subplot(131);
imshow(uint8(image_y)),title('Image Y');
subplot(132);
imshow(uint8(image_cb)),title('Image Cb');
subplot(133);
imshow(uint8(image_cr)),title('Image Cr');
Matlab代碼將輸出結(jié)果:
1. 轉(zhuǎn)換前/后圖像對比:
2. Y、Cb、Cr三通道圖像顯示:
2.3 RGB生成灰度圖像原理
RGB生成灰度圖像的方法較多,常用轉(zhuǎn)換公式如下:
采用RGB中任意單通道表示灰度值:
Gray = R (Gray = G or Gray = B)
采用RGB三通道的平均值表示灰度值:
Gray = (R + G + B) / 3
采用RGB三通道的加權(quán)均值表示灰度值:
Gray = 0.299*R + 0.587*G + 0.114*B
采用RGB三通道的最大/最小值的均值表示灰度值:
Gray = ( max(R, G, B) + min(R, G, B) ) / 2
通過Matlab對轉(zhuǎn)換算法進行驗證:
Matlab轉(zhuǎn)換代碼(采用不同方法,轉(zhuǎn)換結(jié)果略有區(qū)別):
%**********************************************************************
% -------------------------------------------------------------------
% Company: Cascatrix
% Engineer: Carson
%
% Create Date: 2023/02/11
% Design Name: rgb_gray
% Module Name: rgb_gray
% Tool Versions: v1.0
% Description: Convert RGB888 into gray value
%-------------------------------------------------------------------
%*********************************************************************/
clear;clear all;clc;
% Load image
image_in = imread('cascatrix.jpg');
% Seperate R G B
image_r = int16(image_in(:,:,1));
image_g = int16(image_in(:,:,2));
image_b = int16(image_in(:,:,3));
% Get image size
[row,col,n] = size(image_in);
% Calculate gray value by different methods
gray = rgb2gray(image_in);
% gray = image_r;
% gray = 0.299 * image_r + 0.587 * image_g + 0.114 * image_b;
% gray = (image_r + image_g + image_b) / 3;
% Display before/after processed image
figure
subplot(121);
imshow(uint8(image_in)), title('Image in');
subplot(122);
imshow(uint8(gray));title('Image out');
Matlab代碼將輸出轉(zhuǎn)換前/后圖像:
03
色彩空間轉(zhuǎn)換實現(xiàn)
3.1 RGB與YCbCr轉(zhuǎn)換Verilog代碼
本節(jié)分析基于FPGA實現(xiàn)色彩空間轉(zhuǎn)換方法,在Vivado和Matlab聯(lián)合仿真的基礎上,對Verilog轉(zhuǎn)換實現(xiàn)結(jié)果在Matlab中展示,驗證代碼的可行性。
3.1.1 預處理操作
分析RGB轉(zhuǎn)為YCbCr的原理中存在小數(shù)乘法與加法運算,F(xiàn)PGA不擅長小數(shù)處理,因此采用擴大2^n倍后向右移n位進行實現(xiàn),具體實現(xiàn)方法如下:
RGB轉(zhuǎn)YCbCr算法:
Y = 0.257*R + 0.504*G + 0.098*B + 16
Cb = - 0.148*R - 0.291*G + 0.439*B + 128
Cr = 0.439*R - 0.368*G - 0.071*B + 128
將方程擴大256倍后右移8位,算法依然等價:
Y = 256*(0.257*R + 0.504*G + 0.098*B + 16)>>8
Cb = 256*(- 0.148*R - 0.291*G + 0.439*B + 128)>>8
Cr = 256*(0.439*R - 0.368*G - 0.071*B + 128)>>8
算法推導得:
Y = (66*R + 129*G + 25*B + 4096)>>8
Cb = (- 38*R - 74*G + 112*B + 32768)>>8
Cr = (112*R - 94*G - 18*B + 32768)>>8
算法轉(zhuǎn)化為FPGA擅長的乘法與移位運算。
3.1.2 Verilog代碼
基于Matlab與Verilog聯(lián)合仿真工程,添加格式轉(zhuǎn)換模塊cx_RGB_YCbCr構(gòu)建頂層top模塊,對top進行仿真。
各模塊代碼如下:
1. 頂層模塊 cx_top.v:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Cascatrix
// Engineer: Carson
//
// Create Date: 2023/02/12
// Design Name: Image_Color_Space
// Module Name: cx_top
// Tool Versions: v1.0
// Description: Covert RGB into YUV(YCbCr) and generate gray value
//
//////////////////////////////////////////////////////////////////////////////////
module cx_top(
input wire clk,
input wire rst_n,
output wireen,
outputwirehsyn,
output wirevsyn,
output wire [23:0]ycbcr_data
);
wire [23:0] data;
cx_image inst_cx_image(
.clk(clk),
.hsyn(hsyn),
.vsyn(vsyn),
.en (en ),
.data(data)
);
cx_RGB_YCbCr inst_cx_RGB_YCbCr
(
.clk(clk),
.rst_n (rst_n ),
.rgb_data(data),
.ycbcr_data(ycbcr_data)
);
endmodule
2. 圖像文件讀取模塊 cx_image.v:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Cascatrix
// Engineer: Carson
//
// Create Date: 2023/02/12
// Design Name: Image_Color_Space
// Module Name: cx_image
// Tool Versions: v1.0
// Description: Covert RGB into YUV(YCbCr) and generate gray value
//
//////////////////////////////////////////////////////////////////////////////////
`define PIXEL_1920_1080
//`define PIXEL_1680_1050
//`define PIXEL_1280_1024
//`define PIXEL_1280_720
//`define PIXEL_1024_768
//`define PIXEL_800_600
//`define PIXEL_640_480
module cx_image(
inputwireclk,
outputreghsyn,
outputregvsyn,
outputwireen,
outputreg [23:0]data
);
//1920x1080 148.5Mhz
`ifdef PIXEL_1920_1080
parameter H_ACTIVE = 1920;// 行數(shù)據(jù)有效時間
parameter H_FRONT_PORCH = 88; // 行消隱前肩時間
parameter H_SYNC_TIME = 44; // 行同步信號時間
parameter H_BACK_PORCH = 148; // 行消隱后肩時間
parameter V_ACTIVE = 1080;// 列數(shù)據(jù)有效時間
parameter V_FRONT_PORCH = 4; // 列消隱前肩時間
parameter V_SYNC_TIME = 5; // 列同步信號時間
parameter V_BACK_PORCH = 36; // 列消隱后肩時間
`endif
//1680x1050 119Mhz
`ifdef PIXEL_1680_1050
parameter H_ACTIVE = 1680;// 行數(shù)據(jù)有效時間
parameter H_FRONT_PORCH = 48; // 行消隱前肩時間
parameter H_SYNC_TIME = 32; // 行同步信號時間
parameter H_BACK_PORCH = 80; // 行消隱后肩時間
parameter V_ACTIVE = 1050;// 列數(shù)據(jù)有效時間
parameter V_FRONT_PORCH = 3; // 列消隱前肩時間
parameter V_SYNC_TIME = 6; // 列同步信號時間
parameter V_BACK_PORCH = 21; // 列消隱后肩時間
`endif
//1280x1024 108Mhz
`ifdef PIXEL_1280_1024
parameter H_ACTIVE = 1280;// 行數(shù)據(jù)有效時間
parameter H_FRONT_PORCH = 48; // 行消隱前肩時間
parameter H_SYNC_TIME = 112; // 行同步信號時間
parameter H_BACK_PORCH = 248; // 行消隱后肩時間
parameter V_ACTIVE = 1024;// 列數(shù)據(jù)有效時間
parameter V_FRONT_PORCH = 1; // 列消隱前肩時間
parameter V_SYNC_TIME = 3; // 列同步信號時間
parameter V_BACK_PORCH = 38; // 列消隱后肩時間
`endif
//1280X720 74.25MHZ
`ifdef PIXEL_1280_720
parameter H_ACTIVE = 1280;// 行數(shù)據(jù)有效時間
parameter H_FRONT_PORCH = 110; // 行消隱前肩時間
parameter H_SYNC_TIME = 40; // 行同步信號時間
parameter H_BACK_PORCH = 220; // 行消隱后肩時間
parameter V_ACTIVE = 720; // 列數(shù)據(jù)有效時間
parameter V_FRONT_PORCH = 5; // 列消隱前肩時間
parameter V_SYNC_TIME = 5; // 列同步信號時間
parameter V_BACK_PORCH = 20; // 列消隱后肩時間
`endif
//1024x768 65Mhz
`ifdef PIXEL_1024_768
parameter H_ACTIVE = 1024;// 行數(shù)據(jù)有效時間
parameter H_FRONT_PORCH = 24; // 行消隱前肩時間
parameter H_SYNC_TIME = 136; // 行同步信號時間
parameter H_BACK_PORCH = 160; // 行消隱后肩時間
parameter V_ACTIVE = 768; // 列數(shù)據(jù)有效時間
parameter V_FRONT_PORCH = 3; // 列消隱前肩時間
parameter V_SYNC_TIME = 6; // 列同步信號時間
parameter V_BACK_PORCH = 29; // 列消隱后肩時間
`endif
//800x600 40Mhz
`ifdef PIXEL_800_600
parameter H_ACTIVE = 800;// 行數(shù)據(jù)有效時間
parameter H_FRONT_PORCH = 40 ;// 行消隱前肩時間
parameter H_SYNC_TIME = 128;// 行同步信號時間
parameter H_BACK_PORCH = 88 ;// 行消隱后肩時間
parameter V_ACTIVE = 600;// 列數(shù)據(jù)有效時間
parameter V_FRONT_PORCH = 1 ;// 列消隱前肩時間
parameter V_SYNC_TIME = 4 ;// 列同步信號時間
parameter V_BACK_PORCH = 23 ;// 列消隱后肩時間
`endif
//640x480 25.175Mhz
`ifdef PIXEL_640_480
parameter H_ACTIVE = 640; // 行數(shù)據(jù)有效時間
parameter H_FRONT_PORCH = 16 ; // 行消隱前肩時間
parameter H_SYNC_TIME = 96 ; // 行同步信號時間
parameter H_BACK_PORCH = 48 ; // 行消隱后肩時間
parameter V_ACTIVE = 480; // 列數(shù)據(jù)有效時間
parameter V_FRONT_PORCH = 10 ; // 列消隱前肩時間
parameter V_SYNC_TIME = 2 ; // 列同步信號時間
parameter V_BACK_PORCH = 33 ; // 列消隱后肩時間
`endif
parameter H_TOTAL_TIME = H_ACTIVE + H_FRONT_PORCH + H_SYNC_TIME + H_BACK_PORCH;
parameter V_TOTAL_TIME = V_ACTIVE + V_FRONT_PORCH + V_SYNC_TIME + V_BACK_PORCH;
reg h_act = 'd0;
reg v_act = 'd0;
reg [12:0] h_syn_cnt = 'd0;
reg [12:0] v_syn_cnt = 'd0;
reg [23:0] dout = 'd0;
reg [23:0] image [0 : H_ACTIVE*V_ACTIVE-1];
reg [31:0] image_cnt = 'd0;
assign en = h_act & v_act;
//讀取txt文件到image數(shù)組中
initial begin
$readmemh("D:/FPGA_Document/CX_Document/CX_Image /02_Image_color_space/image_src/image_in.txt", image);
end
// 行掃描計數(shù)器
always@(posedge clk)
begin
if(h_syn_cnt == H_TOTAL_TIME-1)
h_syn_cnt <= 13'b0;
else
h_syn_cnt <= h_syn_cnt + 1'b1;
end
// 列掃描計數(shù)器
always@(posedge clk)
begin
if(h_syn_cnt == H_TOTAL_TIME-1)
begin
if(v_syn_cnt == V_TOTAL_TIME-1)
v_syn_cnt <= 13'b0;
else
v_syn_cnt <= v_syn_cnt + 1'b1;
end
end
// 行同步控制
always@(posedge clk)
begin
if(h_syn_cnt < H_SYNC_TIME)
hsyn <= 1'b0;
else
hsyn <= 1'b1;
end
// 場同步控制
always@(posedge clk)
begin
if(v_syn_cnt < V_SYNC_TIME)
vsyn <= 1'b0;
else
vsyn <= 1'b1;
end
always@(posedge clk)
begin
if(v_syn_cnt == V_SYNC_TIME + V_BACK_PORCH - 1 && h_syn_cnt == 0)
v_act = 1'b1;
else if(v_syn_cnt == V_SYNC_TIME + V_BACK_PORCH + V_ACTIVE - 1 && h_syn_cnt == 0)
v_act = 1'b0;
end
always@(posedge clk)
begin
if(h_syn_cnt == H_SYNC_TIME + H_BACK_PORCH - 1)
h_act = 1'b1;
else if(h_syn_cnt == H_SYNC_TIME + H_BACK_PORCH + H_ACTIVE - 1)
h_act = 1'b0;
end
always@(posedge clk)
begin
if(h_act & v_act)
image_cnt <= image_cnt + 1'b1;
else if(image_cnt == H_ACTIVE*V_ACTIVE - 1)
image_cnt <= 32'b0;
end
always@(posedge clk)
begin
if(h_act & v_act)
data <= image[image_cnt][23:0];
else
data <= 24'b0;
end
endmodule
3. RGB轉(zhuǎn)YCbCr模塊 cx_RGB_YCbCr:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Cascatrix
// Engineer: Carson
//
// Create Date: 2023/02/12
// Design Name: Image_Color_Space
// Module Name: cx_RGB_YCbCr
// Tool Versions: v1.0
// Description: Covert RGB into YUV(YCbCr) and generate gray value
//
//////////////////////////////////////////////////////////////////////////////////
module cx_RGB_YCbCr(
input wireclk,
input wirerst_n,
inputwire [23:0]rgb_data,
output wire [23:0]ycbcr_data
);
reg [7:0] r;
reg [7:0] g;
reg [7:0] b;
reg [15:0] y;
reg [15:0] cb;
reg [15:0] cr;
always@(*)
begin
r <= rgb_data[7:0];
g <= rgb_data[15:8];
b <= rgb_data[23:16];
end
always@(*)
begin
if(!rst_n)
begin
y <= 16'd0;
cb <= 16'd0;
cr <= 16'd0;
end
else
begin
y <= 66? * r + 129 * g + 25? * b + 4096 ;
cb <= - 38? * r - 74? * g + 112 * b + 32768;
cr <= 112 * r - 94? * g - 18? * b + 32768;? ? ?
end
end
assign ycbcr_data = {y[15:8], cb[15:8], cr[15:8]};
endmodule
4. 仿真模塊 sim_tb.v:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Cascatrix
// Engineer: Carson
//
// Create Date: 2023/02/12
// Design Name: Image_Color_Space
// Module Name: top
// Tool Versions: v1.0
// Description: Image output simulation
//
//////////////////////////////////////////////////////////////////////////////////
module sim_tb(
);
reg clk;
reg rst_n;
reg [31:0] pixel_cnt;
wire de;
wire [23:0] data;
integer image_txt;
parameter PIXEL_TOTAL = 1920*1080;
//parameter PIXEL_TOTAL = 1680*1050;
//parameter PIXEL_TOTAL = 1280*1024;
//parameter PIXEL_TOTAL = 1280*720;
//parameter PIXEL_TOTAL = 1024*768;
//parameter PIXEL_TOTAL = 800*600;
//parameter PIXEL_TOTAL = 640*480;
cx_top inst_cx_top
(
.clk (clk ),
.en (de ),
.hsyn ( ),
.vsyn ( ),
.ycbcr_data (data )
);
always #1 clk = ~clk;
initial
begin
clk = 1;
rst_n = 0;
#100
rst_n = 1;
end
initial
begin
image_txt = $fopen("D:/FPGA_Document/ CX_Document/ CX_Image/02_Image_color_space/image_src/image_out.txt");
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
pixel_cnt <= 0;
end
else if(de)
begin
pixel_cnt = pixel_cnt + 1;
$fwrite(image_txt,"%h ",data);
end
end
always@(posedge clk)
begin
if(pixel_cnt == PIXEL_TOTAL)
begin
$display("CX: image_out.txt is output completed successfully! %t", $realtime, "ps");
$fclose(image_txt);
$stop;
end
end
endmodule
3.1.3 實現(xiàn)效果分析
通過Matlab顯示Verilog處理后的image_out.txt文件:
%**********************************************************************
% -------------------------------------------------------------------
% Company: Cascatrix
% Engineer: Carson
%
% Create Date: 2023/02/13
% Design Name: ycbcr_display
% Module Name: ycbcr_display
% Tool Versions: v1.0
% Description: Convert .txt into YCbCr and display image in RGB
%-------------------------------------------------------------------
%*********************************************************************/
clear;clear all;clc;
% Image resolution
row = 1080;
col = 1920;
n = 3;
% Create output image
image_out = uint8(zeros(row,col,n));
% Write data into output image
FileImage = fopen('image_out.txt','r');
for x = 1:row
for y = 1:col
YCbCr = fscanf(FileImage,'%s',1);
image_out(x,y,1) = uint8(hex2dec(YCbCr(1:2)));
image_out(x,y,2) = uint8(hex2dec(YCbCr(3:4)));
image_out(x,y,3) = uint8(hex2dec(YCbCr(5:6)));
end
end
fclose(FileImage);
% Convert YCbCr into RGB
image_out = ycbcr2rgb(image_out);
% Vivado reads image in BGR
image_out = cat(3,image_out(:,:,3),image_out(:,:,2),image_out(:,:,1));
% Show the output image
imshow(image_out),title('Image output');
% Create image in .jpg format
imwrite(image_out,'cascatrix_output.jpg');
Matlab圖像顯示結(jié)果:
3.2 RGB生成灰度圖像Verilog代碼
本節(jié)分析基于FPGA實現(xiàn)RGB生成灰度圖算法,在Vivado和Matlab聯(lián)合仿真的基礎上,對Verilog轉(zhuǎn)換實現(xiàn)結(jié)果在Matlab中展示,驗證代碼的可行性。
3.2.1 預處理操作
類似于RGB轉(zhuǎn)為YCbCr,由RGB生成灰度圖中同樣存在小數(shù)乘法與加法運算,F(xiàn)PGA不擅長小數(shù)處理,因此采用擴大2^n倍后向右移n位進行實現(xiàn),具體實現(xiàn)方法如下:
RGB生成灰度圖算法:
Gray = 0.299*R + 0.587*G + 0.114*B
將方程擴大256倍后右移8位,算法依然等價:
Gray= 256*(0.299*R + 0.587*G + 0.114*B)>>8
算法推導得:
Gray= (77*R + 150*G + 29*B)>>8
算法轉(zhuǎn)化為FPGA擅長的乘法與移位運算。
3.2.2 Verilog代碼
基于Matlab與Verilog聯(lián)合仿真工程,添加格式轉(zhuǎn)換模塊cx_RGB_gray構(gòu)建頂層top模塊,對top進行仿真。
各模塊代碼如下:
1. 頂層模塊 cx_top.v:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Cascatrix
// Engineer: Carson
//
// Create Date: 2023/02/12
// Design Name: Image_Color_Space
// Module Name: cx_top
// Tool Versions: v1.0
// Description: Covert RGB into YUV(YCbCr) and generate gray value
//
//////////////////////////////////////////////////////////////////////////////////
module cx_top(
input wire clk,
input wire rst_n,
output wireen,
output wirehsyn,
output wirevsyn,
output wire [7:0]gray_data
);
wire [23:0] data;
cx_image inst_cx_image(
.clk(clk),
.hsyn (hsyn),
.vsyn (vsyn),
.en (en ),
.data (data)
);
cx_RGB_gray inst_cx_RGB_gray
(
.clk(clk),
.rst_n (rst_n ),
.rgb_data (data),
.gray_data (gray_data)
);
endmodule
2. 圖像文件讀取模塊 cx_image.v:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Cascatrix
// Engineer: Carson
//
// Create Date: 2023/02/12
// Design Name: Image_Color_Space
// Module Name: cx_image
// Tool Versions: v1.0
// Description: Covert RGB into YUV(YCbCr) and generate gray value
//
//////////////////////////////////////////////////////////////////////////////////
`define PIXEL_1920_1080
//`define PIXEL_1680_1050
//`define PIXEL_1280_1024
//`define PIXEL_1280_720
//`define PIXEL_1024_768
//`define PIXEL_800_600
//`define PIXEL_640_480
module cx_image(
inputwireclk,
outputreghsyn,
outputregvsyn,
outputwireen,
outputreg [23:0]data
);
//1920x1080 148.5Mhz
`ifdef PIXEL_1920_1080
parameter H_ACTIVE = 1920;// 行數(shù)據(jù)有效時間
parameter H_FRONT_PORCH = 88; // 行消隱前肩時間
parameter H_SYNC_TIME = 44; // 行同步信號時間
parameter H_BACK_PORCH = 148; // 行消隱后肩時間
parameter V_ACTIVE = 1080;// 列數(shù)據(jù)有效時間
parameter V_FRONT_PORCH = 4; // 列消隱前肩時間
parameter V_SYNC_TIME = 5; // 列同步信號時間
parameter V_BACK_PORCH = 36; // 列消隱后肩時間
`endif
//1680x1050 119Mhz
`ifdef PIXEL_1680_1050
parameter H_ACTIVE = 1680;// 行數(shù)據(jù)有效時間
parameter H_FRONT_PORCH = 48; // 行消隱前肩時間
parameter H_SYNC_TIME = 32; // 行同步信號時間
parameter H_BACK_PORCH = 80; // 行消隱后肩時間
parameter V_ACTIVE = 1050;// 列數(shù)據(jù)有效時間
parameter V_FRONT_PORCH = 3; // 列消隱前肩時間
parameter V_SYNC_TIME = 6; // 列同步信號時間
parameter V_BACK_PORCH = 21; // 列消隱后肩時間
`endif
//1280x1024 108Mhz
`ifdef PIXEL_1280_1024
parameter H_ACTIVE = 1280;// 行數(shù)據(jù)有效時間
parameter H_FRONT_PORCH = 48; // 行消隱前肩時間
parameter H_SYNC_TIME = 112; // 行同步信號時間
parameter H_BACK_PORCH = 248; // 行消隱后肩時間
parameter V_ACTIVE = 1024;// 列數(shù)據(jù)有效時間
parameter V_FRONT_PORCH = 1; // 列消隱前肩時間
parameter V_SYNC_TIME = 3; // 列同步信號時間
parameter V_BACK_PORCH = 38; // 列消隱后肩時間
`endif
//1280X720 74.25MHZ
`ifdef PIXEL_1280_720
parameter H_ACTIVE = 1280;// 行數(shù)據(jù)有效時間
parameter H_FRONT_PORCH = 110; // 行消隱前肩時間
parameter H_SYNC_TIME = 40; // 行同步信號時間
parameter H_BACK_PORCH = 220; // 行消隱后肩時間
parameter V_ACTIVE = 720; // 列數(shù)據(jù)有效時間
parameter V_FRONT_PORCH = 5; // 列消隱前肩時間
parameter V_SYNC_TIME = 5; // 列同步信號時間
parameter V_BACK_PORCH = 20; // 列消隱后肩時間
`endif
//1024x768 65Mhz
`ifdef PIXEL_1024_768
parameter H_ACTIVE = 1024;// 行數(shù)據(jù)有效時間
parameter H_FRONT_PORCH = 24; // 行消隱前肩時間
parameter H_SYNC_TIME = 136; // 行同步信號時間
parameter H_BACK_PORCH = 160; // 行消隱后肩時間
parameter V_ACTIVE = 768; // 列數(shù)據(jù)有效時間
parameter V_FRONT_PORCH = 3; // 列消隱前肩時間
parameter V_SYNC_TIME = 6; // 列同步信號時間
parameter V_BACK_PORCH = 29; // 列消隱后肩時間
`endif
//800x600 40Mhz
`ifdef PIXEL_800_600
parameter H_ACTIVE = 800;// 行數(shù)據(jù)有效時間
parameter H_FRONT_PORCH = 40 ;// 行消隱前肩時間
parameter H_SYNC_TIME = 128;// 行同步信號時間
parameter H_BACK_PORCH = 88 ;// 行消隱后肩時間
parameter V_ACTIVE = 600;// 列數(shù)據(jù)有效時間
parameter V_FRONT_PORCH = 1 ;// 列消隱前肩時間
parameter V_SYNC_TIME = 4 ;// 列同步信號時間
parameter V_BACK_PORCH = 23 ;// 列消隱后肩時間
`endif
//640x480 25.175Mhz
`ifdef PIXEL_640_480
parameter H_ACTIVE = 640; // 行數(shù)據(jù)有效時間
parameter H_FRONT_PORCH = 16 ; // 行消隱前肩時間
parameter H_SYNC_TIME = 96 ; // 行同步信號時間
parameter H_BACK_PORCH = 48 ; // 行消隱后肩時間
parameter V_ACTIVE = 480; // 列數(shù)據(jù)有效時間
parameter V_FRONT_PORCH = 10 ; // 列消隱前肩時間
parameter V_SYNC_TIME = 2 ; // 列同步信號時間
parameter V_BACK_PORCH = 33 ; // 列消隱后肩時間
`endif
parameter H_TOTAL_TIME = H_ACTIVE + H_FRONT_PORCH + H_SYNC_TIME + H_BACK_PORCH;
parameter V_TOTAL_TIME = V_ACTIVE + V_FRONT_PORCH + V_SYNC_TIME + V_BACK_PORCH;
reg h_act = 'd0;
reg v_act = 'd0;
reg [12:0] h_syn_cnt = 'd0;
reg [12:0] v_syn_cnt = 'd0;
reg [23:0] dout = 'd0;
reg [23:0] image [0 : H_ACTIVE*V_ACTIVE-1];
reg [31:0] image_cnt = 'd0;
assign en = h_act & v_act;
//讀取txt文件到image數(shù)組中
initial begin
$readmemh("D:/FPGA_Document/CX_Document/CX_Image /02_Image_color_space/image_src/image_in.txt", image);
end
// 行掃描計數(shù)器
always@(posedge clk)
begin
if(h_syn_cnt == H_TOTAL_TIME-1)
h_syn_cnt <= 13'b0;
else
h_syn_cnt <= h_syn_cnt + 1'b1;
end
// 列掃描計數(shù)器
always@(posedge clk)
begin
if(h_syn_cnt == H_TOTAL_TIME-1)
begin
if(v_syn_cnt == V_TOTAL_TIME-1)
v_syn_cnt <= 13'b0;
else
v_syn_cnt <= v_syn_cnt + 1'b1;
end
end
// 行同步控制
always@(posedge clk)
begin
if(h_syn_cnt < H_SYNC_TIME)
hsyn <= 1'b0;
else
hsyn <= 1'b1;
end
// 場同步控制
always@(posedge clk)
begin
if(v_syn_cnt < V_SYNC_TIME)
vsyn <= 1'b0;
else
vsyn <= 1'b1;
end
always@(posedge clk)
begin
if(v_syn_cnt == V_SYNC_TIME + V_BACK_PORCH - 1 && h_syn_cnt == 0)
v_act = 1'b1;
else if(v_syn_cnt == V_SYNC_TIME + V_BACK_PORCH + V_ACTIVE - 1 && h_syn_cnt == 0)
v_act = 1'b0;
end
always@(posedge clk)
begin
if(h_syn_cnt == H_SYNC_TIME + H_BACK_PORCH - 1)
h_act = 1'b1;
else if(h_syn_cnt == H_SYNC_TIME + H_BACK_PORCH + H_ACTIVE - 1)
h_act = 1'b0;
end
always@(posedge clk)
begin
if(h_act & v_act)
image_cnt <= image_cnt + 1'b1;
else if(image_cnt == H_ACTIVE*V_ACTIVE - 1)
image_cnt <= 32'b0;
end
always@(posedge clk)
begin
if(h_act & v_act)
data <= image[image_cnt][23:0];
else
data <= 24'b0;
end
endmodule
3. RGB轉(zhuǎn)gray模塊 cx_RGB_gray:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Cascatrix
// Engineer: Carson
//
// Create Date: 2023/02/12
// Design Name: Image_Color_Space
// Module Name: cx_RGB_gray
// Tool Versions: v1.0
// Description: Covert RGB into YUV(YCbCr) and generate gray value
//
//////////////////////////////////////////////////////////////////////////////////
module cx_RGB_gray(
input wireclk,
input wirerst_n,
inputwire [23:0]rgb_data,
output wire [7:0]gray_data
);
reg [7:0] r;
reg [7:0] g;
reg [7:0] b;
reg [15:0] gray_value;
always@(*)
begin
r <= rgb_data[7:0];
g <= rgb_data[15:8];
b <= rgb_data[23:16];
end
always@(*)
begin
if(!rst_n)
begin
gray_value <= 16'd0;
end
else
begin
gray_value <= 77 * r + 150 * g + 29 * b;
end
end
assign gray_data = gray_value[15:8];
endmodule
4. 仿真模塊 sim_tb.v:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Cascatrix
// Engineer: Carson
//
// Create Date: 2023/02/12
// Design Name: Image_Color_Space
// Module Name: top
// Tool Versions: v1.0
// Description: Image output simulation
//
//////////////////////////////////////////////////////////////////////////////////
module sim_tb(
);
reg clk;
reg rst_n;
reg [31:0] pixel_cnt;
wire de;
wire [7:0] data;
integer image_txt;
parameter PIXEL_TOTAL = 1920*1080;
//parameter PIXEL_TOTAL = 1680*1050;
//parameter PIXEL_TOTAL = 1280*1024;
//parameter PIXEL_TOTAL = 1280*720;
//parameter PIXEL_TOTAL = 1024*768;
//parameter PIXEL_TOTAL = 800*600;
//parameter PIXEL_TOTAL = 640*480;
cx_top inst_cx_top
(
.clk (clk ),
.en (de ),
.hsyn ( ),
.vsyn ( ),
.gray_data (data )
);
always #1 clk = ~clk;
initial
begin
clk = 1;
rst_n = 0;
#100
rst_n = 1;
end
initial
begin
image_txt = $fopen("D:/FPGA_Document/ CX_Document/ CX_Image/02_Image_color_space/image_src/image_out.txt");
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
pixel_cnt <= 0;
end
else if(de)
begin
pixel_cnt = pixel_cnt + 1;
$fwrite(image_txt,"%h ",data);
end
end
always@(posedge clk)
begin
if(pixel_cnt == PIXEL_TOTAL)
begin
$display("CX: image_out.txt is output completed successfully! %t", $realtime, "ps");
$fclose(image_txt);
$stop;
end
end
endmodule
3.2.3 實現(xiàn)效果分析
通過Matlab顯示Verilog處理后的image_out.txt文件:
%**********************************************************************
% -------------------------------------------------------------------
% Company: Cascatrix
% Engineer: Carson
%
% Create Date: 2023/02/13
% Design Name: gray_display
% Module Name: gray_display
% Tool Versions: v1.0
% Description: Display Gray Image
%-------------------------------------------------------------------
%*********************************************************************/
clear;clear all;clc;
% Image resolution
row = 1080;
col = 1920;
% Create output image
image_out = uint8(zeros(row,col));
% Write data into output image
FileImage = fopen('image_out.txt','r');
for x = 1:row
for y = 1:col
Gray = fscanf(FileImage,'%s',1);
image_out(x,y) = uint8(hex2dec(Gray(1:2)));
end
end
fclose(FileImage);
% Show the output image
imshow(image_out),title('Image output');
% Create image in .jpg format
imwrite(image_out,'cascatrix_output.jpg');
Matlab圖像顯示結(jié)果:
審核編輯:湯梓紅
-
FPGA
+關(guān)注
關(guān)注
1625文章
21627瀏覽量
601251 -
色彩
+關(guān)注
關(guān)注
0文章
21瀏覽量
12653 -
RGB
+關(guān)注
關(guān)注
4文章
797瀏覽量
58338 -
Verilog
+關(guān)注
關(guān)注
28文章
1343瀏覽量
109926 -
數(shù)字圖像處理
+關(guān)注
關(guān)注
7文章
103瀏覽量
18900
原文標題:FPGA數(shù)字圖像處理基礎(一)——色彩空間轉(zhuǎn)換(Verilog)
文章出處:【微信號:Carlinx FPGA,微信公眾號:Carlinx FPGA】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論