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

图像直方图计算

所使用的图片如下所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M9HaoMqo-1582555944898)(https://i.imgur.com/4dMKhGF.png)]

主函数编辑:

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

直方图显示如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pq3f3EX7-1582555944899)(https://i.imgur.com/mUPmfn1.png)]

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

最终效果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HrH9bNF4-1582555944900)(https://i.imgur.com/mItsC9D.png)]
在这里插入图片描述

在这里插入图片描述

  • 4
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值