Zedboard & Zynq 图像采集 视频开发 (二) FPGA图像采集raw转rgb888

时间:2022-04-30 18:39:49

前一篇已经介绍了Zedboard上面搭建图像采集系统的硬件结构,这一篇主要介绍Zynq内部Fpga部分系统设计

下面是在本工程的系统框图

Zedboard & Zynq 图像采集 视频开发 (二) FPGA图像采集raw转rgb888

图像采集

OV7725是一款CMOS图像传感器,VGA分辨率,帧率60fps,SCCB协议,与I2C协议通用。这里用HDL编写一个I2C 模块,对ov7725进行初始化,i2c模块是直接采用的crazybingo的设计,这里不再赘述,只是列出ov7725寄存器初始化列表,让其输出Bayer RGB图像数据
[plain]  view plain copy
  1. 0 :     LUT_DATA    =   {8'h1C, 8'h7F}; //Manufacturer ID Byte - High (Read only)  
  2. 1 :     LUT_DATA    =   {8'h1D, 8'hA2}; //Manufacturer ID Byte - Low (Read only)  
  3. //Write Data Index  
  4. 2   :   LUT_DATA    =   {8'h12, 8'h80}; // BIT[7]-Reset all the Reg   
  5. 3   :   LUT_DATA    =   {8'h3d, 8'h03}; //DC offset for analog process  
  6. 4   :   LUT_DATA    =   {8'h15, 8'h02}; //COM10: href/vsync/pclk/data reverse(Vsync H valid)  
  7. 5   :   LUT_DATA    =   {8'h17, 8'h22}; //VGA:  8'h22;  QVGA:   8'h3f;  
  8. 6   :   LUT_DATA    =   {8'h18, 8'ha4}; //VGA:  8'ha4;  QVGA:   8'h50;  
  9. 7   :   LUT_DATA    =   {8'h19, 8'h07}; //VGA:  8'h07;  QVGA:   8'h03;  
  10. 8   :   LUT_DATA    =   {8'h1a, 8'hf0}; //VGA:  8'hf0;  QVGA:   8'h78;  
  11. 9   :   LUT_DATA    =   {8'h32, 8'h00}; //Bit[7]:Mirror image edge alignment   
  12. 10  :   LUT_DATA    =   {8'h29, 8'hA0}; //VGA:  8'hA0;  QVGA:   8'hF0  
  13. 11  :   LUT_DATA    =   {8'h2C, 8'hF0}; //VGA:  8'hF0;  QVGA:   8'h78  
  14. 12  :   LUT_DATA    =   {8'h0d, 8'h41}; //Bypass PLL  
  15. 13  :   LUT_DATA    =   {8'h11, 8'h01}; //CLKRC,Finternal clock = Finput clk*PLL multiplier/[(CLKRC[5:0]+1)*2] = 25MHz*4/[(x+1)*2]  
  16.                                         //00: 50fps, 01:25fps, 03:12.5fps   (50Hz Fliter)  
  17. 14  :   LUT_DATA    =   {8'h12, 8'h03}; //BIT[6]:   0:VGA; 1;QVGA  
  18.                                         //BIT[3:2]: 01:RGB565  
  19.                                         //VGA:  00:YUV; 01:Processed Bayer RGB; 10:RGB; 11:Bayer RAW; BIT[7]-Reset all the Reg   
  20. 15  :   LUT_DATA    =   {8'h0c, 8'h90}; //COM3: Bit[6]:Horizontal mirror image ON/OFF, Bit[0]:Color bar; Default:8'h10  
  21. //DSP control  
  22. 16  :   LUT_DATA    =   {8'h42, 8'h7f}; //BLC Blue Channel Target Value, Default: 8'h80  
  23. 17  :   LUT_DATA    =   {8'h4d, 8'h09}; //BLC Red Channel Target Value, Default: 8'h80  
  24. 18  :   LUT_DATA    =   {8'h63, 8'hf0}; //AWB Control  
  25. 19  :   LUT_DATA    =   {8'h64, 8'hff}; //DSP_Ctrl1:  
  26. 20  :   LUT_DATA    =   {8'h65, 8'h00}; //DSP_Ctrl2:      
  27. 21  :   LUT_DATA    =   {8'h66, 8'h00}; //{COM3[4](0x0C), DSP_Ctrl3[7]}:00:YUYV;    01:YVYU;    [10:UYVY]   11:VYUY   
  28. 22  :   LUT_DATA    =   {8'h67, 8'h02}; //DSP_Ctrl4:[1:0]00/01: YUV or RGB; 10: RAW8; 11: RAW10   
  29.    //AGC AEC AWB  
  30. 23  :   LUT_DATA    =   {8'h13, 8'hff};  
  31. 24  :   LUT_DATA    =   {8'h0f, 8'hc5};  
  32. 25  :   LUT_DATA    =   {8'h14, 8'h11};  
  33. 26  :   LUT_DATA    =   {8'h22, 8'h98}; //Banding Filt er Minimum AEC Value; Default: 8'h09  
  34. 27  :   LUT_DATA    =   {8'h23, 8'h03}; //Banding Filter Maximum Step  
  35. 28  :   LUT_DATA    =   {8'h24, 8'h40}; //AGC/AEC - Stable Operating Region (Upper Limit)  
  36. 29  :   LUT_DATA    =   {8'h25, 8'h30}; //AGC/AEC - Stable Operating Region (Lower Limit)  
  37. 30  :   LUT_DATA    =   {8'h26, 8'ha1}; //AGC/AEC Fast Mode Operating Region  
  38. 31  :   LUT_DATA    =   {8'h2b, 8'h9e}; //*: 8'h00:60Hz Filter; Mainland: 8'h9e:50Hz Filter  
  39. 32  :   LUT_DATA    =   {8'h6b, 8'haa}; //AWB Control 3  
  40. 33  :   LUT_DATA    =   {8'h13, 8'hff}; //8'hff: AGC AEC AWB Enable; 8'hf0: AGC AEC AWB Disable;  
  41. //matrix sharpness brightness contrast UV     
  42. 34  :   LUT_DATA    =   {8'h90, 8'h0a};   
  43. 35  :   LUT_DATA    =   {8'h91, 8'h01};  
  44. 36  :   LUT_DATA    =   {8'h92, 8'h01};  
  45. 37  :   LUT_DATA    =   {8'h93, 8'h01};  
  46. 38  :   LUT_DATA    =   {8'h94, 8'h5f};  
  47. 39  :   LUT_DATA    =   {8'h95, 8'h53};  
  48. 40  :   LUT_DATA    =   {8'h96, 8'h11};  
  49. 41  :   LUT_DATA    =   {8'h97, 8'h1a};  
  50. 42  :   LUT_DATA    =   {8'h98, 8'h3d};  
  51. 43  :   LUT_DATA    =   {8'h99, 8'h5a};  
  52. 44  :   LUT_DATA    =   {8'h9a, 8'h1e};  
  53. 45  :   LUT_DATA    =   {8'h9b, 8'h3f}; //Brightness   
  54. 46  :   LUT_DATA    =   {8'h9c, 8'h25};  
  55. 47  :   LUT_DATA    =   {8'h9e, 8'h81};   
  56. 48  :   LUT_DATA    =   {8'ha6, 8'h06};  
  57. 49  :   LUT_DATA    =   {8'ha7, 8'h65};  
  58. 50  :   LUT_DATA    =   {8'ha8, 8'h65};  
  59. 51  :   LUT_DATA    =   {8'ha9, 8'h80};  
  60. 52  :   LUT_DATA    =   {8'haa, 8'h80};  
  61. //Gamma correction  
  62. 53  :   LUT_DATA    =   {8'h7e, 8'h0c};  
  63. 54  :   LUT_DATA    =   {8'h7f, 8'h16}; //  
  64. 55  :   LUT_DATA    =   {8'h80, 8'h2a};  
  65. 56  :   LUT_DATA    =   {8'h81, 8'h4e};  
  66. 57  :   LUT_DATA    =   {8'h82, 8'h61};  
  67. 58  :   LUT_DATA    =   {8'h83, 8'h6f};  
  68. 59  :   LUT_DATA    =   {8'h84, 8'h7b};  
  69. 60  :   LUT_DATA    =   {8'h85, 8'h86};  
  70. 61  :   LUT_DATA    =   {8'h86, 8'h8e};  
  71. 62  :   LUT_DATA    =   {8'h87, 8'h97};  
  72. 63  :   LUT_DATA    =   {8'h88, 8'ha4};  
  73. 64  :   LUT_DATA    =   {8'h89, 8'haf};  
  74. 65  :   LUT_DATA    =   {8'h8a, 8'hc5};  
  75. 66  :   LUT_DATA    =   {8'h8b, 8'hd7};  
  76. 67  :   LUT_DATA    =   {8'h8c, 8'he8};  
  77. 68  :   LUT_DATA    =   {8'h8d, 8'h20};  
  78. //Others  
  79. 69  :   LUT_DATA    =   {8'h0e, 8'h65};//night mode auto frame rate control  

Bayer8转RGB888

ov7725图像传感器可以输出rgb565,yuv格式的图像数据,但这里用到的是RAW格式图像数据。配置好ov7725以后,摄像头传回raw格式图像数据,每个像素8bit,Bayer像素排列如下
Zedboard & Zynq 图像采集 视频开发 (二) FPGA图像采集raw转rgb888
像素总数的一半是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
Zedboard & Zynq 图像采集 视频开发 (二) FPGA图像采集raw转rgb888
实际上就是多维的移位寄存器,但是在xilinx的ip中并没有这个ip,只有一维的ram based shift register,不过不要紧,只要将多个一维移位寄存器串接起来就可以实现相同的功能了,当然也可以使用sysgen或者hls自己做一个(个人想法,没有实现过)
做好移位寄存器,就可以生成3X3矩阵,然后线性插值将RAW8转换为RGB888了,具体过程可以参见我的工程:
http://download.csdn.net/detail/zhangyu_eeprom/7726541