前一篇已经介绍了Zedboard上面搭建图像采集系统的硬件结构,这一篇主要介绍Zynq内部Fpga部分系统设计
下面是在本工程的系统框图
图像采集
OV7725是一款CMOS图像传感器,VGA分辨率,帧率60fps,SCCB协议,与I2C协议通用。这里用HDL编写一个I2C 模块,对ov7725进行初始化,i2c模块是直接采用的crazybingo的设计,这里不再赘述,只是列出ov7725寄存器初始化列表,让其输出Bayer RGB图像数据
- 0 : LUT_DATA = {8'h1C, 8'h7F}; //Manufacturer ID Byte - High (Read only)
- 1 : LUT_DATA = {8'h1D, 8'hA2}; //Manufacturer ID Byte - Low (Read only)
- //Write Data Index
- 2 : LUT_DATA = {8'h12, 8'h80}; // BIT[7]-Reset all the Reg
- 3 : LUT_DATA = {8'h3d, 8'h03}; //DC offset for analog process
- 4 : LUT_DATA = {8'h15, 8'h02}; //COM10: href/vsync/pclk/data reverse(Vsync H valid)
- 5 : LUT_DATA = {8'h17, 8'h22}; //VGA: 8'h22; QVGA: 8'h3f;
- 6 : LUT_DATA = {8'h18, 8'ha4}; //VGA: 8'ha4; QVGA: 8'h50;
- 7 : LUT_DATA = {8'h19, 8'h07}; //VGA: 8'h07; QVGA: 8'h03;
- 8 : LUT_DATA = {8'h1a, 8'hf0}; //VGA: 8'hf0; QVGA: 8'h78;
- 9 : LUT_DATA = {8'h32, 8'h00}; //Bit[7]:Mirror image edge alignment
- 10 : LUT_DATA = {8'h29, 8'hA0}; //VGA: 8'hA0; QVGA: 8'hF0
- 11 : LUT_DATA = {8'h2C, 8'hF0}; //VGA: 8'hF0; QVGA: 8'h78
- 12 : LUT_DATA = {8'h0d, 8'h41}; //Bypass PLL
- 13 : LUT_DATA = {8'h11, 8'h01}; //CLKRC,Finternal clock = Finput clk*PLL multiplier/[(CLKRC[5:0]+1)*2] = 25MHz*4/[(x+1)*2]
- //00: 50fps, 01:25fps, 03:12.5fps (50Hz Fliter)
- 14 : LUT_DATA = {8'h12, 8'h03}; //BIT[6]: 0:VGA; 1;QVGA
- //BIT[3:2]: 01:RGB565
- //VGA: 00:YUV; 01:Processed Bayer RGB; 10:RGB; 11:Bayer RAW; BIT[7]-Reset all the Reg
- 15 : LUT_DATA = {8'h0c, 8'h90}; //COM3: Bit[6]:Horizontal mirror image ON/OFF, Bit[0]:Color bar; Default:8'h10
- //DSP control
- 16 : LUT_DATA = {8'h42, 8'h7f}; //BLC Blue Channel Target Value, Default: 8'h80
- 17 : LUT_DATA = {8'h4d, 8'h09}; //BLC Red Channel Target Value, Default: 8'h80
- 18 : LUT_DATA = {8'h63, 8'hf0}; //AWB Control
- 19 : LUT_DATA = {8'h64, 8'hff}; //DSP_Ctrl1:
- 20 : LUT_DATA = {8'h65, 8'h00}; //DSP_Ctrl2:
- 21 : LUT_DATA = {8'h66, 8'h00}; //{COM3[4](0x0C), DSP_Ctrl3[7]}:00:YUYV; 01:YVYU; [10:UYVY] 11:VYUY
- 22 : LUT_DATA = {8'h67, 8'h02}; //DSP_Ctrl4:[1:0]00/01: YUV or RGB; 10: RAW8; 11: RAW10
- //AGC AEC AWB
- 23 : LUT_DATA = {8'h13, 8'hff};
- 24 : LUT_DATA = {8'h0f, 8'hc5};
- 25 : LUT_DATA = {8'h14, 8'h11};
- 26 : LUT_DATA = {8'h22, 8'h98}; //Banding Filt er Minimum AEC Value; Default: 8'h09
- 27 : LUT_DATA = {8'h23, 8'h03}; //Banding Filter Maximum Step
- 28 : LUT_DATA = {8'h24, 8'h40}; //AGC/AEC - Stable Operating Region (Upper Limit)
- 29 : LUT_DATA = {8'h25, 8'h30}; //AGC/AEC - Stable Operating Region (Lower Limit)
- 30 : LUT_DATA = {8'h26, 8'ha1}; //AGC/AEC Fast Mode Operating Region
- 31 : LUT_DATA = {8'h2b, 8'h9e}; //*: 8'h00:60Hz Filter; Mainland: 8'h9e:50Hz Filter
- 32 : LUT_DATA = {8'h6b, 8'haa}; //AWB Control 3
- 33 : LUT_DATA = {8'h13, 8'hff}; //8'hff: AGC AEC AWB Enable; 8'hf0: AGC AEC AWB Disable;
- //matrix sharpness brightness contrast UV
- 34 : LUT_DATA = {8'h90, 8'h0a};
- 35 : LUT_DATA = {8'h91, 8'h01};
- 36 : LUT_DATA = {8'h92, 8'h01};
- 37 : LUT_DATA = {8'h93, 8'h01};
- 38 : LUT_DATA = {8'h94, 8'h5f};
- 39 : LUT_DATA = {8'h95, 8'h53};
- 40 : LUT_DATA = {8'h96, 8'h11};
- 41 : LUT_DATA = {8'h97, 8'h1a};
- 42 : LUT_DATA = {8'h98, 8'h3d};
- 43 : LUT_DATA = {8'h99, 8'h5a};
- 44 : LUT_DATA = {8'h9a, 8'h1e};
- 45 : LUT_DATA = {8'h9b, 8'h3f}; //Brightness
- 46 : LUT_DATA = {8'h9c, 8'h25};
- 47 : LUT_DATA = {8'h9e, 8'h81};
- 48 : LUT_DATA = {8'ha6, 8'h06};
- 49 : LUT_DATA = {8'ha7, 8'h65};
- 50 : LUT_DATA = {8'ha8, 8'h65};
- 51 : LUT_DATA = {8'ha9, 8'h80};
- 52 : LUT_DATA = {8'haa, 8'h80};
- //Gamma correction
- 53 : LUT_DATA = {8'h7e, 8'h0c};
- 54 : LUT_DATA = {8'h7f, 8'h16}; //
- 55 : LUT_DATA = {8'h80, 8'h2a};
- 56 : LUT_DATA = {8'h81, 8'h4e};
- 57 : LUT_DATA = {8'h82, 8'h61};
- 58 : LUT_DATA = {8'h83, 8'h6f};
- 59 : LUT_DATA = {8'h84, 8'h7b};
- 60 : LUT_DATA = {8'h85, 8'h86};
- 61 : LUT_DATA = {8'h86, 8'h8e};
- 62 : LUT_DATA = {8'h87, 8'h97};
- 63 : LUT_DATA = {8'h88, 8'ha4};
- 64 : LUT_DATA = {8'h89, 8'haf};
- 65 : LUT_DATA = {8'h8a, 8'hc5};
- 66 : LUT_DATA = {8'h8b, 8'hd7};
- 67 : LUT_DATA = {8'h8c, 8'he8};
- 68 : LUT_DATA = {8'h8d, 8'h20};
- //Others
- 69 : LUT_DATA = {8'h0e, 8'h65};//night mode auto frame rate control
Bayer8转RGB888
ov7725图像传感器可以输出rgb565,yuv格式的图像数据,但这里用到的是RAW格式图像数据。配置好ov7725以后,摄像头传回raw格式图像数据,每个像素8bit,Bayer像素排列如下
像素总数的一半是G分量,四分之一是R,四分之一是B,这是因为人眼对绿色分量最为敏感,所以G分量占的比重大。将Bayer raw图像转换为RGB图像,最简单的办法就是使用插值法,插值法就是使用周围邻域像素来恢复自身像素值的办法,本设计采用3X3窗口来做双线性插值,举例说明,对于像素点G22,绿色分量就等于自身像素值,红色分量
R22 = (R12 + R32) / 2 蓝色分量 B22 = (B21 + B23) / 2 以此类推
线性插值法简单,而且适合FPGA上面流水线操作,但是也有比较严重的弊端,那就是色彩的恢复没有考虑到各个颜色分量之间的相关性,容易产生伪彩色,同时在图像纹理比较丰富的地方,容易造成图像轮廓失真。
在FPGA上面实现双线性插值法,要对图像进行3行的缓存,这是FPGA图像处理比较基本的东西,也不再多说,只是提一下这件事,一些人在使用Altera FPGA的时候,quartus提供这样一个IP
实际上就是多维的移位寄存器,但是在xilinx的ip中并没有这个ip,只有一维的ram based shift register,不过不要紧,只要将多个一维移位寄存器串接起来就可以实现相同的功能了,当然也可以使用sysgen或者hls自己做一个(个人想法,没有实现过)
做好移位寄存器,就可以生成3X3矩阵,然后线性插值将RAW8转换为RGB888了,具体过程可以参见我的工程:
http://download.csdn.net/detail/zhangyu_eeprom/7726541