0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

FPGA开源工作室 来源:CSDN技术社区 作者: FPGA开源工作室 2021-04-06 10:23 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

基于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处理后的显示效果
编辑:lyn

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FPGA
    +关注

    关注

    1664

    文章

    22545

    浏览量

    640419
  • 白平衡
    +关注

    关注

    0

    文章

    14

    浏览量

    8173

原文标题:基于FPGA的自动白平衡算法的实现

文章出处:【微信号:leezym0317,微信公众号:FPGA开源工作室】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    幻尔miniBalan智能平衡小车搭载PID、LQR等多维算法,融合多模态AI大模型

    幻尔科技发布AI大模型平衡小车miniBalan,以“全力开卷”的姿态,为每一位探索智能控制领域的学习者,打造出集经典理论、前沿AI、实战创新于一体的全能学习平台,实现从入门到精通的无缝进阶!一
    的头像 发表于 05-19 11:46 239次阅读
    幻尔miniBalan智能<b class='flag-5'>平衡</b>小车搭载PID、LQR等多维<b class='flag-5'>算法</b>,融合多模态AI大模型

    AI 算法核心知识清单(深度实战版2)

    三、机器学习核心算法(入门到实战)​1.监督学习算法(已知标签的模型训练)​线性模型​线性回归(回归任务):​核心原理:假设y=w₀+w₁x₁+w₂x₂+...+wₙxₙ+ε(ε为误差项),通过
    的头像 发表于 04-24 11:58 259次阅读
    AI <b class='flag-5'>算法</b>核心知识清单(深度<b class='flag-5'>实战</b>版2)

    如何在 Base Secure Boot 中对 ADKP 进行编程?

    我想问如何在 Base Secure Boot 中对 ADKP 进行编程 S32K344-白平衡器 #HSE#BaseSecureBoot
    发表于 04-14 07:23

    基于FPGA的低照度条件下EBAPS图像混合噪声去除算法

    本文提出了基于可编程逻辑门阵列(field programmable gate array,FPGA)的开关融合中值-高斯(open and close mix-median-Gaussian,OCMMG)滤波算法
    的头像 发表于 03-11 09:24 7480次阅读
    基于<b class='flag-5'>FPGA</b>的低照度条件下EBAPS图像混合噪声去除<b class='flag-5'>算法</b>

    芯片过热导致锁死?全自动烧录机温控系统的优化实战

    。 额外收益:温度日志帮助发现,来自不同封装厂的芯片,其发热特性有细微差异。这为后续的芯片来料质量评估提供了一个新的观察维度。 总结与反思这次优化实战揭示了一个常见误区:全自动烧录机的可靠性,不只取决于
    发表于 02-11 09:34

    KMbalancerII+动平衡等级评估功能介绍#动平衡仪#动平衡校正

    平衡
    KM预测性维护专家
    发布于 :2025年11月04日 16:36:39

    基于FPGA的CLAHE图像增强算法设计

    CLAHE图像增强算法又称为对比度有限的自适应直方图均衡算法,其算法原理是通过有限的调整图像局部对比度来增强有效信号和抑制噪声信号。
    的头像 发表于 10-15 10:14 886次阅读
    基于<b class='flag-5'>FPGA</b>的CLAHE图像增强<b class='flag-5'>算法</b>设计

    UWB自动跟随技术原理、算法融合优化和踩坑实录

    UWB为什么是最靠谱的自动跟随技术?原理是什么?需要做什么算法融合、优化?我们在开发过程中踩过的坑。
    的头像 发表于 08-14 17:45 1878次阅读
    UWB<b class='flag-5'>自动</b>跟随技术原理、<b class='flag-5'>算法</b>融合优化和踩坑实录

    无感FOC算法:如何在动态与稳定之间找到最优平衡?--【其利天下】

    在无感FOC(Field-OrientedControl,磁场定向控制)算法中,动态响应和稳定性是电机控制系统中两个非常重要的性能指标。动态响应指的是系统对输入信号变化的快速反应能力,而稳定性则是指
    的头像 发表于 08-08 18:38 6626次阅读
    无感FOC<b class='flag-5'>算法</b>:如何在动态与稳定之间找到最优<b class='flag-5'>平衡</b>?--【其利天下】

    Ansible代码上线项目实战案例

    在DevOps浪潮中,自动化部署已经成为每个运维工程师的必备技能。今天我将分享一个完整的Ansible代码上线项目实战案例,让你的部署效率提升10倍!
    的头像 发表于 07-24 14:03 820次阅读

    基于FPGA实现FOC算法之PWM模块设计

    哈喽,大家好,从今天开始正式带领大家从零到一,在FPGA平台上实现FOC算法,整个算法的框架如下图所示,如果大家对算法的原理不是特别清楚的话,可以先去百度上学习一下,本教程着重介绍实现
    的头像 发表于 07-17 15:21 3784次阅读
    基于<b class='flag-5'>FPGA</b>实现FOC<b class='flag-5'>算法</b>之PWM模块设计

    基于Matlab与FPGA的双边滤波算法实现

    前面发过中值、均值、高斯滤波的文章,这些只考虑了位置,并没有考虑相似度。那么双边滤波来了,既考虑了位置,有考虑了相似度,对边缘的保持比前几个好很多,当然实现上也是复杂很多。本文将从原理入手,采用Matlab与FPGA设计实现双边滤波算法
    的头像 发表于 07-10 11:28 4917次阅读
    基于Matlab与<b class='flag-5'>FPGA</b>的双边滤波<b class='flag-5'>算法</b>实现

    基于FPGA的压缩算法加速实现

    本设计中,计划实现对文件的压缩及解压,同时优化压缩中所涉及的信号处理和计算密集型功能,实现对其的加速处理。本设计的最终目标是证明在充分并行化的硬件体系结构 FPGA 上实现该算法时,可以大大提高该算法
    的头像 发表于 07-10 11:09 2670次阅读
    基于<b class='flag-5'>FPGA</b>的压缩<b class='flag-5'>算法</b>加速实现

    是德示波器MSOX3104A自动测量功能详解与实战技巧

    与高效化。通过自动识别信号特征、一键生成测量结果,该设备显著降低了人工操作的复杂性,提升了测量精度与效率。本文将围绕其自动测量功能的原理、操作步骤及实战应用展开详细探讨。   二、MSOX3104A
    的头像 发表于 07-03 13:52 903次阅读
    是德示波器MSOX3104A<b class='flag-5'>自动</b>测量功能详解与<b class='flag-5'>实战</b>技巧

    同步电机失步浅析

    纯分享帖,需要者可点击附件免费获取完整资料~~~*附件:同步电机失步浅析.pdf【免责声明】本文系网络转载,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请第一时间告知,删除内容!
    发表于 06-20 17:42