CrazyBingo

YCbCr 转 RGB算法

0
阅读(31872)

wps_clip_image-21606

YUV422_YUV444

wps_clip_image-15972

http://www.cnblogs.com/crazybingo/archive/2012/06/07/2540595.html

http://www.fdworkshop.me/read.php?tid=37

YUV

Y:亮度(16-235) U:色彩 V:饱和度

YCbCr

Y:亮度(16-235) Cb:色度(16-240)(B-Y) Cr:色度(16-240)(R-Y)

YUV2RGB(gamma校正)

YUV

Y:亮度(16-235) U:色彩 V:饱和度

1) RGB转YUV

Y= 0.299R + 0.587G + 0.114B

U= -0.147R - 0.289G + 0.436B = 0.492(B- Y)

V= 0.615R - 0.515G - 0.100B = 0.877(R- Y)

2) YUV转RGB

R = Y + 1.140V

G = Y - 0.394U - 0.581V

B = Y + 2.032U

R = (Y*512 + V*584)>>9

G = (Y*512 - U*202 - V*297)>>9

B = (Y*512 + U*1040)>>9

RGB2YCbCr(视频系统 ITU-RBT.656)(gamma校正)

YCbCr

Y:亮度(16-235) Cb:色度(16-240)(B-Y) Cr:色度(16-240)(R-Y)

(1)不适合使用在计算机中16-235

wps_clip_image-8894

R = Y + 1.371(Cr-128)

G = Y - 0.698(Cr-128) - 0.336(Cb-128)

B = Y + 1.732(Cb-128)

=>*512

XOUT = Y*512 + 702(Cr-128)

YOUT = Y*512 + 257(Cr-128) - 172(Cb-128)

ZOUT = Y*512 + 887(Cb-128)

=>/512

