最后输出的DATA信号进入下一级单元,即YUV到RGB的转换。
2.3 颜色-空间转换部分设计[5]
为什么要有这个转换呢?因为不论是电视机还是CRT显示器,都是使用RGB三基色合成的方法来显示颜色。用RGB三基色来表示彩色的确很直观,但是如果把这种方法用作图像传输则绝不是一个好方法。主要是因为:
(1) 与黑白图像不兼容;
(2) 占用太多带宽;
(3) 抗干扰能力差。
本系统图像传感器输出YCbCr信号,需要进行到RGB信号的转换,用于CRT显示。YCbCr 到RGB按照下面公式进行转换:
R = 1.164 ( Y-16 ) + 1.596 ( Cr-128 );
G = 1.164 ( Y-16 )- 0.813 ( Cr-128 ) - 0.392(Cb-128);
B = 1.164 ( Y-16 ) + 2.017 ( Cb-128 );
观察上面公式可以发现,转换均需要乘加运算,并且式子中用到了小数,所以必须要对系数进行放大。经过合理转化,公式如下:
R = (1/256) * ( 298*Y + 409*Cr - 57065 );
G = (1/256) * ( 298*Y - 100*Cb - 208*Cr + 34718 );
B = (1/256) * ( 298*Y + 516*Cb - 70861 );
用Verilog HDL编写代码,实现YUV到RGB的转化。其中共包括3个模块跟1个仿真激励。在模块const_mult中,主要实现乘法运算,主要代码如下:
module const_mult (CLOCk, ClockEnable, Reset, Color, Color_Out);
parameter IN_SIZE = 8;
parameter OUT_SIZE = 16; // output size width (integer)
parameter CST_MULT = 66; // constant multipliCANd (integer)
........
always @(posedge Clock or posedge Reset)
begin : COLOR_KCM
if (Reset)
Color_Out <= 0;
else if (ClockEnable)
Color_Out <= CST_MULT * Color;
end
endmodule
模块csc.v中,调用const_mult模块,通过参数传递改变参数IN_SIZE, OUT_SIZE, CST_MULT的值,然后实现加法运算。
以R = (1/256) * ( 298*Y + 409*Cr - 57065 )为例,主要代码如下:
const_mult #(8, 18, 298) R_KCM_Y(.Clock(Clock), .ClockEnable(ClockEnable), .Reset(Reset), .Color(Y),.Color_Out(R_Y_KCM));
const_mult #(8, 18, 0 ) R_KCM_Cb(.Clock(Clock), .ClockEnable(ClockEnable), .Reset(Reset), .Color(Cb),.Color_Out(R_Cb_KCM));
const_mult #(8, 18, 409) R_KCM_Cr(.Clock(Clock), .ClockEnable(ClockEnable), .Reset(Reset), .Color(Cr),.Color_Out(R_Cr_KCM));
// Adder for (Cr + constant)
always @(posedge Clock or posedge Reset)
begin : R_Cr_C_Adder
if (Reset)
R_Cr_C <= 0;
else if (ClockEnable)
R_Cr_C <= R_Cr_KCM - 57065;
end
// Adder for (Y + Cb)
always @(posedge Clock or posedge Reset)
begin : R_Y_Cb_Adder
if (Reset)
R_Y_Cb <= 0;
else if (ClockEnable)
R_Y_Cb <= R_Y_KCM + R_Cb_KCM;
end
// Adder for R => Y + Cb + constant
always @(posedge Clock or posedge Reset)
begin : R_Adder
if (Reset)
R_full <= 0;
else if (ClockEnable)
R_full <= R_Y_Cb + R_Cr_C;
End
用以实现G、B的代码与上面类似,在此不再赘述。以下代码实现R_full*1/256功能。
always @(R_full or G_full or B_full)
begin
if(R_full[17]) R = 0;
else if(R_full[16]) R = 255;
else R = R_full [15:8];
……
end