自动色阶、自动对比度以及直方图均衡这三个算法虽然很普通,也很简单,可是在实际应用中有着很是高的使用率,特别是在修图中,不少设计师打开一幅图,首先的的操做就是Shift+Ctrl+L(自动色阶)。在原理实现上,他们都属于基于直方图统计方面的算法,执行效率都很是之高。我在调整图像- 自动对比度、自动色阶算法一文中对他们的过程进行了详细的分析和解读,这里不在详述。html
可是有的时候咱们发现自动色阶或对比度等等会过调整或欠调整,在某个软件(不记得是那个了)中我发现了对他们的一些改进方式,其核心改进以下:java
普通的方式:算法
for (int Y = 0; Y < 256; Y++) { if (Y < Min) Table[Y] = 0; else if (Y > Max) Table[Y] = 255; else Table[Y] = IM_ClampToByte((float)(Y - Min) / (Max - Min) * 255); }
改进后的方式:app
float Avg = 0, Mean = 0, Sum = 0; for (int Y = 0; Y < 256; Y++) { Sum += Histgram[Y]; Avg += Y * Histgram[Y]; } Mean = Avg / Sum; float Gamma = log(0.5f) / log((float)(Mean - Min) / (Max - Min)); if (Gamma < 0.1f) Gamma = 0.1f; else if (Gamma > 10) Gamma = 10; for (int Y = 0; Y < 256; Y++) { if (Y < Min) Table[Y] = 0; else if (Y > Max) Table[Y] = 255; else Table[Y] = IM_ClampToByte(pow((float)(Y - Min) / (Max - Min), Gamma) * 255); }
其中的Max和Min的意思请参考其余的文章。less
改进后的查找表考虑到全图的一个平均值信息,根据这个平局值来决定调整的一个Gamma值,至关于他同时结合了Gamma校订和自动色阶的思想,普通的自动色阶对应Gamma=1,仍是拿一些我经常使用的测试图举例吧。ide
原图 标准的自动色阶 改进后的自动色阶post
彷佛改进后的更为合理。测试
对于直方图均衡化的改进,我在ImageJ的代码中找到这样一段话:优化
// Changes the tone curves of images. // It should bring up the detail in the flat regions of your image. // Histogram Equalization can enhance meaningless detail and hide important but small high-contrast features. This method uses a // similar algorithm, but uses the square root of the histogram values, so its effects are less extreme. Hold the alt key down // to use the standard histogram equalization algorithm. This code was contributed by Richard Kirk (rak@cre.canon.co.uk). // ImageJ\source\ij\plugin\ContrastEnhancer.java
他的核心代码修改以下:url
private void equalize(ImageProcessor ip, int[] histogram) { ip.resetRoi(); if (ip instanceof ShortProcessor) { // Short max = 65535; range = 65535; } else { //bytes max = 255; range = 255; } double sum; sum = getWeightedValue(histogram, 0); for (int i=1; i<max; i++) sum += 2 * getWeightedValue(histogram, i); sum += getWeightedValue(histogram, max); double scale = range/sum; int[] lut = new int[range+1]; lut[0] = 0; sum = getWeightedValue(histogram, 0); for (int i=1; i<max; i++) { double delta = getWeightedValue(histogram, i); sum += delta; lut[i] = (int)Math.round(sum*scale); sum += delta; } lut[max] = max; applyTable(ip, lut); }
private double getWeightedValue(int[] histogram, int i) { int h = histogram[i]; if (h<2 || classicEqualization) return (double)h; return Math.sqrt((double)(h)); }
他这里主要是对直方图的数据进行了开根号,这样能够减小有些色阶特别集中的直方图对修正后的图像的影响,他能够解决普通的直方图均衡化有时候处理起来图像变换太大的问题,咱们一样以上述两幅图来作示范。
原图 标准的直方图均衡化 改进后的直方图均衡化
能够明显的看到,标准的直方图均衡化对两幅图的处理都太过度,而改进后的则效果要和谐和天然不少。
这种改进还能够嵌入到不少其余的和直方图有关的算法中,好比CLAHE等等,也能够有效的改进他们的效果。
本人的SSE算法优化合集DEMO: http://files.cnblogs.com/files/Imageshop/SSE_Optimization_Demo.rar。