1.背景知識(shí)
YUV是被歐洲電視系統(tǒng)所采用的一種顏色編碼方法(屬于PAL),是PAL和SECAM模擬彩色電視制式采用的顏色空間。在現(xiàn)代彩色電視系統(tǒng)中,通常采用三管彩色攝影機(jī)或彩色CCD攝影機(jī)進(jìn)行取像,然后把取得的彩色圖像信號(hào)經(jīng)分色、分別放大校正后得到RGB,再經(jīng)過(guò)矩陣變換電路得到亮度信號(hào)Y和兩個(gè)色差信號(hào)B-Y(即U)、R-Y(即V),最后發(fā)送端將亮度和色差三個(gè)信號(hào)分別進(jìn)行編碼,用同一信道發(fā)送出去。這種色彩的表示方法就是所謂的YUV色彩空間表示。采用YUV色彩空間的重要性是它的亮度信號(hào)Y和色度信號(hào)U、V是分離的。YUV主要用于優(yōu)化彩色視頻信號(hào)的傳輸,使其向后相容老式黑白電視。與RGB視頻信號(hào)傳輸相比,它最大的優(yōu)點(diǎn)在于只需占用極少的頻寬(RGB要求三個(gè)獨(dú)立的視頻信號(hào)同時(shí)傳輸)。其中“Y”表示明亮度(Luminance或Luma),也就是灰階值;而“U”和“V” 表示的則是色度(Chrominance或Chroma),作用是描述影像色彩及飽和度,用于指定像素的顏色。“亮度”是透過(guò)RGB輸入信號(hào)來(lái)建立的,方法是將RGB信號(hào)的特定部分疊加到一起。“色度”則定義了顏色的兩個(gè)方面─色調(diào)與飽和度,分別用Cr和Cb來(lái)表示。其中,Cr反映了RGB輸入信號(hào)紅色部分與RGB信號(hào)亮度值之間的差異。而Cb反映的是RGB輸入信號(hào)藍(lán)色部分與RGB信號(hào)亮度值之間的差異。
2.FPGA 實(shí)現(xiàn)RGB圖像轉(zhuǎn)Gray圖像方法
一般RGB像轉(zhuǎn)灰度(gray)圖像有兩種方法,第一種就是使用RGB圖像的單通道去顯示圖像(R,G或B)。

