1 圖像bayer格式介紹
bayer格式是伊士曼·柯達公司科學(xué)家Bryce Bayer發(fā)明的,Bryce Bayer所發(fā)明的拜耳陣列被廣泛運用數(shù)字圖像。Bayer格式是相機內(nèi)部的原始數(shù)據(jù), 一般后綴名為.raw。
對于彩色圖像,一般是三原色數(shù)據(jù),rgb格式。但是攝像頭一個像素點只有rgb中一種數(shù)據(jù)(下圖為bayer色彩濾波陣列)。但是有很多攝像頭直接輸出rgb和yuv格式,如ov5640、ov7725等等,這是因為在Sensor模組的內(nèi)部會有一個ISP模塊,會將 Sensor采集到的數(shù)據(jù)進行插值和特效處理,所以直接輸出彩色圖像但也有攝像頭沒有ISP模塊,直接輸出Bayer數(shù)據(jù),這就需要自己寫B(tài)ayer轉(zhuǎn)rgb算法。
2 MT9V034簡單介紹
做圖像處理的朋友都知道,MT9V034是一款十分出色的做機器視覺的攝像頭,一般都是灰度的。但是也有彩色款,當(dāng)時我覺得灰度的效果那么好,一時頭熱就買一個彩色款的。mt9v034用起來很方便,可以不用寄存器配置,上電默認752*480分辨率。當(dāng)然也可以iic配置。
3 MT9V034 datasheet 簡單解析
1) 有效圖像 752x480;
最大時鐘為27Mhz;
最大幀率為60fps;
10位的adc(我的是八位的輸出,店家只將高8位引出,有點影響最后圖像的精度);
2)這是mt9v034Bayer陣列,注意輸出方向,從左到右,從上到下;
3)攝像頭ID號要需要查看攝像頭模塊PCB上的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轉(zhuǎn)rgb算法解析
我是用shift_register IP緩存兩行數(shù)據(jù),形成2*2窗口(這是FPGA做圖像算法最常用的方法和IP),不會的朋友可以搜一搜,有很多博客可以學(xué)習(xí),一定要自己仿真一下,搞明白,這原理有點難理解。
根據(jù)窗口移動,不難發(fā)現(xiàn),總結(jié)出一條重要的規(guī)律:總共只有四種窗口,而且與行和列的奇偶有關(guān)。
假設(shè)計數(shù)器從零開始記數(shù):
1)第一種{行偶,列偶}
2)第二種{行偶,列奇}
3)第三種{行奇,列偶}
4)第四種{行奇,列奇}
5 算法實現(xiàn)
首先說明我是用Xilinx的ZYNQ FPGA,(Altera的也有類似的IP)。我直接說明一下IP的參數(shù)設(shè)置,其他的像怎么添加IP什么的我就不講了,不會的自己網(wǎng)上學(xué)習(xí)。
1)這是IP首頁,藍框自定義IP名,修改一下紅框的參數(shù),我們是8位數(shù)據(jù),一行數(shù)據(jù)為640個。Clock enable端與sclr端可以根據(jù)自己的要求決定勾不勾選。其他默認就行,點擊ok可以了。
2)Vivado也提供端口例化模板,如下圖操作就行;
3)verilog源碼
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: 宏強子
//
// Create Date: 2019/02/04 1056
// 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 vsync_i_1 ;
reg vsync_i_2 ;
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 *******************************
//=============================================================================
//列計數(shù)
always @ (posedge pclk or negedge s_rst_n) begin
if(s_rst_n == 1‘b0)
col_cnt 《= 10’d0;
else if (hsync_i == 1‘b1)
col_cnt 《= col_cnt + 1’b1;
else
col_cnt 《= 10‘d0;
end
always @ (posedge pclk) begin
hsync_i_1 《= hsync_i;
hsync_i_2 《= hsync_i_1;
end
always @ (posedge pclk) begin
vsync_i_1 《= vsync_i;
vsync_i_2 《= vsync_i_1;
end
//行計數(shù)
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 (row_cnt 》= 9‘d481)
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_1 == 1‘b1 && hsync_i == 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 + 8‘d5;
rgb_g = line2_1 + line1_2 + 8’d10;
rgb_b = line2_2 + 8‘d5;
end
3’b001 : begin
rgb_r = line1_2 + 8‘d5;
rgb_g = line1_1 + line2_2 + 8’d10;
rgb_b = line2_1 + 8‘d5;
end
3’b010 : begin
rgb_r = line2_1 + 8‘d5;
rgb_g = line1_1 + line2_2 + 8’d10;
rgb_b = line1_2 + 8‘d5;
end
3’b011 : begin
rgb_r = line2_2 + 8‘d5;
rgb_g = line2_1 + line1_2 + 8’d10;
rgb_b = line1_1 + 8‘d5;
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_2;
assign hsync_o = hsync_i_2;
endmodule
6 總結(jié)
最后說明一下,最后分辨率改為640*480,但是發(fā)現(xiàn)480指的是0~480,所以行計數(shù)器在481清零。由于我使用的是ZYNQ,所以直接使用PS端的IIC接口配置攝像頭。如果用默認的分辨率就需要修改一下IP的深度和行計數(shù)器的清零的數(shù)值就行了。
編輯:jq
-
寄存器
+關(guān)注
關(guān)注
31文章
5294瀏覽量
119816 -
計數(shù)器
+關(guān)注
關(guān)注
32文章
2253瀏覽量
94287 -
IIC
+關(guān)注
關(guān)注
11文章
298瀏覽量
38241
原文標(biāo)題:彩色MT9V034攝像頭 Bayer轉(zhuǎn)RGB FPGA實現(xiàn)
文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論