亲测有效!一种完美动态阈值白平衡算法 Java实现。
几年没发文了,重新拿起技术!
最近做图像处理,要自动处理颜色平衡问题,很多什么直方图优化之类的,都不完美。所以在博客园找到了这个前辈的文章。
http://www.cnblogs.com/Imageshop/archive/2013/04/20/3032062.html#commentform
基于灰度世界、完美反射、动态阈值等图像自动白平衡算法的原理、实现及效果
很可惜,这篇文章,首先没有源码,其次给出的一些计算过程有问题。所以我直接查看论文原文,以及一些映射公式,现在分享Java实现的版本:
核心算法:
BufferedImage img = ImageIO.read(new File("model3.jpg"));
int pixelsize = img.getWidth() * img.getHeight();
double[][][] YCbCr = new double[img.getWidth()][img.getHeight()][3];
double Mr = 0, Mb = 0, Ymax = 0;
for (int i = 0; i < img.getWidth(); i++) {
for (int j = 0; j < img.getHeight(); j++) {
YCbCr[i][j] = toYCbCr(img.getRGB(i, j));
Mr += YCbCr[i][j][2];
Mb += YCbCr[i][j][1];
Ymax = Math.max(Ymax, YCbCr[i][j][0]);
}
}
Mr /= pixelsize;
Mb /= pixelsize;
double Dr = 0, Db = 0;
for (int i = 0; i < YCbCr.length; i++) {
for (int j = 0; j < YCbCr[i].length; j++) {
Db += Math.abs(YCbCr[i][j][1] - Mb);
Dr += Math.abs(YCbCr[i][j][2] - Mr);
}
}
Dr /= pixelsize;
Db /= pixelsize;
double[][] Y = new double[img.getWidth()][img.getHeight()];
double[] Yhistogram = new double[256];
double Ysum = 0;
for (int i = 0; i < Y.length; i++) {
for (int j = 0; j < Y[i].length; j++) {
int value = (Math.abs(YCbCr[i][j][1] - (Mb + Db * Math.signum(Mb))) < 1.5 * Db) & //
(Math.abs(YCbCr[i][j][2]) - (1.5 * Mr + Dr * Math.signum(Mr))) < 1.5 * Dr ? 1 : 0;
if (value <= 0)
continue;
double y = YCbCr[i][j][0];
Y[i][j] = y;
Yhistogram[(int) Y[i][j]]++;
Ysum++;
}
}
double Yhistogramsum = 0;
double Ymin = 0;
for (int i = Yhistogram.length - 1; i >= 0; i--) {
Yhistogramsum += Yhistogram[i];
if (Yhistogramsum > 0.1 * Ysum) {
Ymin = i;
break;
}
}
double Raver = 0, Gaver = 0, Baver = 0;
double averSum = 0;
for (int i = 0; i < Y.length; i++) {
for (int j = 0; j < Y[i].length; j++) {
if (Y[i][j] > Ymin) {
int color = img.getRGB(i, j);
int r = (color >> 16) & 0xFF;
int g = (color >> 8) & 0xFF;
int b = color & 0xFF;
Raver += r;
Gaver += g;
Baver += b;
averSum++;
}
}
}
Raver /= averSum;
Gaver /= averSum;
Baver /= averSum;
double Rgain = Ymax / Raver, Ggain = Ymax / Gaver, Bgain = Ymax / Baver;
for (int i = 0; i < img.getWidth(); i++) {
for (int j = 0; j < img.getHeight(); j++) {
Color color = new Color(img.getRGB(i, j));
int r = ensureColor((int) Math.floor(color.getRed() * Rgain));
int g = ensureColor((int) Math.floor(color.getGreen() * Ggain));
int b = ensureColor((int) Math.floor(color.getBlue() * Bgain));
img.setRGB(i, j, new Color(r, g, b).getRGB());
}
}
ImageIO.write(img, "jpg", new File("xxx.jpg"));
其中计算YCrCb的算法如下:
// https://mathematica.stackexchange.com/questions/29786/how-to-convert-rgb-to-ycbcr
private double[] toYCbCr(int color) { int r = (color >> 16) & 0xFF;
int g = (color >> 8) & 0xFF;
int b = color & 0xFF; double Y = 16 + (65.481 * r / 255 + 128.553 * g / 255 + 24.966 * b / 255);
double Cb = 128 + (-37.797 * r / 255 - 74.203 * g / 255 + 112 * b / 255);
double Cr = 128 + (112 * r / 255 - 93.786 * g / 255 - 18.214 * b / 255); return new double[] { Y, Cb, Cr };
}
最后还有一个像素范围检测:
private int ensureColor(double color) {
if (color < 0)
return 0;
if (color > 255)
return 255;
return (int) color;
}
实际效果:
|
|
|
![]() |
![]() |
效果非常好。我也看了下原作者的问题,应该是计算YCrCb出错了。
本次分享完毕啦!好几年没有在博客园发文了,说下近况了。第一次进博客园是10多年前,在上海交大读研究生的一个穷小孩。研究生毕业之后一直磕磕碰碰在创业,到了现在36了,仍然在创业。也许将来创业成功了,这些博客都能成为励志经历。不成功,那就继续努力。
最近正在投身微信公众号,也小有成就,做了全国最大的乐高公众号。希望将来有一天能有所成。
感谢各位园友的阅读,希望这篇文章有帮助!
亲测有效!一种完美动态阈值白平衡算法 Java实现。的更多相关文章
- matlab 自动阈值白平衡算法 程序可编译实现
一种效果很好的自动白平衡技术(WhiteBalance) 白平衡是图像处理的一个极重要概念.所谓白平衡(英文名称为White Balance),就是对白色物体的还原.当我们用肉眼观看这大千世界时,在不 ...
- 【VS开发】【图像处理】基于灰度世界、完美反射、动态阈值等图像自动白平衡算法的原理、实现及效果
基于灰度世界.完美反射.动态阈值等图像自动白平衡算法的原理.实现及效果 白平衡是电视摄像领域一个非常重要的概念,通过它可以解决色彩还原和色调处理的一系列问题.白平衡是随着电子影像再现色彩真实 ...
- 中兴iptv机顶盒破解教程图文:亲测中兴B760EV3、B860A、B860AV1.1完美安装应用!非ttl破解![转]
一直以为中兴的这几个盒子只能通过ttl来破解,不过现在再也不用这么麻烦了,有了这个工具,前后破解不超3分钟!理论上支持所有中兴的iptv机顶盒的破解! 亲测中兴B760EV3.B860A.B860AV ...
- MyEclipse8.6启动后提示内存不足的解决方案(亲测,完美解决)
转自:http://www.bubuko.com/infodetail-1625857.html 最近可能由于公司项目大了,启动MyEclipse后经常提示内存不足的警告框,如下: 其实点击close ...
- (链接)IDEA 2018 激活 IDEA 2018.3激活教程 最新的(三种)—2018.11.26亲测
破解不成功的请注意时效性,写于2019/2/8,以下第一种激活方法亲测可用, 不过有时候破解成功了可能过几天突然就打不开了,双击无反应的说,这时候再按顺序 操作一遍就是了: 1)把idea64.exe ...
- mac下高效安装 homebrew 及完美避坑姿势 (亲测有效)
世上无难事,只要找到 Homebrew 的正确安装方式. Homebrew 是什么 Homebrew是 mac的包管理器,仅需执行相应的命令,就能下载安装需要的软件包,可以省掉自己去下载.解压.拖拽( ...
- Sublime Text3 最新版本V3.1.1 build3117注册码,亲测可以完美激活~
Sublime Text 3 最新注册码 官网下载的最新版本V3.1.1 build3117,亲测以下注册码可以正常激活 ----- BEGIN LICENSE ----- sgbteam Singl ...
- 获取UIColor中的RGB值(本人亲测多个获取RGB值的方法,这个最有效)
在自己研发的项目个人项目中,碰到一个从颜色中获取RGB值的需求. 在网上找了许久,也有一些方法可以获取RGB值,但不能获取黑白以及灰色的值(他们是非RGB颜色空间,不清楚什么意思,反正亲测确实获取不了 ...
- VS 2013驱动开发 + Windbg + VM双机调试(亲测+详解)
------------VS 2013驱动开发 + Windbg + VM双机调试(亲测+详解)------------- WIN10已上线,随之而来的是VS2015:微软在 "WDK760 ...
随机推荐
- Java (PO,VO,DAO,BO,POJO,DTO) 几种对象解释
1. PO:persistant object 持久对象 可以看成是与数据库中的表相映射的java对象.最简单的PO就是对应数据库中某个表中的一条记录,多个记录可以用PO的集合.PO中应该不包含任何对 ...
- 最常用的缓存技术---redis入门
Redis简介 Redis是基于内存,也可以基于磁盘持久化nosql数据库,使用c语言开发. 数据存储结构:key-value 安装环境准备 Redis使用c语言开发,需要使用gcc编译程序进行编 ...
- Arduino编译bootloader
最近打算自己定制一个Arduino的板子,改改Arduino的烧写机制.好在bootloader都是有源代码的,说干就干,改写前当然要试试这个源码能不能编译,可是到了bootloader目录就茫然了. ...
- kairosdb + cassandra Setup
安装cassandra 下载 cassandra cassandra download mirror wget http://mirror.bit.edu.cn/apache/cassandra/2. ...
- R语言快速深度学习进行回归预测(转)
深度学习在过去几年,由于卷积神经网络的特征提取能力让这个算法又火了一下,其实在很多年以前早就有所出现,但是由于深度学习的计算复杂度问题,一直没有被广泛应用. 一般的,卷积层的计算形式为: 其中.x分别 ...
- Python爬虫学习(二) ——————爬取前程无忧招聘信息并写入excel
作为一名Pythoner,相信大家对Python的就业前景或多或少会有一些关注.索性我们就写一个爬虫去获取一些我们需要的信息,今天我们要爬取的是前程无忧!说干就干!进入到前程无忧的官网,输入关键字&q ...
- 《物联网框架ServerSuperIO教程》-19.设备驱动和OPC Client支持mysql、oracle、sqlite、sqlserver的持久化。v3.6.4版本发布
19.设备驱动和OPC Client支持mysql.oracle.sqlite.sqlserver的持久化 19.1 概述 ServerSuperIO支持设备驱动和OPC Client采集的数 ...
- Windows下用Composer引入官方GitHub扩展包
Windows下用Composer引入官方GitHub扩展包 1. 当你打开威武RC4版本的链接的时候,往下拉你可以看到这个,然后你要做的就是想到,百度Composer,看看是个什么鬼,别想太多,跟着 ...
- 平时常用的一些java方法,请留意
平时常用的一些java方法,请留意. package com.util; import java.io.BufferedInputStream; import java.io.BufferedWrit ...
- 调试JDK源码时,不能查看变量的值
前几天本来想以debug模式看一下JDK的源码,进入调试模式时才发现,根本看不到方法里面变量值的情况.为什么呢?JDK现在的版本中,编译过后,去除了里面的调试信息.解决办法是,编译那些类,使其带有调试 ...