R <= (XOUT[8:0] > 9'd255) ? 8'hff : XOUT[7:0];

G <= (YOUT[8:0] > 9'd255) ? 8'hff : YOUT[7:0];

B <= (ZOUT[8:0] > 9'd255) ? 8'hff : ZOUT[7:0];

(2)适用在计算机中 0-255(0V7670已设置为1-FE)

wps_clip_image-12896

YCbCr is a scaled and offset version of the YUV color space.

RGB取值0-255

1) RGB转YCbCr

Y = 0.257R + 0.504G + 0.098B + 16

Cb = -0.148R - 0.291G + 0.439B + 128

Cr = 0.439R - 0.368G - 0.071B + 128

2) YCbCr转 RGB

原式=>

R = 1.164(Y-16) + 1.596(Cr-128)

G = 1.164(Y-16) - 0.813(Cr-128) - 0.391(Cb-128)

B = 1.164(Y-16) + 2.018(Cb-128)

转换(1)=>分离变量

R = 1.164Y + 1.596Cr - 222.912
G = 1.164Y - 0.391Cb - 0.813Cr + 135.488
B = 1.164Y + 2.018Cb - 276.928

<1>方法1:转换(2)=>放大512倍(<<9)----当然也可以直接用ALTMULT_ADD(乘法器)

XOUT[19:0] = ((Y*10'd596) + (Cr*10'd817) - 18'd114131)>>9;

YOUT[19:0] = ((Y*10'd596) - (Cb*10'd200) - (Cr*10'd416) + 18'd69370)>>9;

ZOUT[19:0] = ((Y*10'd596) + (Cb*11'd1033) - 18'd141787)>>9;

<2>方法2:转换(3)=>放大512倍(<<9)----移位实现

XOUT = (((Y<<9)+(Y<<6)+(Y<<4)+(Y<<2)) + ((Cr<<9)+(Cr<<8)+(Cr<<5)+(Cr<<4)+Cr) - 18'd114131)>>9;

YOUT = (((Y<<9)+(Y<<6)+(Y<<4)+(Y<<2)) - ((Cb<<7)+(Cb<<6)+(Cb<<3)) - ((Cr<<8)+(Cr<<7)+(Cr<<5)) + 18'd69370)>>9;

ZOUT = (((Y<<9)+(Y<<6)+(Y<<4)+(Y<<2)) + ((Cb<<10)+(Cb<<3)+Cb) - 18'd141787)>>9;

最终结果:转换(4)=>缩小512倍(>>9)

R <= XOUT[19] ? 8'h0 : (XOUT[8:0] > 9'd255) ? 8'hff : XOUT[7:0];

G <= YOUT[19] ? 8'h0 : (YOUT[8:0] > 9'd255) ? 8'hff : YOUT[7:0];

B <= ZOUT[19] ? 8'h0 : (ZOUT[8:0] > 9'd255) ? 8'hff : ZOUT[7:0];

在Quartus中综合编译,发现用流水线+移位操作实现YUV2RGB(能达到80M),远比用乘法器(只能50M)速度要快,当然在一定范围内,两者都可以。最后,移位转换RTL如下所示:

wps_clip_image-8792

(当然也可以通过ROM查找表来实现,但我认为这个不适合因为浪费了很多资源,而且不适合在CPLD实现,有兴趣可以看如下论文http://www.chinaaet.com/lib/detail.aspx?id=89671)

实际经过测试,从OV7670捕获YUV数据,在转换为RGB在VGA显示,效果还好,相关代码如下所示

YCbCr2RGB verilog代码如下所示:
/*------------------------------------------------------------------------- This confidential and proprietary software may be only used as authorized by a licensing agreement from CrazyBingo.www.cnblogs.com/crazybingo (C) COPYRIGHT 2012 CrazyBingo. ALL RIGHTS RESERVED Filename : yuv444_rgb888 Author : CrazyBingo Data : 2012-06-6 Version : 1.0 Description : I2C Configure Data of OV7670. Modification History : Data By Version Change Description =========================================================================== 12/06/06 CrazyBingo 1.0 Original --------------------------------------------------------------------------*/ `timescale 1ns/1ns module YCbCr2RGB ( input clk, input rst_n, input [7:0] Y, input [7:0] Cb, input [7:0] Cr, output reg [7:0] R, output reg [7:0] G, output reg [7:0] B ); //Way1 :shift //wire [19:0] XOUT = (((Y<<9)+(Y<<6)+(Y<<4)+(Y<<2)) + ((Cr<<9)+(Cr<<8)+(Cr<<5)+(Cr<<4)+Cr) - 18'd114131)>>9; //wire [19:0] YOUT = (((Y<<9)+(Y<<6)+(Y<<4)+(Y<<2)) - ((Cb<<7)+(Cb<<6)+(Cb<<3)) - ((Cr<<8)+(Cr<<7)+(Cr<<5)) + 18'd69370)>>9; //wire [19:0] ZOUT = (((Y<<9)+(Y<<6)+(Y<<4)+(Y<<2)) + ((Cb<<10)+(Cb<<3)+Cb) - 18'd141787)>>9; //Ways2 : mult //wire [19:0] XOUT = ((Y*10'd596) + (Cr*10'd817) - 18'd114131)>>9; //wire [19:0] YOUT = ((Y*10'd596) - (Cr*10'd416) - (Cb*10'd200) + 18'd69370)>>9; //wire [19:0] ZOUT = ((Y*10'd596) + (Cb*11'd1033) - 18'd141787)>>9; //------------------------------------------- //流水线1:计算XOUT通道每个Y Cb Cr数据,加速 reg [19:0] mY; reg [19:0] mCr1; reg [19:0] mCb2; reg [19:0] mCr2; reg [19:0] mCb3; always@(posedge clk or negedge rst_n) begin if(!rst_n) begin mY <= 0; mCr1 <= 0; mCb2 <= 0; mCr2 <= 0; mCb3 <= 0; end else begin mY <= (Y<<9)+(Y<<6)+(Y<<4)+(Y<<2); mCr1 <= (Cr<<9)+(Cr<<8)+(Cr<<5)+(Cr<<4)+Cr; mCb2 <= (Cb<<7)+(Cb<<6)+(Cb<<3); mCr2 <= (Cr<<8)+(Cr<<7)+(Cr<<5); mCb3 <= (Cb<<10)+(Cb<<3)+Cb; end end //------------------------------------------- //流水线2:计算XOUT通道结果,加速 reg [19:0] XOUT; reg [19:0] YOUT; reg [19:0] ZOUT; always@(posedge clk or negedge rst_n) begin if(!rst_n) begin XOUT <= 0; YOUT <= 0; ZOUT <= 0; end else begin XOUT <= (mY + mCr1 - 18'd114131)>>9; YOUT <= (mY - mCb2 - mCr2 + 18'd69370)>>9; ZOUT <= (mY + mCb3 - 18'd141787)>>9;; end end //------------------------------------------- //流水线3:计算RGB通道结果,加速 always@(posedge clk or negedge rst_n) begin if(!rst_n) begin R <= 0; G <= 0; B <= 0; end else //when <0 ro <0 begin R <= XOUT[19] ? 8'h0 : (XOUT[8:0] > 9'd255) ? 8'hff : XOUT[7:0]; G <= YOUT[19] ? 8'h0 : (YOUT[8:0] > 9'd255) ? 8'hff : YOUT[7:0]; B <= ZOUT[19] ? 8'h0 : (ZOUT[8:0] > 9'd255) ? 8'hff : ZOUT[7:0]; end end endmodule
Baidu
map