CrazyBingo

YUV YCbCr解码设计

0
阅读(5829)

YUV YCbCr解码设计

视频信号为YUV信号,同时,目前CMOS摄像头支持YUV信号和RGB565两种模式。只玩过RGB565,未免不太爽,不仅仅因为YUV是视频信号,而且,YUV对RGB很好的压缩。

wps_clip_image-28561

对于视频信号而言,还存在帧头帧尾,FF0000XY。因为传统的电视是隔行扫描的,通过此序列的采样,能够有效地捕获信号。CMOS OV7670YUV下输出的帧头帧尾如下图所示:

wps_clip_image-5246

wps_clip_image-15931

YUV

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

YUV有很多格式,比如4:2:2; 4:2:2; 4:2:0等,一般摄像头YUV422格式的数据模式。

YUV422模式即水平方向上UV的采样速度为Y的一半,相当于每两个点采样一个U,V,每一个点采样一个Y。这样被允许的原因是因为,我们的眼睛对亮度的敏感度远大于对色度的敏感度,因此可以通过牺牲色度的采样率来达到图像数据压缩的目的。

当年的黑白电视,只有亮度,即Y;YUV格式的出现很好的兼容了不同制式的电视,因为YUV2RGB可以转换为彩色图像,这个YCbCr中讲过了。

当然以上不是我主要要讲的,这里,以OV7670视频数据为例,捕获YUV信号的捕获,最大限度的保持数据的同步,并且使得数据不丢失,设计了时序,请听Bingo一一道来:

首先,对于视频而言,所谓YUV信号就是YCbCr信号,想知道更多的孩纸请看http://www.fdworkshop.me/read.php?tid=37

wps_clip_image-18602

如上图所示,标准的视频的YUV信号,以Cb0 Y0 Cr0 Y1 Cb1 Y2 Cr1 Y3………当然通过合并8bit到16bit(为了存储,16bit)后,数据变成了{Cb0Y0} {Cr0Y1} {Cb1Y2} {Cr1Y3}………

wps_clip_image-24276

某公司的解码代码如上所示,CbCr与对应的Y肯定错位了,只是肉眼看不到。但是,既然我们知道问题,我们也能改进,为什么不严谨一点呢??

由于时序的严格,为了有效的解码,可以通过如下步骤

(1)捕获Cb0,Y0

(2)捕获Cr0,Y1

(3)捕获Cb1,Y2,输出Y0Cb0Cr0

(4)捕获Cr1,Y3,输出Y1Cb0Cr0

相关代码如下所示:

 

//convert yuv422 to yuv444
reg	[2:0]	yuv_state;
reg	[7:0]	mY0, mY1, mY2, mY3;
reg	[7:0]	mCb0, mCb1;
reg	[7:0]	mCr0, mCr1;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		begin
		yuv_state <= 3'd0;
		{mY0, mCb0, mCr0} <= {8'h0, 8'h0, 8'h0};
		mY1 <= 8'h0;
		{mY2, mCb1, mCr1} <= {8'h0, 8'h0, 8'h0};
		mY3	<= 8'h0;
		{Y, Cb,Cr} <= {8'h0, 8'h0, 8'h0};
		end
	else if(yuv_capture_en)	//ahead 2 clock
		begin
		case(yuv_state)		//{Cb,Y},{Cr,Y}---YCbCr
		3'd0:	begin	yuv_state <= 3'd1;	{mCb0, mY0} <= image_data;	end		//reg p0
		3'd1:	begin	yuv_state <= 3'd2;	{mCr0, mY1} <= image_data;	end		//reg p1
		
		3'd2:	begin	yuv_state <= 3'd3;	{mCb1, mY2} <= image_data;	{Y, Cb, Cr} <= {mY0, mCb0, mCr0};	end	//p0;	reg p2
		3'd3:	begin	yuv_state <= 3'd4;	{mCr1, mY3} <= image_data;	{Y, Cb, Cr} <= {mY1, mCb0, mCr0};	end	//p1;	reg p3
		3'd4:	begin	yuv_state <= 3'd5;	{mCb0, mY0} <= image_data;	{Y, Cb, Cr} <= {mY2, mCb1, mCr1};	end	//p2;	reg	p0
		3'd5:	begin	yuv_state <= 3'd2;	{mCr0, mY1} <= image_data;	{Y, Cb, Cr} <= {mY3, mCb1, mCr1};	end	//p3;	reg p1
		endcase
		end
	else
		begin
		yuv_state <= 3'd0;
		{mY0, mCb0, mCr0} <= {8'h0, 8'h0, 8'h0};
		{mY1, mCb1, mCr1} <= {8'h0, 8'h0, 8'h0};
		{Y, Cb,Cr} <= {8'h0, 8'h0, 8'h0};
		end
end

状态机如下所示:

wps_clip_image-22179

 

经过实验,OV7670---YCbCr422解码---YCbCr444--RGB565---VGA显示效果不错,验证了解码代码的准确性。