拓冰建站拓冰建站
首页 / 资讯中心 / 正文

FPGA ISP 算法模块实现(blc、bnr)

目录一、bayer格栅二、blc算法模块实现三、3✖3邻域生成四、中值滤波算法实现一、bayer格栅Bayer 格栅中文常译拜耳阵列或拜耳滤色镜英文 Bayer Pattern / Bayer CFA是当今绝大多数数码相机、手机摄像头 CMOS/CCD 传感器上覆盖的那层彩色滤光片阵列。摄像头数据以bayer格式通过mipi接口进去FPGA。bayer格式通常有四种RGGB、BGGR、GRBG、GBRG​。以RGGB为例其数据排布如下数据按行顺序从左往右传输。本文提到的算法都是对每个通道数据进行单独处理的数据传进FPGA后需要将其分配进不同通道。RGRGGBGBRGRGGBGB二、blc算法模块实现基础公式输出原始值-黑电平偏置module blc # (parameter DATAWIDTH12) ( input wire clk, input wire rst_n, input wire [DATAWIDTH-1:0] din, input wire din_vld, input wire [DATAWIDTH-1:0] blc_offset, output reg [DATAWIDTH-1:0] dout, output reg dout_vld ); localparam ONE512d1; localparam ZERO512d0; wire [DATAWIDTH:0] result_temp; wire [DATAWIDTH-1:0] result; //输入为raw12数据即12bit无符号数据如果校正后数据出现负值则将结果置零 assign result_temp {1b0,din}-{1b0,blc_offset}; assign result result_temp[12] ? ZERO[0:12]:result_temp; always (posedge clk or negedge rst_n) begin if (!rst_n) dout ZERO[0:12]; else if (din_vld) dout result; end always (posedge clk or negedge rst_n) begin if (!rst_n) dout_vld 1b0; else dout_vld din_vld; end endmodule三、3✖3邻域生成在图像处理算法中常对像素点及其邻域内的8个像素点进行处理图像数据串行出入要产生3✖3的滑窗可采用如下图所示的方案。四、中值滤波算法实现本文采用中值滤波作为bnr的降噪算法中值滤波会选取数字图像或数字序列中像素点及其周围临近像素点一共有奇数个像素点的像素值将这些像素值排序然后将位于中间位置的像素值作为当前像素点的像素值让周围的像素值接近真实值从而消除孤立的噪声点。从九个像素中获取中值的步骤1、找出每组3✖1数据的最大值中值最小值2、找出3个最大值中的最小值3个中值中的中值3个最小值的最大值3、找出最大值的最小值、中值的中值、最小值的最大值这三个数据的中值即为九个像素的中值。具体verilog代码如下所示cmp模块对3✖1数据进行排序bnr模块输出3✖3数据的中值。module cmp # (parameter DATAWIDTH12) ( input wire [DATAWIDTH-1:0] din1,din2,din3, output reg [DATAWIDTH-1:0] max,mid,min ); localparam ONE 512d1; localparam ZERO 512d0; wire flag1,flag2,flag3; assign flag1 din1din2; assign flag2 din1din3; assign flag3 din2din3; always (*) begin case ({flag1,flag2,flag3}) 3b000:begin maxdin3;middin2;mindin1;end 3b001:begin maxdin2;middin3;mindin1;end 3b010:begin maxdin2;middin1;mindin3;end 3b011:begin maxdin2;middin1;mindin3;end //din1din2 3b100:begin maxdin3;middin1;mindin2;end 3b101:begin maxdin3;middin2;mindin1;end 3b110:begin maxdin1;middin3;mindin2;end 3b111:begin maxdin1;middin2;mindin3;end default:begin maxZERO[DATAWIDTH-1:0]; midZERO[DATAWIDTH-1:0]; minZERO[DATAWIDTH-1:0]; end endcase end endmodulemodule bnr # (parameter DATAWIDTH12) ( input wire clk, input wire rst_n, input wire [DATAWIDTH-1:0] din1,din2,din3, input wire din_vld, output reg [DATAWIDTH-1:0] dout, output reg dout_vld ); localparam ONE 512d1; localparam ZERO 512d0; wire [DATAWIDTH-1:0] max1,mid1,min1; reg [1:0]vld_shift; reg [DATAWIDTH-1:0] max2,max3,mid2,mid3,min2,min3; wire [DATAWIDTH-1:0] max_min,mid_mid,min_max; wire [DATAWIDTH-1:0] mid; cmp #( .DATAWIDTH( DATAWIDTH ) )u_cmp1( .din1 ( din1 ), .din2 ( din2 ), .din3 ( din3 ), .max ( max1 ), .mid ( mid1 ), .min ( min1 ) ); always (posedge clk or negedge rst_n) begin if (!rst_n) vld_shift ZERO[1:0]; else if (din_vld) vld_shift {vld_shift[0],din_vld}; end always (posedge clk or negedge rst_n) begin if (!rst_n) begin max2 ZERO[DATAWIDTH-1:0]; mid2 ZERO[DATAWIDTH-1:0]; min2 ZERO[DATAWIDTH-1:0]; max3 ZERO[DATAWIDTH-1:0]; mid3 ZERO[DATAWIDTH-1:0]; min3 ZERO[DATAWIDTH-1:0]; end else if (din_vld) begin max2 max1; mid2 mid1; min2 min1; max3 max2; mid3 mid2; min3 min2; end end cmp #( .DATAWIDTH( DATAWIDTH ) )u_cmp2( .din1 ( max1 ), .din2 ( max2 ), .din3 ( max3 ), .min ( max_min) ); cmp #( .DATAWIDTH( DATAWIDTH ) )u_cmp3( .din1 ( mid1 ), .din2 ( mid2 ), .din3 ( mid3 ), .mid ( mid_mid) ); cmp #( .DATAWIDTH( DATAWIDTH ) )u_cmp4( .din1 ( min1 ), .din2 ( min2 ), .din3 ( min3 ), .max ( min_max) ); cmp #( .DATAWIDTH( DATAWIDTH ) )u_cmp5( .din1 ( max_min ), .din2 ( mid_mid ), .din3 ( min_max ), .mid ( mid) ); always (posedge clk or negedge rst_n) begin if (!rst_n) dout ZERO[DATAWIDTH-1:0]; else if (din_vld vld_shift[1]) dout mid; end always (posedge clk or negedge rst_n) begin if (!rst_n) dout_vld 1b0; else dout_vld din_vld vld_shift[1]; end endmodule
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门