RGB單通道實(shí)現(xiàn)灰度圖像FPGA源碼:
//----------------------------------------------------------------------
// R G B to gray
//----------------------------------------------------------------------
wire [15:0] rgb;
assign TFT_rgb = {rgb[15:11],rgb[15:11],1'b0,rgb[15:11]}; //red
//assign TFT_rgb = {rgb[10:6],rgb[10:5],rgb[10:6]}; //green
//assign TFT_rgb = {rgb[4:0],rgb[4:0],1'b1,rgb[4:0]}; //blue
//assign TFT_rgb = {rgb[4:0],rgb[4:0],1'b0,rgb[4:0]}; //blue





計(jì)算公式:Y = 0.183R + 0.614G + 0.062B + 16;
CB = -0.101R - 0.338G + 0.439B + 128;
CR = 0.439R - 0.399G - 0.040B + 128;
其中,時(shí)序在計(jì)算過(guò)程中完全沒(méi)有用到
輸入到輸出有三個(gè)clock的時(shí)延。
第一級(jí)流水線計(jì)算所有乘法;
第二級(jí)流水線計(jì)算所有加法,把正的和負(fù)的分開(kāi)進(jìn)行加法;
第三級(jí)流水線計(jì)算最終的和,若為負(fù)數(shù)取0;
Modelsim仿真部分希望自己去做。
RGB轉(zhuǎn)Ycbcr FPGA源碼:
/*
RGB轉(zhuǎn)YUV算法
計(jì)算公式:Y = 0.183R + 0.614G + 0.062B + 16;
CB = -0.101R - 0.338G + 0.439B + 128;
CR = 0.439R - 0.399G - 0.040B + 128;
其中,時(shí)序在計(jì)算過(guò)程中完全沒(méi)有用到
輸入到輸出有三個(gè)clock的時(shí)延。
第一級(jí)流水線計(jì)算所有乘法;
第二級(jí)流水線計(jì)算所有加法,把正的和負(fù)的分開(kāi)進(jìn)行加法;
第三級(jí)流水線計(jì)算最終的和,若為負(fù)數(shù)取0;
仿真通過(guò)
*/
`timescale 1ns/1ps
modulergb_to_ycbcr(
inputclk,
input[7 : 0]i_r_8b,
input[7 : 0]i_g_8b,
input[7 : 0]i_b_8b,
inputi_h_sync,
inputi_v_sync,
inputi_data_en,
output[7 : 0]o_y_8b,
output[7 : 0]o_cb_8b,
output[7 : 0]o_cr_8b,
outputo_h_sync,
outputo_v_sync,
outputo_data_en
);
/***************************************parameters*******************************************/
//multiply 256
parameterpara_0183_10b = 10'd47; //0.183 定點(diǎn)數(shù)
parameterpara_0614_10b = 10'd157;
parameterpara_0062_10b = 10'd16;
parameterpara_0101_10b = 10'd26;
parameterpara_0338_10b = 10'd86;
parameterpara_0439_10b = 10'd112;
parameterpara_0399_10b = 10'd102;
parameterpara_0040_10b = 10'd10;
parameterpara_16_18b = 18'd4096;
parameterpara_128_18b = 18'd32768;
/********************************************************************************************/
/***************************************signals**********************************************/
wiresign_cb;
wiresign_cr;
reg[17: 0]mult_r_for_y_18b;
reg[17: 0]mult_r_for_cb_18b;
reg[17: 0]mult_r_for_cr_18b;
reg[17: 0]mult_g_for_y_18b;
reg[17: 0]mult_g_for_cb_18b;
reg[17: 0]mult_g_for_cr_18b;
reg[17: 0]mult_b_for_y_18b;
reg[17: 0]mult_b_for_cb_18b;
reg[17: 0]mult_b_for_cr_18b;
reg[17: 0]add_y_0_18b;
reg[17: 0]add_cb_0_18b;
reg[17: 0]add_cr_0_18b;
reg[17: 0]add_y_1_18b;
reg[17: 0]add_cb_1_18b;
reg[17: 0]add_cr_1_18b;
reg[17: 0] result_y_18b;
reg[17: 0]result_cb_18b;
reg[17: 0]result_cr_18b;
reg[9:0] y_tmp;
reg[9:0] cb_tmp;
reg[9:0] cr_tmp;
regi_h_sync_delay_1;
regi_v_sync_delay_1;
regi_data_en_delay_1;
regi_h_sync_delay_2;
regi_v_sync_delay_2;
regi_data_en_delay_2;
regi_h_sync_delay_3;
regi_v_sync_delay_3;
regi_data_en_delay_3;
/********************************************************************************************/
/***************************************initial**********************************************/
initial
begin
mult_r_for_y_18b <= 18'd0;
mult_r_for_cb_18b <= 18'd0;
mult_r_for_cr_18b <= 18'd0;
mult_g_for_y_18b <= 18'd0;
mult_g_for_cb_18b <= 18'd0;
mult_g_for_cr_18b <= 18'd0;
mult_b_for_y_18b <= 18'd0;
mult_g_for_cb_18b <= 18'd0;
mult_b_for_cr_18b <= 18'd0;
add_y_0_18b <= 18'd0;
add_cb_0_18b <= 18'd0;
add_cr_0_18b <= 18'd0;
add_y_1_18b <= 18'd0;
add_cb_1_18b <= 18'd0;
add_cr_1_18b <= 18'd0;
result_y_18b <= 18'd0;
result_cb_18b <= 18'd0;
result_cr_18b <= 18'd0;
i_h_sync_delay_1 <= 1'd0;
i_v_sync_delay_1 <= 1'd0;
i_data_en_delay_1 <= 1'd0;
i_h_sync_delay_2 <= 1'd0;
i_v_sync_delay_2 <= 1'd0;
i_data_en_delay_2 <= 1'd0;
end
/********************************************************************************************/
/***************************************arithmetic*******************************************/
//LV1 pipeline :mult
always @ (posedgeclk)
begin
mult_r_for_y_18b <= i_r_8b * para_0183_10b;
mult_r_for_cb_18b <= i_r_8b * para_0101_10b;
mult_r_for_cr_18b <= i_r_8b * para_0439_10b;
end
always @ (posedgeclk)
begin
mult_g_for_y_18b <= i_g_8b * para_0614_10b;
mult_g_for_cb_18b <= i_g_8b * para_0338_10b;
mult_g_for_cr_18b <= i_g_8b * para_0399_10b;
end
always @ (posedgeclk)
begin
mult_b_for_y_18b <= i_b_8b * para_0062_10b;
mult_b_for_cb_18b <= i_b_8b * para_0439_10b;
mult_b_for_cr_18b <= i_b_8b * para_0040_10b;
end
//LV2 pipeline : add
always @ (posedgeclk)
begin
add_y_0_18b <= mult_r_for_y_18b + mult_g_for_y_18b;
add_y_1_18b <= mult_b_for_y_18b + para_16_18b;
add_cb_0_18b <= mult_b_for_cb_18b + para_128_18b;
add_cb_1_18b <= mult_r_for_cb_18b + mult_g_for_cb_18b;
add_cr_0_18b <= mult_r_for_cr_18b + para_128_18b;
add_cr_1_18b <= mult_g_for_cr_18b + mult_b_for_cr_18b;
end
//LV3 pipeline : y + cb + cr
assignsign_cb = (add_cb_0_18b >= add_cb_1_18b);
assignsign_cr = (add_cr_0_18b >= add_cr_1_18b);
always @ (posedgeclk)
begin
result_y_18b <= add_y_0_18b + add_y_1_18b;
result_cb_18b <= sign_cb ? (add_cb_0_18b - add_cb_1_18b) : 18'd0;
result_cr_18b <= sign_cr ? (add_cr_0_18b - add_cr_1_18b) : 18'd0;
end
always @ (posedgeclk)
begin
y_tmp<= result_y_18b[17:8] + {9'd0,result_y_18b[7]};
cb_tmp<= result_cb_18b[17:8] + {9'd0,result_cb_18b[7]};
cr_tmp<= result_cr_18b[17:8] + {9'd0,result_cr_18b[7]};
end
//output
assigno_y_8b = (y_tmp[9:8] == 2'b00) ? y_tmp[7 : 0] : 8'hFF;
assigno_cb_8b = (cb_tmp[9:8] == 2'b00) ? cb_tmp[7 : 0] : 8'hFF;
assigno_cr_8b = (cr_tmp[9:8] == 2'b00) ? cr_tmp[7 : 0] : 8'hFF;
/********************************************************************************************/
/***************************************timing***********************************************/
always @ (posedgeclk)
begin
i_h_sync_delay_1 <= i_h_sync;
i_v_sync_delay_1 <= i_v_sync;
i_data_en_delay_1 <= i_data_en;
i_h_sync_delay_2 <= i_h_sync_delay_1;
i_v_sync_delay_2 <= i_v_sync_delay_1;
i_data_en_delay_2 <= i_data_en_delay_1;
i_h_sync_delay_3 <= i_h_sync_delay_2;
i_v_sync_delay_3 <= i_v_sync_delay_2;
i_data_en_delay_3 <= i_data_en_delay_2;
end
//--------------------------------------
//timing
//--------------------------------------
assigno_h_sync = i_h_sync_delay_3;
assigno_v_sync = i_v_sync_delay_3;
assign o_data_en = i_data_en_delay_3;
/********************************************************************************************/
Endmodule
代碼2:
////////////////////////////////////////////////////////////////
wire [15:0] rgb;
wire hs;
wire vs;
wire de;
wire[7 : 0]o_y_8b;
wire[7 : 0]o_cb_8b;
wire[7 : 0]o_cr_8b;
assign TFT_rgb = {o_y_8b[7:3],o_y_8b[7:2],o_y_8b[7:3]}; //Y
//assign TFT_rgb = {o_cb_8b[7:3],o_cb_8b[7:2],o_cb_8b[7:3]}; //cb
//assign TFT_rgb = {o_cr_8b[7:3],o_cr_8b[7:2],o_cr_8b[7:3]}; //cr
代碼已經(jīng)過(guò)驗(yàn)證,實(shí)現(xiàn)效果

Y分量實(shí)現(xiàn)效果
此方法實(shí)現(xiàn)RGB轉(zhuǎn)gray圖像效果較好。
掃一掃獲取最新精彩內(nèi)容與學(xué)習(xí)資料
星空人工智能技術(shù)網(wǎng) 倡導(dǎo)尊重與保護(hù)知識(shí)產(chǎn)權(quán)。如發(fā)現(xiàn)本站文章存在版權(quán)等問(wèn)題,煩請(qǐng)30天內(nèi)提供版權(quán)疑問(wèn)、身份證明、版權(quán)證明、聯(lián)系方式等發(fā)郵件至1851688011@qq.com我們將及時(shí)溝通與處理。!:首頁(yè) > 大數(shù)據(jù) » FPGA圖像處理之rgbtogray算法的實(shí)現(xiàn)