非常基础的白平衡算法分享

发布时间:2024年01月21日

之前有学过一种白平衡算法,但是存在一些缺陷,昨天突发奇想换一种思路,发现解决了这个历史遗留问题。

首先是之前的白平衡算法实现以后得效果图:

以上的这个效果图的问题是,越靠上的区域比较黑,这是因为当时是采用每一行的数据除以总的像素,得到该行对于总的子像素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

文章来源:https://blog.csdn.net/weixin_60010850/article/details/135733946
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。