【VS开发】【图像处理】基于灰度世界、完美反射、动态阈值等图像自动白平衡算法的原理、实现及效果
一、原始的灰度世界算法
灰度世界算法(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]内。实践证明这种方式将会使图像整体偏暗,建议采用第一种方案。
一般来说,灰度世界算法的效果还是比较好的呢,并且该算法的执行速度非常之快,目前也存在了不少对该算法进行改进的效果,有时间我在整理一下。
原图 处理后的图
二、完美反射算法
当初写这个代码的时候的一些参考文献一下子也找不到了,就从已经写好的代码中描述下该算法的过程吧。
原理:完美全反射理论perfect Reflector假设图像上最亮点就是白点,并以此白点为参考对图像进行自动白平衡,最亮点定义为R+G+B的最大值,具体编码步骤如下:
(1)计算每个像素的R\G\B之和,并保存到一临时内存块中。
1
2
3
4
5
6
7
8
9
10
11
12
|
for (Y { Pointer for (X { Sum short )(*(Pointer) // HistRGB[Sum]++; *SumP short )Sum; Pointer SumP++; } } |
(2)按R+G+B值的大小计算出其前10%或其他Ratio的白色参考点的的阈值T。
1
2
3
4
5
6
7
8
9
|
for (Y { Sum if (Sum { Threshold break ; } } |
(3)遍历图像中的每个点,计算其中R+G+B值大于T的所有点的R\G\B分量的累积和的平均值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
for (Y { Pointer for (X { if (*SumP { AvgB AvgG AvgR // Amount++; } Pointer SumP++; } } AvgB AvgG AvgR |
(4)对每个点将像素量化到[0,255]之间。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
for (Y { Pointer for (X { Blue // Green Red if (Red else if (Red // if (Green else if (Green // if (Blue else if (Blue *Pointer byte )Blue; *(Pointer byte )Green; *(Pointer byte )Red; Pointer } } |
原图 Ratio=10% Ratio=2%
从效果上看,该算法应该比灰度世界的效果要好些,但是也还是受到Ratio这个参数的影像。特别是第二个图片,过高的Ration导致图片过于泛白。这个问题可以还是最后量化的哪一步引起的,我会抽空再研究一下其他的量化方式,尽量降低Ration的影响。
针对上述的第二步,看到很多matlab和VC的代码,有很多人居然先用快速排序对累加后的数据进行排序,然后再取其10%的最大值,对图像的数据进行排序,可能就是再快速的排序都快不起来吧,看到这,也许全国人民都笑了。
三、动态阈值算法
参考论文:A
Novel Automatic White Balance Method For Digital Still Cameras
同经典的一些算法相同,算法分为两个步骤:白点检测和白点调整。
白点检测:
(1)为了增强算法的鲁棒性,原文将图像分成12部分,其中宽高比为4:3,关于这一点,我认为不合理,对图像不是通用的,后文再说。
(2)计算每个区域的Cb\Cr分量的平均值Mb/Mr。
(3)按下式计算每个区域的Cb\Cr分量的绝对差的累积值Db/Dr:
上式中N为每个区域的像素数。
(4)如果Db/Dr的值偏小,则我们忽略这一块,因为这表明这一块的颜色分布比较均匀,而这样的局部对于白平衡不好。这个偏小的准则我们稍微再谈。
(5)统计对于除了符合第四条的的其他区域的Mb/Mr/Db/Dr的平均值作为整幅图像的Mb/Mr/Db/Dr值。
关于这一条,原文的话是:The final Mb、Mr、Db、Dr are obtained by taking the average of those regions that pass this additional step。
我在实际中做的时候就是分别对每块进行的,似乎效果也还不错。
(6)按下述规则初步确定哪些点是属于白色参考点:
(7)对于初步判断已经属于白色参考点的像素,按大小取其亮度值为前10%的位最终确定的白色参考点。
白点调整:
(1)计算白色参考点亮度值的平均值Raver,Gaver,Baver,(各通道分开计算)。
(2)按照以下各式计算每个通道的增益:
式中,Ymax就是YCbCr颜色空间中Y分量的在整幅图像中的最大值。
(3)按照以下各式计算最终每个通道的颜色值:
其中R/G/B为在原始的颜色空间中的值,注意这里要进行溢出检测的。
简单的谈下白点检测的分块操作吧,原文把图像分成4*3的12快,这样做事针对于我们很多数码照片是这个比例的,如果通用,我觉得应该用每个块的大小来控制,比如每块为 100*100个像素。
这个算法的效果如下:
原图 块大小50*50 块大小100*100
上三图表明:1、该算法效果非常好;2、对块大小不太敏感,因此非常适合于自动化操作。
关于RGB到YCbCr的快速转换,可以参考:颜色空间系列3: RGB和YCbCr颜色空间的转换及优化算法
由于在上述链接的文章中,YCbCr颜色空间已经被转换到[0,255],因此白色检测部分的第(6)条中的sign函数就不需要了。
同样,提供个编译好的文件给有兴趣研究该算法的朋友看看效果:
http://files.cnblogs.com/Imageshop/AutoWhiteBalance.zip
后记:
针对动态阈值法,很多朋友反映如果YCbCr的值量化在0到255之间的话会出现所有的像素都会被式(6)初步判断为白色参考点。这样前期的工作就失去了意义,算法就变成了类似于完美反射算法那了,稍微有点不同的地方就是两者选择两点的准则有所不同。虽然这样做的最终结果还算不错,但确实和论文的本意像违背了,后面经过实践,如果把YCbCr的值量化在-127到128之间,式6中的Sgn同样适用,则初步判断为白点的数会大量的减少,对于同一个图片,同一个参数两个算法的最终的效果比较如下:
更新后的下载链接依旧如下,以增加了修正后的功能。
***************************作者: laviewpbt 时间: 2013.4.20 联系QQ: 33184777 转载请保留本行信息*************************
【VS开发】【图像处理】基于灰度世界、完美反射、动态阈值等图像自动白平衡算法的原理、实现及效果的更多相关文章
- 亲测有效!一种完美动态阈值白平衡算法 Java实现。
几年没发文了,重新拿起技术! 最近做图像处理,要自动处理颜色平衡问题,很多什么直方图优化之类的,都不完美.所以在博客园找到了这个前辈的文章. http://www.cnblogs.com/Images ...
- 基于uFUN开发板的心率计(二)动态阈值算法获取心率值
前言 上一篇文章:基于uFUN开发板的心率计(一)DMA方式获取传感器数据,介绍了如何获取PulseSensor心率传感器的电压值,并对硬件电路进行了计算分析.心率计,重要的是要获取到心率值,本篇文章 ...
- 使用反射动态调用ActiveX控件
使用反射动态调用ActiveX控件 袁永福 2018-3-2 ■■■■问题描述: 目前的基于.NET平台的软件研发中仍然存在大量的对COM及ActiveX控件的调用.使用C#调用ActiveX控件时一 ...
- 基于 CGLIB 库的动态代理机制
之前的文章我们详细的介绍了 JDK 自身的 API 所提供的一种动态代理的实现,它的实现相对而言是简单的,但是却有一个非常致命性的缺陷,就是只能为接口中的方法完成代理,而委托类自己的方法或者父类中的方 ...
- winform快速开发平台 -> 通用权限管理之动态菜单
这几个月一直忙APP的项目,没来得及更新项目,想想该抽出时间整理一下开发思路,跟大家分享,同时也希望得到宝贵的建议. 先说一下我们的权限管理的的设计思路,首先一个企业信息化管理系统一定会用到权限管理, ...
- ecshop 完美解决动态ip登录超时和购物车清空问题
ecshop 完美解决动态ip登录超时和购物车清空问题 ECSHOP模板/ecshop开发中心(www.68ecshop.com) / 2014-05-06 前一段时间,ECSHOP开发中心的一个客户 ...
- .NET简谈反射(动态调用)
我们继续C#基础知识的学习,这篇文章主要要讲的是我们C#程序员迈向高级C#程序员的关键性的一步. 有的朋友会说事实不是这样的,我不用反射就不能开发吗?当然可以,但是用与不用肯定是不一样的,任何复杂抽象 ...
- Apache Solr采用Java开发、基于Lucene的全文搜索服务器
http://docs.spring.io/spring-data/solr/ 首先介绍一下solr: Apache Solr (读音: SOLer) 是一个开源.高性能.采用Java开发.基于Luc ...
- Java学习:注解,反射,动态编译
狂神声明 : 文章均为自己的学习笔记 , 转载一定注明出处 ; 编辑不易 , 防君子不防小人~共勉 ! Java学习:注解,反射,动态编译 Annotation 注解 什么是注解 ? Annotat ...
随机推荐
- :last-child的坑-CSS3选择器
CSS3选择器之:last-child - Eric 真实经历 最近开发项目的时候发现了一个这么多年忽略的问题,和大家分享一下.项目使用的是Antd组件库,有一个搜索框是这样的: 为了保证下拉框的内容 ...
- 关于深度学习之TensorFlow简单实例
1.对TensorFlow的基本操作 import tensorflow as tf import os os.environ[" a=tf.constant(2) b=tf.constan ...
- 浮点数的存储、类型转换知识点(面宝P34)
以float a=1.0f为例: (int)a实际上是以浮点数a为参数构造了一个整型数,该整数的值是1: (int&)a则是告诉编译器将a当作整数看(并没有做任何实质上的转换),即读a的内存时 ...
- ython CGI编程Ⅱ
HTTP头部 hello.py文件内容中的" Content-type:text/html"即为HTTP头部的https://www.xuanhe.net/一部分,它会发送给浏览器 ...
- jdk,jre下载安装
JDK安装https://blog.csdn.net/u012934325/article/details/73441617/jre需要手动生成在JDK安装目录下,的bin cmd执行bin\ jli ...
- Python GUI教程(六):使用Qt设计师进行窗口布局
本篇介绍使用qt设计师进行GUI窗口的布局管理,主要包含以下内容: 使用Qt设计师布局我们的窗口部件: 垂直布局: 水平布局: 网格布局: 使用间隔: 使用“伙伴”将label标签与窗口部件进行连接. ...
- confluence 附件docx文件 乱码处理
服务器安装字体库 Fontconfig是一个用于配置和自定义字体访问的库 yum -y install fontconfig 拷贝需要的字体文件 fonts.zip(或自己电脑中的字体文件c:/Win ...
- Codeforces 343D Water Tree & 树链剖分教程
原题链接 题目大意 给定一棵根为1,初始时所有节点值为0的树,进行以下三个操作: 将以某点为根的子树节点值都变为1 将某个节点及其祖先的值都变为0 *询问某个节点的值 解题思路 这是一道裸的树链剖分题 ...
- PTA 道长你想怎么死
道长你想怎么死 (25 分) 故事:[ 他身着白衣,撑着伞朝我走来.说要送我回家.而我早已陷入他那对深邃的眼眸中,心内一阵悸动.他一把拉我入伞下.我得知他是山上的道士,也刚好下山采药.他把伞赠予我,一 ...
- R_Studio(教师经济信息)逻辑回归分析的方法和技巧
使用R语言对"教师经济信息"进行逻辑回归分析 (1)按3:1的比例采用简单随机抽样方法,创建训练集和测试集 (2)用训练集创建逻辑回归模型 (3)用测试集预测贷款结果,并用tabl ...