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仿真的源文件不好添加,联合仿真操作有点繁琐,这里呢先不讲,我下次再另外写一篇博客总结一下。

  • 相关阅读:
    把枚举类型绑定到datasource
    关于linq使用建议
    VS2012恢复默认设置的2种方法
    Manifold learning-based methods for analyzing single-cell RNA-sequencing data
    Single cell RNA-seq denoising using a deep count autoencoder
    scImpute——An accurate and robust imputation method scImpute for single-cell RNA-seq data
    第三代测序popular workflow
    js作用域闭包
    select的option选项左右移动
    添加区域练级联动
  • 原文地址:https://www.cnblogs.com/hqz68/p/10413896.html
Copyright © 2011-2022 走看看