之前有学过一种白平衡算法,但是存在一些缺陷,昨天突发奇想换一种思路,发现解决了这个历史遗留问题。
首先是之前的白平衡算法实现以后得效果图:
以上的这个效果图的问题是,越靠上的区域比较黑,这是因为当时是采用每一行的数据除以总的像素,得到该行对于总的子像素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