之前有学过一种白平衡算法,但是存在一些缺陷,昨天突发奇想换一种思路,发现解决了这个历史遗留问题。
首先是之前的白平衡算法实现以后得效果图:
以上的这个效果图的问题是,越靠上的区域比较黑,这是因为当时是采用每一行的数据除以总的像素,得到该行对于总的子像素1920x1080x3的比例,因为是采用累加的过程,但是刚开始累加的和肯定比较小,除以一个固定的值会导致结果趋于0,对于数字电路来说,没有小数的情况下那就是0,因此在经过不断累加以后,越下方那么数值越趋于正常,因此下方的图像就越清晰。
?
对于上面这个改进的图像,我们修改缺陷是:
之前是因为每一行都累计,每一行与这个固定的总的子像素1920x1080x3去比,这次我们修改为,当将一帧数据都累加完以后,我们在去除以这个总的子像素,这样避免刚开始数据比较小的问题。
但是这个存在一个问题,那就是实际上当前帧的比例关系是上一帧和总的子像素1920x1080x3之间的关系,在采集足够快的时候,这个应该是没啥问题的。到这里,本次分享的基础的白平衡算法就算结束啦。下方附上verilog代码
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2024 All rights reserved
// -----------------------------------------------------------------------------
// Author : TXH 1811369830@qq.com
// File : white_balance.v
// Create : 2024-01-21 19:57:41
// Revise : 2024-01-21 19:57:41
// Editor : sublime text3, tab size (4)
// -----------------------------------------------------------------------------
module white_balance(
input wire clk,
input wire rst,
input wire rgb_fv,
input wire rgb_lv,
input wire [7:0] data_r,
input wire [7:0] data_g,
input wire [7:0] data_b,
output wire rgb_fv_o,
output wire rgb_lv_o,
output wire [7:0] data_r_o,
output wire [7:0] data_g_o,
output wire [7:0] data_b_o
);
reg [31:0] Rsum , Gsum,Bsum;
reg rgb_fv_fall;
reg [1:0] rgb_fv_dly;
reg [32:0] Ksum;
reg [10:0] Ravg,Gavg,Bavg;
wire [63:0] Tmp_Kavg;
wire Kavg_vld;
wire [32:0] Kavg;
wire [18:0] RxKavg,GxKavg,BxKavg;
reg [2:0] rgb_lv_dly;
wire [39:0] tmp_Rnew,tmp_Gnew,tmp_Bnew;
wire tmp_Rnew_vld;
reg [7:0] Rnew,Gnew,Bnew;
reg RGBnew_vld;
reg [12:0] fv_cnt;
reg [12:0] hv_cnt;
wire flag_frame;
assign flag_frame = (fv_cnt=='d1079 &&rgb_lv==1'b1 && hv_cnt=='d1919)?1:0;
always @( posedge clk ) begin
if (rst == 1'b1) begin
hv_cnt<= 'd0;
end
else if(rgb_lv==1'b1 && hv_cnt=='d1919)begin
hv_cnt<= 'd0;
end
else if(rgb_lv==1'b1) begin
hv_cnt<=hv_cnt+1'b1;
end
end
always @( posedge clk ) begin
if (rst == 1'b1) begin
fv_cnt<= 'd0;
end
else if(fv_cnt=='d1079 &&rgb_lv==1'b1 && hv_cnt=='d1919)begin
fv_cnt<= 'd0;
end
else if(rgb_lv==1'b1 && hv_cnt=='d1919) begin
fv_cnt<=fv_cnt+1'b1;
end
end
always @(posedge clk) begin
rgb_lv_dly <= {rgb_lv_dly[1:0],rgb_lv};
end
always @(posedge clk) begin
rgb_fv_dly <= {rgb_fv_dly[0],rgb_fv};
end
always @(posedge clk ) begin
if(rst == 1'b1) begin
Rsum <='d0;
end
else if(flag_frame==1'b1)begin
Rsum <='d0;
end
else if (rgb_lv == 1'b1) begin
Rsum <= Rsum + data_r;
end
end
always @(posedge clk ) begin
if(rst == 1'b1) begin
Gsum <='d0;
end
else if(flag_frame==1'b1)begin
Gsum <='d0;
end
else if (rgb_lv == 1'b1) begin
Gsum <= Gsum + data_g;
end
end
always @(posedge clk ) begin
if(rst == 1'b1) begin
Bsum <='d0;
end
else if(flag_frame==1'b1)begin
Bsum <='d0;
end
else if (rgb_lv == 1'b1) begin
Bsum <= Bsum + data_g;
end
end
always @( posedge clk ) begin
if (rst == 1'b1) begin
Ksum<= 'd0;
end
else if(flag_frame==1'b1) begin
Ksum<= Rsum + Gsum + Bsum;
end
end
div_gen_kavg div_gen_kavg_inst (
.aclk(clk), // input wire aclk
.s_axis_divisor_tvalid(flag_frame==1'b1), // input wire s_axis_divisor_tvalid
.s_axis_divisor_tdata(23'd6220800), // input wire [23 : 0] s_axis_divisor_tdata
.s_axis_dividend_tvalid(flag_frame==1'b1), // input wire s_axis_dividend_tvalid
.s_axis_dividend_tdata(Ksum), // input wire [39 : 0] s_axis_dividend_tdata
.m_axis_dout_tvalid(Kavg_vld), // output wire m_axis_dout_tvalid
.m_axis_dout_tdata(Tmp_Kavg) // output wire [63 : 0] m_axis_dout_tdata 56:24
);
assign Kavg = Tmp_Kavg[56:24];
always @(posedge clk) begin
if(rst == 1'b1) begin
Ravg <='d0;
Gavg <= 'd0;
Bavg <= 'd0;
end
else if(flag_frame==1'b1)begin
Ravg <= Rsum[31:21];
Gavg <= Gsum[31:21];
Bavg <= Bsum[31:21];
end
end
//red
mult_gen_8x11 mult_gen_8x11_R (
.CLK(clk), // input wire CLK
.A(data_r), // input wire [7 : 0] A
.B(Kavg[10:0]), // input wire [10 : 0] B
.P(RxKavg) // output wire [18 : 0] P
);
div_gen_PixelNew NewPixelR (
.aclk(clk), // input wire aclk
.s_axis_divisor_tvalid(rgb_lv_dly[2]), // input wire s_axis_divisor_tvalid
.s_axis_divisor_tdata(Ravg), // input wire [15 : 0] s_axis_divisor_tdata
.s_axis_dividend_tvalid(rgb_lv_dly[2]), // input wire s_axis_dividend_tvalid
.s_axis_dividend_tdata(RxKavg), // input wire [23 : 0] s_axis_dividend_tdata
.m_axis_dout_tvalid(tmp_Rnew_vld), // output wire m_axis_dout_tvalid
.m_axis_dout_tdata(tmp_Rnew) // output wire [39 : 0] m_axis_dout_tdata
);
//green
mult_gen_8x11 mult_gen_8x11_G (
.CLK(clk), // input wire CLK
.A(data_g), // input wire [7 : 0] A
.B(Kavg[10:0]), // input wire [10 : 0] B
.P(GxKavg) // output wire [18 : 0] P
);
div_gen_PixelNew NewPixelG (
.aclk(clk), // input wire aclk
.s_axis_divisor_tvalid(rgb_lv_dly[2]), // input wire s_axis_divisor_tvalid
.s_axis_divisor_tdata(Gavg), // input wire [15 : 0] s_axis_divisor_tdata
.s_axis_dividend_tvalid(rgb_lv_dly[2]), // input wire s_axis_dividend_tvalid
.s_axis_dividend_tdata(GxKavg), // input wire [23 : 0] s_axis_dividend_tdata
.m_axis_dout_tvalid(), // output wire m_axis_dout_tvalid
.m_axis_dout_tdata(tmp_Gnew) // output wire [39 : 0] m_axis_dout_tdata
);
//blue
mult_gen_8x11 mult_gen_8x11_B (
.CLK(clk), // input wire CLK
.A(data_b), // input wire [7 : 0] A
.B(Kavg[10:0]), // input wire [10 : 0] B
.P(BxKavg) // output wire [18 : 0] P
);
div_gen_PixelNew NewPixelB (
.aclk(clk), // input wire aclk
.s_axis_divisor_tvalid(rgb_lv_dly[2]), // input wire s_axis_divisor_tvalid
.s_axis_divisor_tdata(Bavg), // input wire [15 : 0] s_axis_divisor_tdata
.s_axis_dividend_tvalid(rgb_lv_dly[2]), // input wire s_axis_dividend_tvalid
.s_axis_dividend_tdata(BxKavg), // input wire [23 : 0] s_axis_dividend_tdata
.m_axis_dout_tvalid(), // output wire m_axis_dout_tvalid
.m_axis_dout_tdata(tmp_Bnew) // output wire [39 : 0] m_axis_dout_tdata 34:16
);
/
always @(posedge clk) begin
if(rst == 1'b1 ) begin
Rnew <= 'd0;
end
else if(tmp_Rnew[34:16] >255) begin
Rnew <= 'd255;
end
else begin
Rnew <= tmp_Rnew[23:16];
end
end
always @(posedge clk) begin
if(rst == 1'b1 ) begin
Gnew <= 'd0;
end
else if(tmp_Gnew[34:16] >255) begin
Gnew <= 'd255;
end
else begin
Gnew <= tmp_Gnew[23:16];
end
end
always @(posedge clk) begin
if(rst == 1'b1 ) begin
Bnew <= 'd0;
end
else if(tmp_Bnew[34:16] >255) begin
Bnew <= 'd255;
end
else begin
Bnew <= tmp_Bnew[23:16];
end
end
always @(posedge clk ) begin
RGBnew_vld <=tmp_Rnew_vld;
end
assign rgb_lv_o = RGBnew_vld;
assign data_r_o = Rnew;
assign data_g_o = Gnew;
assign data_b_o = Bnew;
assign rgb_fv_o = rgb_fv_dly[1];
endmodule