灰度圖的直方圖均衡化的原理及實現
阿新 • • 發佈:2019-01-04
直方圖均衡化的作用是影象增強。
有兩個問題比較難懂,一是為什麼要選用累積分佈函式,二是為什麼使用累積分佈函式處理後像素值會均勻分佈。
第一個問題。均衡化過程中,必須要保證兩個條件:①畫素無論怎麼對映,一定要保證原來的大小關係不變,較亮的區域,依舊是較亮的,較暗依舊暗,只是對比度增大,絕對不能明暗顛倒;
②如果是八點陣圖像,那麼畫素對映函式的值域應在0和255之間的,不能越界。綜合以上兩個條件,累積分佈函式是個好的選擇,因為累積分佈函式是單調增函式(控制大小關係),並且值域是0到1(控制越界問題),所以直方圖均衡化中使用的是累積分佈函式。
第二個問題。累積分佈函式具有一些好的性質,那麼如何運用累積分佈函式使得直方圖均衡化?
有兩個問題比較難懂,一是為什麼要選用累積分佈函式,二是為什麼使用累積分佈函式處理後像素值會均勻分佈。
第一個問題。均衡化過程中,必須要保證兩個條件:①畫素無論怎麼對映,一定要保證原來的大小關係不變,較亮的區域,依舊是較亮的,較暗依舊暗,只是對比度增大,絕對不能明暗顛倒;
②如果是八點陣圖像,那麼畫素對映函式的值域應在0和255之間的,不能越界。綜合以上兩個條件,累積分佈函式是個好的選擇,因為累積分佈函式是單調增函式(控制大小關係),並且值域是0到1(控制越界問題),所以直方圖均衡化中使用的是累積分佈函式。
第二個問題。累積分佈函式具有一些好的性質,那麼如何運用累積分佈函式使得直方圖均衡化?
比較概率分佈函式和累積分佈函式,前者的二維影象是參差不齊的,後者是單調遞增的。直方圖均衡化過程中,對映方法是:
其中,n是影象中畫素的總和,nk是當前灰度級的畫素個數,L是影象中可能的灰度級總數。
來看看通過上述公式怎樣實現的拉伸。假設有如下影象:
得影象的統計資訊如下圖所示,並根據統計資訊完成灰度值對映:
對映後的影象如下所示:
灰度直方圖均衡化實現的步驟:
1.統計灰度級中每個畫素在整幅影象中的個數
2.計算每個灰度級佔影象中的概率分佈
3.計算累計分佈概率
4.計算均衡化之後的灰度值
5.映射回原來畫素的座標的畫素值
放上原始碼:
原圖:#include<opencv2\opencv.hpp> #include<cmath> #include<iostream> using namespace cv; using namespace std; Mat MyequalizeHist(Mat &srcImage) { int nRows = srcImage.rows; int nCols = srcImage.cols; int nSumPix[256]; double nProDis[256]; double nSumProDis[256]; int EqualizeSumPix[256]; for (int i = 0; i < 256; i++) { nSumPix[i] = 0; nProDis[i] = 0.0; nSumProDis[i] = 0.0; EqualizeSumPix[i] = 0; } for (int i = 0; i < nRows; i++) { for (int j = 0; j < nCols; j++) { nSumPix[(int)srcImage.at<uchar>(i, j)]++; } } for (int i = 0; i < 256; i++) { nProDis[i] = (double)nSumPix[i] / (nRows * nCols); } nSumProDis[0] = nProDis[0]; for (int i = 1; i < 256; i++) { nSumProDis[i] = nSumProDis[i - 1] + nProDis[i]; } for (int i = 0; i < 256; i++) { EqualizeSumPix[i] = cvRound((double)nSumProDis[i] * 255); } Mat resultImage(nRows, nCols, srcImage.type()); for (int i = 0; i < nRows; i++) { for (int j = 0; j < nCols; j++) { resultImage.at<uchar>(i, j) = EqualizeSumPix[(int)srcImage.at<uchar>(i, j)]; } } return resultImage; } int main() { Mat srcIamge = imread("flower.jpg"); if (!srcIamge.data) { printf("image could not load...\n"); return -1; } Mat srcGray; //轉化為灰度圖並且顯示 cvtColor(srcIamge, srcGray, CV_BGR2GRAY); imshow("srcGray", srcGray); Mat resultImage = MyequalizeHist(srcGray); imshow("res", resultImage); waitKey(0); return 0; }
效果圖: