FPGA-图像处理-色彩空间转换(RGB转YUV和YCBCR)

简介: FPGA-图像处理-色彩空间转换(RGB转YUV和YCBCR)

之前转了一篇定点运算的文章希望大家看完再看这个,

涉及到FPGA的色彩空间转换的知识,一定要提定点运算,其实之前在进行小数运算的时候已经用到了,这里我也不详细说了看文章吧

OV7670摄像头采集的数据格式是RGB565,转换色彩空间计算公式是rgb888的

24位888——>16位565(取高位)

{R7 R6 R5 R4 R3 R2 R1 R0}{G7 G6 G5 G4 G3 G2 G1 G0}{B7 B6 B5 B4 B3 B2 B1 B0}转

{R7 R6 R5 R4 R3}{G7 G6 G5 G4 G3 G2}{B7 B6 B5 B4 B3}

16位565——>24位888(补位)

转换回去

{R4 R3 R2 R1 R0}{G5 G4 G3 G2 G1 G0}{B4 B3 B2 B1 B0}转

{R4 R3 R2 R1 R0 R2 R1 R0}{G5 G4 G3 G2 G1 G0 G1 G0}{B4 B3 B2 B1 B0 B2 B1 B0}

下面给出色彩空间的转换的代码(YUV和YCBCR):

