1. 程式人生 > >OpenCV數字影象處理(一)——直方圖均衡化的實現

OpenCV數字影象處理(一)——直方圖均衡化的實現

計算一幅影象的直方圖

影象是由不同數值的顏色畫素組成,畫素值在整幅影象中的分佈情況是該影象的一個重要屬性。直方圖(Histogram)是一幅影象分佈的精確圖形表示。因此,灰度影象的直方圖有256個專案。

OpenCV計算直方圖

  • 環境:Windows 10, Microsoft Visual Studio 2015

Histogram1D類的建立

OpenCV可以簡單地呼叫 cv:calcHist 函式來進行直方圖計算,我們建立一個專用類來處理單通道灰度影象的類。

class Histogram1D {

private:

	int histSize[1];
	float hranges[2];
	const float* ranges[1];
	int channels[1];

public:

	Histogram1D() {
		histSize[0] = 256;
		hranges[0] = 0.0;
		hranges[1] = 256.0;
		ranges[0] = hranges;
		channels[0] = 0;
	}

	Mat getHistogram(const Mat &image) {
		Mat hist;
		calcHist(&image, 1, channels, Mat(), hist, 1, histSize, ranges);
		return hist;
	}

	Mat getHistogramImage(const Mat &image, int zoom = 1) {
		Mat hist = getHistogram(image);
		return getImageOfHistogram(hist, zoom);
	}

	static Mat getImageOfHistogram(const Mat &hist, int zoom) {
		double maxVal = 0;
		double minVal = 0;
		minMaxLoc(hist, &minVal, &maxVal, 0, 0);

		int histSize = hist.rows;
		Mat histImg(histSize*zoom, histSize*zoom, CV_8U, Scalar(255));
		int hpt = static_cast<int>(0.9*histSize);

		for (int h = 0; h < histSize; h++) {
			float binVal = hist.at<float>(h);
			if (binVal > 0) {
				int intensity = static_cast<int>(binVal*hpt / maxVal);
				line(histImg, Point(h*zoom, histSize*zoom),
					Point(h*zoom, (histSize - intensity)*zoom), Scalar(0), zoom);
			}
		}
		return histImg;
	}
};

影象直方圖計算

所使用的圖片如下所示:

主函式編輯:

int main()
{
	Mat image = imread("Fig3.15(a)1top.BMP", 0);
	Histogram1D h;
	Mat histo = h.getHistogram(image);
	for (int i = 0; i < 256; i++)
	{
		cout << "Value " << i << " = " << histo.at<float>(i) << endl;
	}
	namedWindow("Histogram");
	imshow("Histogram", h.getHistogramImage(image));
	waitKey(0);
	return 0;
}

輸出的值非0的結果:

Value 12 = 477
Value 13 = 16986
Value 14 = 379
Value 15 = 572
Value 16 = 1917
Value 17 = 8955
Value 18 = 2129
Value 19 = 16228
Value 20 = 10188
Value 21 = 3327
Value 22 = 5751
Value 23 = 1406
Value 24 = 4224
Value 25 = 1266
Value 26 = 4332
Value 27 = 2539
Value 28 = 2830
Value 29 = 5529
Value 30 = 2141
Value 31 = 3653
Value 32 = 2187
Value 33 = 4142
Value 34 = 3227
Value 35 = 5808
Value 36 = 3019
Value 37 = 4913
Value 38 = 6980
Value 39 = 4303
Value 40 = 3729
Value 41 = 4048
Value 42 = 6398
Value 43 = 1849
Value 44 = 6581
Value 45 = 1762
Value 46 = 6731
Value 47 = 9532
Value 48 = 3374
Value 49 = 5324
Value 50 = 2989
Value 51 = 4945
Value 52 = 3840
Value 53 = 3528
Value 54 = 3609
Value 55 = 5614
Value 56 = 5712
Value 57 = 1385
Value 58 = 4312
Value 59 = 2731
Value 60 = 3788
Value 61 = 1018
Value 62 = 3184
Value 63 = 863
Value 64 = 1910
Value 65 = 3471
Value 66 = 2638
Value 67 = 697
Value 68 = 2341
Value 69 = 1434
Value 70 = 1339
Value 71 = 1378
Value 72 = 1744
Value 73 = 971
Value 74 = 2267
Value 75 = 1460
Value 76 = 861
Value 77 = 909
Value 78 = 158
Value 79 = 141
Value 80 = 16
Value 81 = 9
Value 82 = 1
Value 83 = 1

直方圖顯示如下:

OpenCV直方圖均衡

OpenCV提供了一個直方圖均衡化的函式 cv::equalizeHist(image,result),我們通過使用這個函式來實現直方圖均衡化,通過修改下面main函式:

int main()
{
	Mat image = imread("Fig3.15(a)1top.BMP", 0);
	Histogram1D h;
	Mat histo = h.getHistogram(image);
	for (int i = 0; i < 256; i++)
	{
		if (histo.at<float>(i) != 0) 
			cout << "Value " << i << " = " << histo.at<float>(i) << endl;
	}
	namedWindow("Histogram");
	imshow("Histogram", h.getHistogramImage(image));
	/*namedWindow("Cell");
	imshow("Cell", image);
	equalizeHist(image, image);
	namedWindow("CellequalizeHist");
	imshow("CellequalizeHist", image);
	namedWindow("Histogram2");
	imshow("Histogram2", h.getHistogramImage(image));*/
	waitKey(0);
	return 0;
}

最終效果如下: