自動色階、自動對比度以及直方圖均衡這三個算法雖然很普通,也很簡單,可是在實際應用中有着很是高的使用率,特別是在修圖中,不少設計師打開一幅圖,首先的的操做就是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。