博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
亲测有效!一种完美动态阈值白平衡算法 Java实现。
阅读量:6050 次
发布时间:2019-06-20

本文共 4232 字,大约阅读时间需要 14 分钟。

几年没发文了,重新拿起技术!

最近做图像处理,要自动处理颜色平衡问题,很多什么直方图优化之类的,都不完美。所以在博客园找到了这个前辈的文章。

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了,仍然在创业。也许将来创业成功了,这些博客都能成为励志经历。不成功,那就继续努力。

最近正在投身微信公众号,也小有成就,做了全国最大的乐高公众号。希望将来有一天能有所成。

 

感谢各位园友的阅读,希望这篇文章有帮助!

你可能感兴趣的文章
tomcat 性能调优
查看>>
docker 容积硬盘扩容小坑一个
查看>>
输入10个整数,程序找出其中的最大值和最小值
查看>>
中科红旗之死--国产软件界最大不幸
查看>>
启动jboss报jdk错误
查看>>
统计PV、UV
查看>>
【实战】锐捷AC+AP配置WLAN基本服务系列
查看>>
window基础-1:win7开机按ctrl+alt+delete启动
查看>>
《大话无线通信》
查看>>
XMPP Openfire集成windows身份认证
查看>>
无线POS机的原理及应用
查看>>
使用 netbeans 为 Java/JavaFX 程序生成启动器(exe)或者安装程序(exe,msi)
查看>>
python中的if__name__== "__main__"
查看>>
我的友情链接
查看>>
SaltStack 学习笔记 - 第二篇: Salt-master配置文件详解
查看>>
oracle 物理读 逻辑读的理解
查看>>
win10连接宽带,拨号提示错误720:不能建立到远程计算机的连接,解决方法
查看>>
python基础(三)——类的研究
查看>>
mysql 转数据类型
查看>>
第二阶段冲刺6
查看>>