zoukankan      html  css  js  c++  java
  • 彩色MT9V034摄像头 Bayer转rgb FPGA实现

    1 图像bayer格式介绍

      bayer格式是伊士曼·柯达公司科学家Bryce Bayer发明的,Bryce Bayer所发明的拜耳阵列被广泛运用数字图像。Bayer格式是相机内部的原始数据, 一般后缀名为.raw。

      对于彩色图像,一般是三原色数据,rgb格式。但是摄像头一个像素点只有rgb中一种数据(下图为bayer色彩滤波阵列)。但是有很多摄像头直接输出rgb和yuv格式,如ov5640、ov7725等等,这是因为在Sensor模组的内部会有一个ISP模块,会将 Sensor采集到的数据进行插值和特效处理,所以直接输出彩色图像。但不是所有的摄像头都集成ISP,而直接输出Bayer数据,这就需要自己写Bayer转rgb算法。

    2 MT9V034简单介绍

       做图像处理的朋友都知道,MT9V034是一款十分出色的做机器视觉的摄像头,一般都是灰度的。但是也有彩色款,当时我觉得灰度的效果那么好,一时头热就买一个彩色款的。mt9v034用起来很方便,可以不用寄存器配置,上电默认752*480分辨率。根据需求也可以iic配置。

      全局快门(相对滚动快门) 拍摄高速物体的效果:

      高动态效果:

    3 MT9V034 datasheet 简单解析

      1)有效图像 752x480

        最大时钟为27Mhz

        最大帧率为60fps

        10位的adc(我的是八位的输出,店家只将高8位引出,有点影响最后图像的精度)

       2)这是mt9v034Bayer阵列,注意输出方向,从左到右,从上到下。

       3)摄像头ID号要根据 S_CTRL_ADR1, S_CTRL_ADR0这两个引脚咋连接的

      4)下图是摄像头原理图,很明显S_CTRL_ADR1, S_CTRL_ADR0是被拉低了,所以摄像头ID为0x90.上面说到摄像头只有高8位被引出,在这里可以证实了。

      5)下面是大部分寄存器,mt9v034可配置的寄存器很少。0x00是芯片版本。03、04是摄像头分辨率

     

      6)datasheet就介绍到这里,更多信息可以自己去阅读。

     4 Bayer转rgb算法解析

    我是用shift register ip 缓存两行数据,形成2*2窗口(这是FPGA做图像算法最常用的方法和ip),不是很会的朋友可以百度搜一搜,有很多博客可以学习,一定要自己仿真一下,搞明白,这有点难理解。

    根据窗口移动,不难发现,总结出一条重要的规律:总共只有四种窗口,而且与行和列的奇偶有关。

    假设计数器从零开始记数:

    第一种{行偶,列偶}

     第二种{行偶,列奇}

     第三种{行奇,列偶}

    第四种{行奇,列奇}

    5 算法实现

    首先说明我是用xilinx的zynq fpga,altera的也有类似的ip。我直接说明一下ip 参数修改,其他的怎么添加ip什么的我就不讲了,不会的自己百度学习。

      1)这是ip首页,蓝框自定义ip名,修改一下红框的参数,我们是8位数据,一行数据为640个。clock enable端与sclr端可以根据自己的要求决定勾不勾选。其他默认就行,点击ok可以了。

       2)vivado也提供端口例化模板,如下图操作就行,

     

      3)源码

        用两个shift register ip形成2*2的窗口,代码就不具体解说了,自己仿真一下结合源码理解吧。

    `timescale 1ns / 1ps
    //////////////////////////////////////////////////////////////////////////////////
    // Company: 
    // Engineer: 
    // 
    // Create Date: 2019/02/04 10:29:56
    // Design Name: colour MT98V034 bayer2rgb
    // Module Name: MT_bayer2rgb
    // Project Name: Colour_MT_bayer2rgb
    // Target Devices: ZYNQ7020
    // Tool Versions: vivado2018.3
    // Description: 
    // 
    // Dependencies: 
    // 
    // Revision:
    // Revision 0.01 - File Created
    // Additional Comments:
    // 
    //////////////////////////////////////////////////////////////////////////////////
    
    
    module MT_bayer2rgb(
        //system singal
        input                        s_rst_n            ,
        //cmos simgals
        input                        vsync_i            ,
        input                        hsync_i            ,
        input                        pclk            ,
        input            [7:0]        bayer_data        ,
        //输出
        output                        vsync_o            ,
        output                        hsync_o            ,
        output            [23:0]        rgb_data        
        );
    
    //========================================================================\
    // =========== Define Parameter and Internal signals =========== 
    //========================================================================/
    
    reg             [9:0]        col_cnt            ;
    reg             [8:0]        row_cnt            ;
    
    reg                         hsync_i_1        ;
    reg                         hsync_i_2        ;
    reg                         hsync_i_3        ;
    
    reg                         vsync_i_1        ;
    reg                         vsync_i_2        ;
    reg                         vsync_i_3        ;
    
    wire             [7:0]        line_1            ;
    wire             [7:0]        line_2            ;
    reg                [2:0]        data_control    ;
    
    reg             [7:0]        line1_1            ;    
    reg             [7:0]        line1_2            ;    
    
    reg             [7:0]        line2_1            ;    
    reg             [7:0]        line2_2            ;    
    
    
    reg             [7:0]        rgb_r            ;
    reg             [8:0]        rgb_g            ;
    reg             [7:0]        rgb_b            ;
    //=============================================================================
    //****************************     Main Code    *******************************
    //=============================================================================
    
    //列计数
    always @ (negedge pclk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0)
            col_cnt <= 10'd0;
        else if (hsync_i_3 == 1'b1 && hsync_i_2 == 1'b1)
            col_cnt <= col_cnt + 1'b1;    
        else    
            col_cnt <= 10'd0;
    end
    
    always @ (posedge pclk or negedge s_rst_n) begin 
        if(s_rst_n == 1'b0) begin
            hsync_i_1 <= 1'b0;
            hsync_i_2 <= 1'b0;
            hsync_i_3 <= 1'b0;
        end
        else begin
            hsync_i_1 <= hsync_i;
            hsync_i_2 <= hsync_i_1;
            hsync_i_3 <= hsync_i_2;
        end
    end
    
    
    always @ (posedge pclk or negedge s_rst_n) begin 
         if(s_rst_n == 1'b0) begin
            vsync_i_1 <= 1'b0;
            vsync_i_2 <= 1'b0;
            vsync_i_3 <= 1'b0;
        end
        else begin
            vsync_i_1 <= vsync_i;
            vsync_i_2 <= vsync_i_1;
            vsync_i_3 <= vsync_i_2;
        end
    end
    
    //行计数
    always @ (posedge pclk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0)
            row_cnt <= 9'd0;
        else if(~hsync_i && hsync_i_1)
            row_cnt <= row_cnt + 1'b1;
        else if (~vsync_i && vsync_i_1)
            row_cnt <= 9'd0;     
    end
    
    
    //data_control
    always @ (posedge pclk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0)
            data_control <= 3'b100;
        else if (hsync_i_2 == 1'b1 && hsync_i_1 == 1'b1)
            data_control <= {1'b0,row_cnt[0],~col_cnt[0]};
        else
            data_control <= 3'b100;       
    end
    
    shift_ram        shift_ram_1 (
      .D             (bayer_data     ),        // input wire [7 : 0] D
      .CLK             (pclk            ),      // input wire CLK
      .CE             (hsync_i         ),       // input wire CE
      .SCLR            (~s_rst_n        ),      // input wire SCLR
      .Q             (line_1            )         // output wire [7 : 0] Q
    );
    
    shift_ram        shift_ram_2 (
      .D             (line_1            ),        // input wire [7 : 0] D
      .CLK             (pclk            ),      // input wire CLK
      .CE             (hsync_i         ),       // input wire CE
      .SCLR            (~s_rst_n        ),      // input wire SCLR
      .Q             (line_2            )         // output wire [7 : 0] Q
    );
    
    
    always @ (posedge pclk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0) begin
            line1_1    <= 8'd0;
            line1_2    <= 8'd0;
    
            line2_1 <= 8'd0;
            line2_2 <= 8'd0;
        end
        else begin
            line1_1    <= line_1;
            line1_2    <= line1_1;
    
            line2_1    <= line_2;
            line2_2    <= line2_1;
        end    
            
    end
    
    
    always @ (data_control) begin
           case(data_control)
               3'b000 : begin 
                   rgb_r = line1_1; 
                   rgb_g = line2_1 + line1_2; 
                   rgb_b = line2_2;
               end
               3'b001 : begin
                   rgb_r = line1_2;
                   rgb_g = line1_1 + line2_2; 
                   rgb_b = line2_1;
               end
               3'b010 : begin
                   rgb_r = line2_1;
                   rgb_g = line1_1 + line2_2;
                   rgb_b = line1_2;
               end
               3'b011 : begin
                   rgb_r = line2_2;
                   rgb_g = line2_1 + line1_2;
                   rgb_b = line1_1;
               end
               default: begin 
                   rgb_r = 8'd0;
                   rgb_g = 9'd0;
                   rgb_b = 8'd0; 
               end
               endcase
    end
    
    assign rgb_data =  {rgb_r,rgb_g[8:1],rgb_b};
    assign vsync_o     = vsync_i_3;
    assign hsync_o     = hsync_i_3;
    endmodule

      4)最后欣赏一下效果 ,效果还不错,继承了灰度款的优良性能。

    最后说明一下,最后分辨率改为640*480,但是发现480指的是0~480,所以行计数器在481清零。我是用的zynq,所以没进行iic硬件配置,用的是ps端arm的 iic接口做的。如果用默认的分辨率就需要修改一下ip的深度和行计数器的清零的数值就行了。说到仿真,vivado自带的仿真器还是没有modelsim好,但是modelsim仿真含有vivado ip的工程时,很麻烦,独立仿真更不行,ip仿真的源文件不好添加,联合仿真操作有点繁琐,这里呢先不讲,我下次再另外写一篇博客总结一下。

  • 相关阅读:
    Siege 3.0 正式版发布,压力测试工具
    Pomm 1.1.2 发布,专为 PG 设计的 ORM 框架
    Whonix 0.5.6 发布,匿名通用操作系统
    国内开源 java cms,Jspxcms 2.0 发布
    EZNamespaceExtensions.Net v2013增加对上下文菜单、缩略图、图标、属性表的支持
    GNU Guile 2.0.9 发布,Scheme 实现
    jdao 1.0.4 发布 轻量级的orm工具包
    OpenSearchServer 1.4 RC4 发布
    Percona Server for MySQL 5.5.3030.2
    Samba 4.0.5 发布
  • 原文地址:https://www.cnblogs.com/hqz68/p/10413896.html
Copyright © 2011-2022 走看看