【算法隨記四】自動色階、對比度、直方圖均衡等算法的一些小改進。 調整圖像- 自動對比度、自動色階算法

  自動色階、自動對比度以及直方圖均衡這三個算法雖然很普通,也很簡單,但是在實際應用中有着非常高的使用率,特別是在修圖中,很多設計師打開一幅圖,首先的的操作就是Shift+Ctrl+L(自動色階)。在原理實現上,他們都屬於基於直方圖統計方面的算法,執行效率都非常之高。我在調整圖像- 自動對比度、自動色階算法一文中對他們的過程進行了詳細的分析和解讀,這裏不在詳述。

  但是有的時候我們發現自動色階或對比度等等會過調整或欠調整,在某個軟件(不記得是那個了)中我發現了對他們的一些改進方式,其核心改進如下:

       普通的方式:

    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);
    }

  改進後的方式:

    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的意思請參考其他的文章。

  改進後的查找表考慮到全圖的一個平均值信息,根據這個平局值來決定調整的一個Gamma值,相當於他同時結合了Gamma校正和自動色階的思想,普通的自動色階對應Gamma=1,還是拿一些我常用的測試圖舉例吧。

      

      

            原圖                      標準的自動色階                          改進後的自動色階

  似乎改進後的更爲合理。

  對於直方圖均衡化的改進,我在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 ([email protected]).
//    ImageJ\source\ij\plugin\ContrastEnhancer.java

  他的核心代碼修改如下:

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

       

 

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章