1. 程式人生 > >影象處理(二)直方圖均衡化

影象處理(二)直方圖均衡化

直方圖均衡化又稱直方圖修平,是一種很重要的非線性點運算。使用該方法可以加強影象的區域性對比度,尤其是當影象的有用資料的對比度相當接近的時候。通過這種方法,亮度可以更好的在直方圖上分佈。

直方圖均衡化的基本思想是把原始影象的直方圖變換為均勻分佈的形式。這樣增加了灰度值的動態範圍,從而達到增強影象整體對比度的效果。

演算法步驟:

1)計算影象f(x,y)的各灰度級中畫素出現的概率p(i)。

                 

2) 計算p的累計概率函式c(i),c即為影象的累計歸一化直方圖

                 

3)將c(i)縮放至0~255範圍內

                 

以下為演算法實現(C#)

 /// <summary>
    /// 直方圖均衡化 直方圖均衡化就是對影象進行非線性拉伸,重新分配影象畫素值,使一定灰度範圍內的畫素數量大致相同
    /// 增大對比度,從而達到影象增強的目的。是影象處理領域中利用影象直方圖對對比度進行調整的方法
    /// </summary>
    /// <param name="srcBmp">原始影象</param>
    /// <param name="dstBmp">處理後圖像</param>
    /// <returns>處理成功 true 失敗 false</returns>
    public static bool Balance(Bitmap srcBmp, out Bitmap dstBmp) {
        if (srcBmp == null) {
            dstBmp = null;
            return false;
        }
        int[] histogramArrayR = new int[256];//各個灰度級的畫素數R
        int[] histogramArrayG = new int[256];//各個灰度級的畫素數G
        int[] histogramArrayB = new int[256];//各個灰度級的畫素數B
        int[] tempArrayR = new int[256];
        int[] tempArrayG = new int[256];
        int[] tempArrayB = new int[256];
        byte[] pixelMapR = new byte[256];
        byte[] pixelMapG = new byte[256];
        byte[] pixelMapB = new byte[256];
        dstBmp = new Bitmap(srcBmp);
        Rectangle rt = new Rectangle(0, 0, srcBmp.Width, srcBmp.Height);
        BitmapData bmpData = dstBmp.LockBits(rt, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
        unsafe {
            //統計各個灰度級的畫素個數
            for (int i = 0; i < bmpData.Height; i++) {
                byte* ptr = (byte*)bmpData.Scan0 + i * bmpData.Stride;
                for (int j = 0; j < bmpData.Width; j++) {
                    histogramArrayB[*(ptr + j * 3)]++;
                    histogramArrayG[*(ptr + j * 3 + 1)]++;
                    histogramArrayR[*(ptr + j * 3 + 2)]++;
                }
            }
            //計算各個灰度級的累計分佈函式
            for (int i = 0; i < 256; i++) {
                if (i != 0) {
                    tempArrayB[i] = tempArrayB[i - 1] + histogramArrayB[i];
                    tempArrayG[i] = tempArrayG[i - 1] + histogramArrayG[i];
                    tempArrayR[i] = tempArrayR[i - 1] + histogramArrayR[i];
                }
                else {
                    tempArrayB[0] = histogramArrayB[0];
                    tempArrayG[0] = histogramArrayG[0];
                    tempArrayR[0] = histogramArrayR[0];
                }
                //計算累計概率函式,並將值放縮至0~255範圍內
                pixelMapB[i] = (byte)(255.0 * tempArrayB[i] / (bmpData.Width * bmpData.Height) + 0.5);//加0.5為了四捨五入取整
                pixelMapG[i] = (byte)(255.0 * tempArrayG[i] / (bmpData.Width * bmpData.Height) + 0.5);
                pixelMapR[i] = (byte)(255.0 * tempArrayR[i] / (bmpData.Width * bmpData.Height) + 0.5);
            }
            //對映轉換
            for (int i = 0; i < bmpData.Height; i++) {
                byte* ptr = (byte*)bmpData.Scan0 + i * bmpData.Stride;
                for (int j = 0; j < bmpData.Width; j++) {
                    *(ptr + j * 3) = pixelMapB[*(ptr + j * 3)];
                    *(ptr + j * 3 + 1) = pixelMapG[*(ptr + j * 3 + 1)];
                    *(ptr + j * 3 + 2) = pixelMapR[*(ptr + j * 3 + 2)];
                }
            }
        }
        dstBmp.UnlockBits(bmpData);
        return true;
    }

效果圖

補充(20160503):

直方圖均衡化是以累積分佈函式變換為基礎的一種直方圖修改方法。假定變換函式為

(1)

x 是積分變數,是r的累計分佈函式。且上式滿足:

(1)在r∈[0,1]內,T(r) 是單調增加的;

(2)對於0≤r≤1,有0≤T(r)≤1。

上式對r求導,得:

(2)

所以,通過上面得到推導可見,在變換後的變數S的定義域內的概率函式是均勻分佈的。因此,通過影象的累計分佈函式作為變換函式可以將影象的灰度級分佈調整為均勻分佈,結果就是增大了畫素取值的動態範圍,這就是直方圖均衡化的數學原理。