参考文献
彩色MT9V034摄像头 Bayer转rgb FPGA实现
https://www.cnblogs.com/hqz68/p/10413896.html
文章目录
- 前言
- Bayer转rgb
- 算法解析
- 总结
前言
Bayer格式是相机内部的原始数据, 一般后缀名为.raw。
对于彩色图像,一般是三原色数据,rgb格式。但是摄像头一个像素点只有rgb中一种数据。但是有很多摄像头直接输出rgb和yuv格式,如ov5640、ov7725等等,这是因为在Sensor模组的内部会有一个ISP模块,会将 Sensor采集到的数据进行插值和特效处理,所以直接输出彩色图像。但不是所有的摄像头都集成ISP,而直接输出Bayer数据,这就需要写Bayer转rgb算法。
Bayer转rgb
算法解析
mt9v034的Bayer阵列为例,注意输出方向,从右到左,从上到下。
可以用shift register ip 或者fifo缓存两行数据,形成2*2窗口。
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
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 @ (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)
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
由于在列计数col_cnt中使用了hsync_i_3 == 1’b1 && hsync_i_2 == 1’b1的作为开始计数条件,相当于向后延迟了3个PCLK,所以col_cnt[0]为0时候,其实列计数为奇数列。
当然,如果列计数col_cnt中直接使用hsync_i == 1’b1作为开始计数条件,则col_cnt[0]为0时候,列计数为偶数列。
//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
根据窗口移动,不难发现,总结出一条重要的规律:总共只有四种窗口,而且与行和列的奇偶有关。
假设计数器从零开始计数:
第一种{行偶,列偶}
第二种{行偶,列奇}
第三种{行奇,列偶}
第四种{行奇,列奇}
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;
总结
本文根据mt9v034讲解Bayer转rgb的使用,不同摄像头有不同的Bayer的起始排列位置,需要根据手册撰写代码。