基于 FPGA 图像处理之 RGB 转灰度算法的实现

1、基础知识

        Gray 图像:灰度(gray)图像就是我们常说的黑白图像,由黑到白为灰阶为 0-255(8bit)。

        YUV 是被欧洲电视系统所采用的一种颜色编码方法(属于 PAL),是 PAL 和 SECAM 模拟彩色电视制式采用的颜色空间。在现代彩色电视系统中,通常采用三管彩色摄影机或彩色 CCD 摄影机进行取像,然后把取得的彩色图像信号经分色、分别放大校正后得到 RGB,再经过矩阵变换电路得到亮度信号 Y 和两个色差信号 B-Y(即 U)、R-Y(即 V),最后发送端将亮度和色差三个信号分别进行编码,用同一信道发送出去。这种色彩的表示方法就是所谓的 YUV 色彩空间表示。采用 YUV 色彩空间的重要性是它的亮度信号 Y 和色度信号 U、V 是分离的。YUV 主要用于优化彩色视频信号的传输,使其向后相容老式黑白电视。与 RGB 视频信号传输相比,它最大的优点在于只需占用极少的频宽(RGB 要求 三个独立的视频信号同时传输)。其中“Y”表示明亮度(Luminance 或 Luma),也就是灰阶值;而“U”和“V” 表示的则是色度(Chrominance 或 Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。“亮度”是透过 RGB 输入信号来 建立的,方法是将 RGB 信号的特定部分叠加到一起。“色度”则定义了颜色的两个方面─色调与饱和度,分别用 Cr 和 Cb 来表示。其中,Cr 反映了 RGB 输入信号红色部分与 RGB 信号亮度值之间的差异。而 Cb 反映的是 RGB 输入信号蓝 色部分与 RGB 信号亮度值之间的差异。

        Ycbcr 或 Y'CbCr 有的时候会被写作:YCBCR 或是 Y'CBCR,是色彩空间的一种,通常会用于影片中的影像连续处理,或是数字摄影系统中。Y'为颜色的亮度(luma)成分、而 CB 和 CR 则为蓝色和红色的浓度偏移量成份。Y'和 Y 是不同的,而 Y 就是所谓的流明(luminance),表示光的浓度且为非线性,使用伽马修正(gamma correction)编码处理。

2、FPGA 实现 RGB 图像转 Gray 图像方法

一般 RGB 像转灰度(gray)图像有两种方法:

        1)使用 RGB 图像的单通道去显示图像(R,G 或 B)。

        2)RGB 图像转换成 Ycbcr 图像,使用 Y 分量去显示图像,来实现彩色 图像转灰度图。

方法一:

         在基于 uart 传图的基础上我们增加了 R/G/B lane 模块来实现 rgb 转 gray 图像的显示。

方法二:

RGB 转 Ycbcr 算法:

        计算公式: Y = 0.183R + 0.614G + 0.062B + 16;

                         CB = -0.101R - 0.338G + 0.439B + 128;

                         CR = 0.439R - 0.399G - 0.040B + 128;

        其中,时序在计算过程中完全没有用到。

        输入到输出有三个 clock 的时延。

        第一级流水线计算所有乘法;

        第二级流水线计算所有加法,把正的和负的分开进行加法;

        第三级流水线计算最终的和,若为负数取 0。

代码:

`timescale 1ns/1ps
module	rgb_to_ycbcr(
						input								clk,
						input				[7 : 0]		i_r_8b,
						input				[7 : 0]		i_g_8b,
						input				[7 : 0]		i_b_8b,
  						
						input						      i_h_sync,
						input							   i_v_sync,
						input							   i_data_en,
						
						output			[7 : 0]		o_y_8b,
						output			[7 : 0]		o_cb_8b,
						output			[7 : 0]		o_cr_8b,
						
						output							o_h_sync,
						output							o_v_sync,                                                                                                  
						output						   o_data_en                                                                                                
						);

/***************************************parameters*******************************************/
//multiply 256
parameter	para_0183_10b = 10'd47;    //0.183 定点数
parameter	para_0614_10b = 10'd157;
parameter	para_0062_10b = 10'd16;
parameter	para_0101_10b = 10'd26;
parameter	para_0338_10b = 10'd86;
parameter	para_0439_10b = 10'd112;
parameter	para_0399_10b = 10'd102;
parameter	para_0040_10b = 10'd10;
parameter	para_16_18b = 18'd4096;
parameter	para_128_18b = 18'd32768;
/********************************************************************************************/

/***************************************signals**********************************************/
wire				sign_cb;
wire				sign_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;

reg					i_h_sync_delay_1;
reg					i_v_sync_delay_1;
reg					i_data_en_delay_1;

reg					i_h_sync_delay_2;
reg					i_v_sync_delay_2;
reg					i_data_en_delay_2;

reg					i_h_sync_delay_3;
reg					i_v_sync_delay_3;
reg					i_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 @ (posedge	clk)
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 @ (posedge	clk)
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 @ (posedge	clk)
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 @ (posedge	clk)
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

assign	sign_cb = (add_cb_0_18b >= add_cb_1_18b);
assign	sign_cr = (add_cr_0_18b >= add_cr_1_18b);
always @ (posedge	clk)
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 @ (posedge	clk)
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
assign	o_y_8b 	= (y_tmp[9:8] == 2'b00) ? y_tmp[7 : 0] : 8'hFF;
assign	o_cb_8b 	= (cb_tmp[9:8] == 2'b00) ? cb_tmp[7 : 0] : 8'hFF;
assign	o_cr_8b 	= (cr_tmp[9:8] == 2'b00) ? cr_tmp[7 : 0] : 8'hFF;
/********************************************************************************************/

/***************************************timing***********************************************/
always @ (posedge	clk)
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
//--------------------------------------	
assign	o_h_sync = i_h_sync_delay_3;
assign	o_v_sync = i_v_sync_delay_3;
assign 	o_data_en = i_data_en_delay_3;

/********************************************************************************************/
endmodule 

总结:

  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
FPGA图像处理中的灰度化是指将彩色图像换为灰度图像的处理过程。在FPGA实现中,可以使用Verilog语言来实现彩色图像的灰度算法,并通过Modelsim进行仿真验证。灰度化的算法通常是基于RGB通道的像素值,按照一定的公式进行换。其中常用的公式为:GRAY = 0.299R + 0.587G + 0.114B。由于FPGA不方便进行小数运算,可以将公式中的系数放大256倍进行运算,然后右移8位,即GRAY = (77R + 150G + 29B) >> 8。这样可以实现将彩色图像的每个像素点换为对应的灰度值。为了解决时序问题,可以对该公式进行流水线处理,分为三个阶段:乘法、加法和移位。通过这样的流水线处理,可以实现灰度化的算法FPGA上的高效实现。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [基于 FPGA 的彩色图像灰度化的设计实现](https://blog.csdn.net/wd12306/article/details/130711477)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [FPGA图像处理-灰度化](https://blog.csdn.net/lzl1342848782/article/details/125048818)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [基于FPGA图像处理灰度图像变换](https://download.csdn.net/download/qq_40261818/10611461)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发光中请勿扰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值