浅析基于FPGA自动白平衡算法的简述与实战

基于fpga自动白平衡算法的实现
1 白平衡介绍
对于白平衡基本概念的详细介绍请查看文章《白平衡初探》,白平衡算法主要的作用是将偏暖或者偏冷的色调自动恢复到正常色调,是图像看起来更加色彩饱满正常。
如上图所示,左1色温偏冷,中间色温正常,右一色温偏暖。上图比较直观的展示了色温的概念。偏冷的色温会给人一种还冷的感觉,偏暖的色温会给人一种温暖的感觉。
2 白平衡算法以及matlab实现
1)原始的灰度世界算法
灰度世界算法(gray world)是以灰度世界假设为基础的,该假设认为对于一幅有着大量色彩变化的图像, r、 g、 b 三个分量的平均值趋于同一个灰度k。一般有两种方法来确定该灰度。
(1)直接给定为固定值, 取其各通道最大值的一半,即取为127或128;
(2)令 k = (raver+gaver+baver)/3,其中raver,gaver,baver分别表示红、 绿、 蓝三个通道的平均值。
算法的第二步是分别计算各通道的增益:
kr=k/raver;
kg=k/gaver;
kb=k/baver;
算法第三步为根据von kries 对角模型,对于图像中的每个像素r、g、b,计算其结果值:
rnew = r * kr;
gnew = g * kg;
bnew = b * kb;
对于上式,计算中可能会存在溢出(》255,不会出现小于0的)现象,处理方式有两种。
a、 直接将像素设置为255,这可能会造成图像整体偏白。
b、 计算所有rnew、gnew、bnew的最大值,然后利用该最大值将将计算后数据重新线性映射到[0,255]内。实践证明这种方式将会使图像整体偏暗,建议采用第一种方案。
2)完美反射算法
原理:完美全反射理论perfect reflector假设图像上最亮点就是白点,并以此白点为参考对图像进行自动白平衡,最亮点定义为r+g+b的最大值,具体编码步骤如下:
(1)计算每个像素的rgb之和,并保存到一临时内存块中。
(2)按r+g+b值的大小计算出其前10%或其他ratio的白色参考点的的阈值t。
(3)遍历图像中的每个点,计算其中r+g+b值大于t的所有点的rgb分量的累积和的平均值。
(4)对每个点将像素量化到[0,255]之间。
3)动态阈值法
(1)。 把图像w*h从rgb空间转换到ycrcb空间。
(2)。 选择参考白色点:
a. 把图像分成宽高比为4:3个块(块数可选)。
b. 对每个块,分别计算cr,cb的平均值mr,mb。
c. 对每个块,根据mr,mb,用下面公式分别计算cr,cb的方差dr,db。
d. 判定每个块的近白区域(near-white region)。
判别表达式为:
设一个“参考白色点”的亮度矩阵rl,大小为w*h。
若符合判别式,则作为“参考白色点”,并把该点(i,j)的亮度(y分量)值赋给rl(i,j);
若不符合,则该点的rl(i,j)值为0。
(3)。 选取参考“参考白色点”中最大的10%的亮度(y分量)值,并选取其中的最小值lu_min.
(4)。 调整rl,若rl(i,j)《lu_min, rl(i,j)=0; 否则,rl(i,j)=1;
(5)。 分别把r,g,b与rl相乘,得到r2,g2,b2。 分别计算r2,g2,b2的平均值,rav,gav,bav;
(6)。 得到调整增益:
ymax=double(max(max(y)))/5;
rgain=ymax/rav;
ggain=ymax/gav;
bgain=ymax/bav;
(7)。 调整原图像:
ro= r*rgain;
go= g*ggain;
bo= b*bgain;
fpga的实现采用灰度世界算法。
matlab代码:
close allclear allclci=imread(‘test1.jpg’);[h,w,l]=size(i);%得到图像长宽高rsum = 0;gsum = 0;bsum = 0;rsum = double(rsum);gsum = double(gsum);bsum = double(bsum);for i = 1 : h for j = 1 :w rsum = rsum + double(i(i,j,1)); gsum = gsum + double(i(i,j,2)); bsum = bsum + double(i(i,j,3)); endendraver = rsum / (h*w);gaver = gsum / (h*w);baver = bsum / (h*w);%k=128;%第一种k取值方法k = (raver+gaver+baver)/3;%第二种方法rgain = k / raver;ggain = k / gaver;bgain = k / baver;iwb(:,:,1) = i(:,:,1) * rgain;iwb(:,:,2) = i(:,:,2) * ggain;iwb(:,:,3) = i(:,:,3) * bgain;imwrite(iwb,‘result1.jpg’);figure(1),subplot(121),imshow(i),title(‘原始图像’);subplot(122),imshow(iwb),title(‘自动白平衡图像’);
效果展示:
3 fpga实现自动白平衡灰度世界法
灰度世界法verilog代码:
/**********************************copyright@fpga open source studio微信公众号:fpga开源工作室algorithm:auto white balance gray world 800x600x255=480000***********************************/`define xlen 32`define n(n) [(n)-1:0]module white_balance#( parameter dw = 24 )( input pixelclk, input reset_n, input [dw-1:0] din, //rgb in input i_hsync, input i_vsync, input i_de,
output [dw-1:0] dout, //gray out output o_hsync, output o_vsync, output o_de ); localparam stage_list = 32‘h0101_0101;//32’b00000000_00000000_00000000_00000000;localparam divisor = 32‘h0007_5300;//800*600localparam divisork = 32’h0000_0003;//800*600 wire [7:0] r,g,b;reg [27:0] sumr,sumg,sumb;reg [27:0] sumr_r,sumg_r,sumb_r;wire [9:0] kave;wire [7:0] k;
wire rack;wire `n(`xlen) rquo,rrem;
wire gack;wire `n(`xlen) gquo,grem;
wire back;wire `n(`xlen) bquo,brem;
wire kack;wire `n(`xlen) kquo,krem;
wire grack;wire `n(`xlen) grquo,grrem;
wire ggack;wire `n(`xlen) ggquo,ggrem;
wire gback;wire `n(`xlen) gbquo,gbrem;
reg [39:0] r_r,g_r,b_r;wire [7:0] ro,go,bo;
reg hsync_r1;reg vsync_r1;reg de_r1;
reg i_vsync_r;reg vsync_neg_r;
wire vsync_neg=(i_vsync_r&(~i_vsync));
assign kave=(rquo+gquo+bquo);assign k=kquo[7:0];
assign r=din[23:16];assign g=din[15:8];assign b=din[7:0];
assign o_hsync = hsync_r1;assign o_vsync = vsync_r1;assign o_de = de_r1;
assign ro=(r_r[18:10]》255)?255:r_r[17:10];assign go=(g_r[18:10]》255)?255:g_r[17:10];assign bo=(b_r[18:10]》255)?255:b_r[17:10];assign dout={ro,go,bo};
//synchronizationalways @(posedge pixelclk) begin hsync_r1 《= i_hsync; vsync_r1 《= i_vsync; de_r1 《= i_de;end
always @(posedge pixelclk or negedge reset_n)begin if(!reset_n)begin sumr《=28‘d0;《 span=“”》 sumg《=28’d0;《 span=“”》 sumb《=28‘d0;《 span=“”》 sumr_r《=28’d0;《 span=“”》 sumg_r《=28‘d0;《 span=“”》 sumb_r《=28’d0;《 span=“”》 i_vsync_r《=1‘b0;《 span=“”》 vsync_neg_r《=1’b0;《 span=“”》 r_r《=40‘b0;《 span=“”》 g_r《=40’b0;《 span=“”》 b_r《=40‘b0;《 span=“”》 end else begin i_vsync_r《=i_vsync;《 span=“”》 vsync_neg_r《=vsync_neg;《 span=“”》 r_r《=r*grquo;《 span=“”》 g_r《=g*ggquo;《 span=“”》 b_r《=b*gbquo;《 span=“”》 if(vsync_neg==1’b1) begin sumr_r《=sumr;《 span=“”》 sumg_r《=sumg;《 span=“”》 sumb_r《=sumb;《 span=“”》 end if(i_vsync==1‘b1) begin if(i_de==1’b1) begin sumr《=sumr+r;《 span=“”》 sumg《=sumg+g;《 span=“”》 sumb《=sumb+b;《 span=“”》 end else begin sumr《=sumr;《 span=“”》 sumg《=sumg;《 span=“”》 sumb《=sumb;《 span=“”》 end end else begin sumr《=28‘d0;《 span=“”》 sumg《=28’d0;《 span=“”》 sumb《=28‘d0;《 span=“”》 end endend
//rave divfunc #( .xlen ( `xlen ), .stage_list ( stage_list )
) i_divr ( .clk ( pixelclk ), .rst ( ~reset_n ), .a ( {4’b0,sumr_r} ), .b ( divisor ), .vld ( vsync_neg_r ), .quo ( rquo ), .rem ( rrem ), .ack ( rack )
);
//gave divfunc #( .xlen ( `xlen ), .stage_list ( stage_list )
) i_divg ( .clk ( pixelclk ), .rst ( ~reset_n ), .a ( {4‘b0,sumg_r} ), .b ( divisor ), .vld ( vsync_neg_r ), .quo ( gquo ), .rem ( grem ), .ack ( gack )
);
//bave divfunc #( .xlen ( `xlen ), .stage_list ( stage_list )
) i_divb ( .clk ( pixelclk ), .rst ( ~reset_n ), .a ( {4’b0,sumb_r} ), .b ( divisor ), .vld ( vsync_neg_r ), .quo ( bquo ), .rem ( brem ), .ack ( back )
);
//kdivfunc #( .xlen ( `xlen ), .stage_list ( stage_list )
) i_divk ( .clk ( pixelclk ), .rst ( ~reset_n ), .a ( {22‘b0,kave} ), .b ( divisork ), .vld ( back ), .quo ( kquo ), .rem ( krem ), .ack ( kack )
);
//rgaindivfunc #( .xlen ( `xlen ), .stage_list ( stage_list )
) i_divgr ( .clk ( pixelclk ), .rst ( ~reset_n ), .a ( {14’b0,k,10‘b0} ), .b ( rquo ), .vld ( kack ), .quo ( grquo ), .rem ( grrem ), .ack ( grack )
);
//ggaindivfunc #( .xlen ( `xlen ), .stage_list ( stage_list )
) i_divgg ( .clk ( pixelclk ), .rst ( ~reset_n ), .a ( {14’b0,k,10‘b0} ), .b ( gquo ), .vld ( kack ), .quo ( ggquo ), .rem ( ggrem ), .ack ( ggack )
);
//bgaindivfunc #( .xlen ( `xlen ), .stage_list ( stage_list )
) i_divgb ( .clk ( pixelclk ), .rst ( ~reset_n ), .a ( {14’b0,k,10‘b0} ), .b ( bquo ), .vld ( kack ), .quo ( gbquo ), .rem ( gbrem ), .ack ( gback )
);
endmodule
1)仿真效果
原始图像
经过灰度世界法的白平衡仿真效果
2)下板验证模型以及实现效果
下板验证图像由笔记本电脑通过hdmi输入到fpga芯片,经过fpga算法处理后在通过hdmi将图像送到显示屏展示处理效果。
笔记本电脑显示图片
经过fpga处理后的显示效果


多款互联网存款产品下架,是否对银行有影响?
iPhone X导入OLED面板,韩系、日系、陆系厂商在OLED面板布局
大功率光伏逆变器的PCB设计要点
HYT主机常见问题及解决方法
光纤衰减器有哪些类型和应用场景
浅析基于FPGA自动白平衡算法的简述与实战
印制电路板应该怎样来设计
大陆LCD厂商兴建10.5代厂 或导致面板产能过剩
北汇信息正式成为东方中科旗下成员企业
AMBEO双声道空间音频实时渲染器插件将于2023年底发布
一加5什么时候上市?一加手机5真机图现身:金属机身+骁龙835+首款8GB手机
过载过流的基础知识汇总
联合物联网高科技共同研发汽车智能健康气候控制系统
派拓网络宣布将以75万美元的价格收购Zingbox
Li-Cycle宣布已完成首次回收锂电电池材料的商业交付 并表示能够回收80%以上的元素
电力电缆为什么不能选择铝合金电缆?
地铁视频监控迎来了怎样的新概念
波音表示已停止使用机器人来进行波音777客机的自动化制造
Xbox Series X搭载的SoC将是最复杂的设计
瑞识科技已打通“芯片+封装+光学集成“的全链条