YUV YCbCr解码设计
0赞YUV YCbCr解码设计
视频信号为YUV信号,同时,目前CMOS摄像头支持YUV信号和RGB565两种模式。只玩过RGB565,未免不太爽,不仅仅因为YUV是视频信号,而且,YUV对RGB很好的压缩。
对于视频信号而言,还存在帧头帧尾,FF0000XY。因为传统的电视是隔行扫描的,通过此序列的采样,能够有效地捕获信号。CMOS OV7670YUV下输出的帧头帧尾如下图所示:
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 。
如上图所示,标准的视频的YUV信号,以Cb0 Y0 Cr0 Y1 Cb1 Y2 Cr1 Y3………当然通过合并8bit到16bit(为了存储,16bit)后,数据变成了{Cb0Y0} {Cr0Y1} {Cb1Y2} {Cr1Y3}………
某公司的解码代码如上所示,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
状态机如下所示:
经过实验,OV7670---YCbCr422解码---YCbCr444--RGB565---VGA显示效果不错,验证了解码代码的准确性。