/*RGB转YUV算法计算公式:Y=0.299R+0.587G+0.114B;
U=-0.148R-0.289G+0.437B; 
V=0.615R-0.515G-0.100B;
输入到输出有四个clock的时延。第一级流水线计算所有乘法;第二级流水线计算所有加法,把正的和负的分开进行加法;第三级流水线计算最终的和,若为负数取0第四级流水线进位计算*/`timescale1ns/1psmodulergb2ycbcr(
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_u_8b,
output     [7:0] o_v_8b,
outputo_h_sync,
outputo_v_sync,                                                                                                  
outputo_data_en);
/*--------------参数列表--------------------*///multiply256parameterpara_0299_10b=10'd77;parameterpara_0587_10b=10'd150;parameterpara_0114_10b=10'd29;parameterpara_0148_10b=10'd38;parameterpara_0289_10b=10'd74;parameterpara_0437_10b=10'd112;parameterpara_0615_10b=10'd158;parameterpara_0515_10b=10'd132;parameterpara_0100_10b=10'd26;/*---------------------------------------------*/wiresign_cb=0;
wiresign_cr=0;
reg[17: 0]  mult_r_for_y_18b=0;
reg[17: 0]  mult_r_for_u_18b=0;
reg[17: 0]  mult_r_for_v_18b=0;
reg[17: 0]  mult_g_for_y_18b=0;
reg[17: 0]  mult_g_for_u_18b=0;
reg[17: 0]  mult_g_for_v_18b=0;
reg[17: 0]  mult_b_for_y_18b=0;
reg[17: 0]  mult_b_for_u_18b=0;
reg[17: 0]  mult_b_for_v_18b=0;
reg[17: 0]  add_y_0_18b=0;
reg[17: 0]  add_u_0_18b=0;
reg[17: 0]  add_v_0_18b=0;
reg[17: 0]  add_y_1_18b=0;
reg[17: 0]  add_u_1_18b=0;
reg[17: 0]  add_v_1_18b=0;
reg[17: 0]  result_y_18b=0;
reg[17: 0]  result_u_18b=0;
reg[17: 0]  result_v_18b=0;
reg[9:0] y_tmp=0;
reg[9:0] u_tmp=0;
reg[9:0] v_tmp=0;
regi_h_sync_delay_1=0;
regi_v_sync_delay_1=0;
regi_data_en_delay_1=0;
regi_h_sync_delay_2=0;
regi_v_sync_delay_2=0;
regi_data_en_delay_2=0;
regi_h_sync_delay_3=0;
regi_v_sync_delay_3=0;
regi_data_en_delay_3=0;
regi_h_sync_delay_4=0;
regi_v_sync_delay_4=0;
regi_data_en_delay_4=0;
/*----------------一级流水-乘法--------------*/always@(posedgeclk)beginmult_r_for_y_18b<=para_0299_10b*i_r_8b;
mult_r_for_u_18b<=para_0587_10b*i_r_8b;
mult_r_for_v_18b<=para_0114_10b*i_r_8b;
endalways@(posedgeclk)beginmult_g_for_y_18b<=para_0148_10b*i_g_8b;
mult_g_for_u_18b<=para_0289_10b*i_g_8b;
mult_g_for_v_18b<=para_0437_10b*i_g_8b;
endalways@(posedgeclk)beginmult_b_for_y_18b<=para_0615_10b*i_b_8b;
mult_b_for_u_18b<=para_0515_10b*i_b_8b;
mult_b_for_v_18b<=para_0100_10b*i_b_8b;
end/*---------------二级流水-分正负项加--------------*/always@(posedgeclk)beginadd_y_0_18b<=mult_r_for_y_18b+mult_g_for_y_18b;
add_y_1_18b<=mult_b_for_y_18b;
endalways@(posedgeclk)beginadd_u_0_18b<=mult_b_for_u_18b ;//+add_u_1_18b<=mult_r_for_u_18b+mult_g_for_u_18b;//-endalways@(posedgeclk)beginadd_v_0_18b<=mult_r_for_v_18b;//+add_v_1_18b<=mult_g_for_v_18b+mult_b_for_v_18b;//-end/*---------------三级流水-求和--y+cb+cr----------*/assignsign_cb= (add_u_0_18b>=add_u_1_18b);
assignsign_cr= (add_v_0_18b>=add_v_1_18b);
/*---计算求和----*/always@(posedgeclk)beginresult_y_18b<=add_y_0_18b+add_y_1_18b;
result_u_18b<=sign_cb? (add_u_0_18b-add_u_1_18b) : 18'd0;result_v_18b<=sign_cr? (add_v_0_18b-add_v_1_18b) : 18'd0;end/*----第四级流水-进位表示---*/always@(posedgeclk)
beginy_tmp<=result_y_18b[17:8] + {9'd0,result_y_18b[7]};u_tmp<=result_u_18b[17:8] + {9'd0,result_u_18b[7]};v_tmp<=result_v_18b[17:8] + {9'd0,result_v_18b[7]};end/*----输出----*/assigno_y_8b= (y_tmp[9:8] ==2'b00) ? y_tmp[7 : 0] : 8'hFF;
assigno_u_8b= (u_tmp[9:8] ==2'b00) ? u_tmp[7 : 0] : 8'hFF;
assigno_v_8b= (v_tmp[9:8] ==2'b00) ? v_tmp[7 : 0] : 8'hFF;
/***************************************timing***********************************************/always@ (posedgeclk)
begini_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;
i_h_sync_delay_4<=i_h_sync_delay_2;
i_v_sync_delay_4<=i_v_sync_delay_2;
i_data_en_delay_4<=i_data_en_delay_2;
end//--------------------------------------//timing//--------------------------------------assigno_h_sync=i_h_sync_delay_4;
assigno_v_sync=i_v_sync_delay_4;
assigno_data_en=i_data_en_delay_4;
endmodule

这里给出了四级流水线的操作,当然你也可以,直接进行一个式子的运算,这样的坏处是,在该段的延时较高,导致数据传输的时候的数据的锁存的时间可能会有变化,运算的效率不高。

//输出  解释:

判断条件:(y_tmp[9:8] == 2'b00)的解释

这里是把我们自己规定的两个正负值进行相加后,在最后一位进行想向上取整的运算,在最高位显示其进位的状态,所以是用两位进行判断。

下面是ycbcr转换

/*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;第四级流水线计算进位仿真通过*/`timescale1ns/1psmodulergb_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*******************************************///multiply256parameterpara_0183_10b=10'd47;    //0.183 定点数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;
regi_h_sync_delay_4;
regi_v_sync_delay_4;
regi_data_en_delay_4;
/********************************************************************************************//***************************************initial**********************************************/initialbeginmult_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*******************************************///LV1pipeline : multalways@ (posedgeclk)
beginmult_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;
endalways@ (posedgeclk)
beginmult_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;
endalways@ (posedgeclk)
beginmult_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//LV2pipeline : addalways@ (posedgeclk)
beginadd_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//LV3pipeline : y+cb+crassignsign_cb= (add_cb_0_18b>=add_cb_1_18b);
assignsign_cr= (add_cr_0_18b>=add_cr_1_18b);
always@ (posedgeclk)
beginresult_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;endalways@ (posedgeclk)
beginy_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//outputassigno_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)
begini_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;
i_h_sync_delay_4<=i_h_sync_delay_2;
i_v_sync_delay_4<=i_v_sync_delay_2;
i_data_en_delay_4<=i_data_en_delay_2;
end//--------------------------------------//timing//--------------------------------------assigno_h_sync=i_h_sync_delay_4;
assigno_v_sync=i_v_sync_delay_4;
assigno_data_en=i_data_en_delay_4;
/********************************************************************************************/endmodule
目录
相关文章
|
3月前
|
算法 计算机视觉 异构计算
基于FPGA的图像RGB转HSV实现,包含testbench和MATLAB辅助验证程序
基于FPGA的图像RGB转HSV实现,包含testbench和MATLAB辅助验证程序
|
5月前
|
机器学习/深度学习 算法 计算机视觉
基于FPGA的RGB图像转化为灰度图实现,通过MATLAB进行辅助验证
基于FPGA的RGB图像转化为灰度图实现,通过MATLAB进行辅助验证
|
2月前
|
算法 异构计算
基于FPGA的图像RGB转CIE-Lab实现,包含testbench和MATLAB辅助验证程序
基于FPGA的图像RGB转CIE-Lab实现,包含testbench和MATLAB辅助验证程序
|
3月前
|
数据采集 算法 异构计算
基于FPGA的图像RGB转CMYK实现,包含testbench和MATLAB辅助验证程序
基于FPGA的图像RGB转CMYK实现,包含testbench和MATLAB辅助验证程序
基于FPGA的图像RGB转CMYK实现,包含testbench和MATLAB辅助验证程序
|
3月前
|
算法 计算机视觉 异构计算
基于FPGA的图像RGB转HLS实现,包含testbench和MATLAB辅助验证程序
基于FPGA的图像RGB转HLS实现,包含testbench和MATLAB辅助验证程序
|
24天前
|
存储 算法 异构计算
基于FPGA的RGB图像转Ycbcr实现,包括tb测试文件以及MATLAB辅助验证
基于FPGA的RGB图像转Ycbcr实现,包括tb测试文件以及MATLAB辅助验证
|
7月前
|
机器学习/深度学习 算法 C语言
FPGA图像处理之边缘检测算法的实现
边缘检测是图像处理和计算机视觉中的基本问题,边缘检测的目的是标识数字图像中亮度变化明显的点。图像属性中的显著变化通常反映了属性的重要事件和变化。这些包括(i)深度上的不连续、(ii)表面方向不连续、(iii)物质属性变化和(iv)场景照明变化。边缘检测是图像处理和计算机视觉中,尤其是特征提取中的一个研究领域。
FPGA图像处理之边缘检测算法的实现
|
7月前
|
算法 计算机视觉 异构计算
FPGA图像处理之rgbtogray算法的实现
Ycbcrr或Y'CbCr有的时候会被写作:YCBCR或是Y'CBCR,是色彩空间的一种,通常会用于影片中的影像连续处理,或是数字摄影系统中。Y'为颜色的亮度(luma)成分、而CB和CR则为蓝色和红色的浓度偏移量成份。Y'和Y是不同的,而Y就是所谓的流明(luminance),表示光的浓度且为非线性,使用伽马修正(gamma correction)编码处理。
|
7月前
|
算法 计算机视觉 异构计算
FPGA图像处理(高斯滤波)仿真篇
高斯滤波是一种低通平滑滤波,常用于模糊处理和减少噪声信号,其中模糊处理常用于预处理,即在提取目标之前去除图像中的一些细节等,这有利于高通处理。对于二维的数字图像信号,一般通过线性滤波器和非线性滤波器的模糊处理来减少强噪声信号。平滑滤波器就是用滤波掩模确定的邻域内的像素与加权值相卷积后得到的灰度均值来代替每个像素的值,这就很容易使用硬件实现。 GAUSS 滤波算法克服了边界效应,因而滤波后的图像较好。
|
11月前
|
分布式计算 算法 异构计算
m基于FPGA的RGB转ycrcb颜色空间转换算法实现,包含testbench,对比三种转换方法
m基于FPGA的RGB转ycrcb颜色空间转换算法实现,包含testbench,对比三种转换方法
161 1

热门文章

最新文章