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;
}
原圖:



效果圖: