直方图均衡化程序 c++

本文介绍了一个使用OpenCV进行图像直方图计算和显示的方法,并实现了RGB图像的直方图均衡化来增强图像对比度。通过计算并显示原始图像及均衡化后的图像的直方图,展示了直方图均衡化对图像质量改善的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\core\core.hpp>
#include <iostream>
using namespace cv;
using namespace std;
Mat calchistcontrol(vector<Mat> rgb);
void draw(Mat hist, int histSize, Mat histImage, int bin_w, int hist_h, int rgb);
Mat getHistImg(const MatND& hist)
{
	double maxVal = 0;
	double minVal = 0;

	//找到直方图中的最大值和最小值
	minMaxLoc(hist, &minVal, &maxVal, 0, 0);
	int histSize = hist.rows;
	Mat histImg(histSize, histSize, CV_8U, Scalar(255));
	// 设置最大峰值为图像高度的90%
	int hpt = static_cast<int>(0.9*histSize);

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

	return histImg;
}
void main()
{
	Mat I;
	I = imread("D:\\ymrf\\enhance\\paper\\test_img\\flower.jpg");//ddd.png
	namedWindow("原始图像", 0);
	imshow("原始图像", I);
	int height = I.rows;
	int width = I.cols;
	Mat I_gray;
	cvtColor(I, I_gray, CV_BGR2GRAY);
	const int channels[3] = { 0,1,2 };
	const int channelsB[1] = { 0 };
	const int channelsG[1] = { 1 };	
	const int channelsR[1] = { 2 };
	const int histSizeI[3] = { 256,256,256};
	const int histSize[1] = { 256};
	float hranges[2] = { 0, 255 };
	const float* ranges[3] = { hranges};
	const float* rangesI[3] = { hranges, hranges, hranges };
	//MatND hist;
	//calcHist(&I, 1, channels, Mat(), hist, 1, histSizeI, ranges);
	//imshow("caise", getHistImg(hist));

	//MatND histgray;
	//calcHist(&I_gray, 1, channelsB, Mat(), histgray, 1, histSize, ranges);
	//imshow("gray", getHistImg(histgray));

	//MatND histB;
	//calcHist(&I, 1, channelsB, Mat(), histB, 1, histSize, ranges);
	//imshow("B", getHistImg(histB));

	//MatND histG;
	//calcHist(&I, 1, channelsG, Mat(), histG, 1, histSize, ranges);
	//imshow("G", getHistImg(histG));

	//MatND histR;
	//calcHist(&I, 1, channelsR, Mat(), histR, 1, histSize, ranges);
	//imshow("R", getHistImg(histR));
	/// 分割成3个单通道图像 ( R, G 和 B )
	Mat dst, rgb_merge, histImage, histImage1;

	vector<Mat> rgb_planes;
	split(I, rgb_planes);

	///直方图计算
	histImage = calchistcontrol(rgb_planes);

	///三个通道直方图均衡化
	vector<Mat> rgb_planes1;
	split(I, rgb_planes1);
	equalizeHist(rgb_planes1[0], rgb_planes1[0]);
	equalizeHist(rgb_planes1[1], rgb_planes1[1]);
	equalizeHist(rgb_planes1[2], rgb_planes1[2]);

	///三个通道直方图均衡化后直方图计算
	histImage1 = calchistcontrol(rgb_planes1);

	///合并三通道
	merge(rgb_planes1, rgb_merge);

	/// 显示直方图
	namedWindow("calcHist Demo", 0);
	namedWindow("calcHist Demo1", 0);
	namedWindow("rgb_merge" , 0);
	imshow("calcHist Demo", histImage);
	imshow("calcHist Demo1", histImage1);
	imshow("rgb_merge", rgb_merge);


	waitKey(0);
}


Mat calchistcontrol(vector<Mat> rgb)
{

	vector<Mat> rgb_planes;
	rgb_planes = rgb;
	/// 设定bin数目
	int histSize = 255;

	/// 设定取值范围 ( R,G,B) )
	float range[] = { 0, 255 };
	const float* histRange = { range };

	bool uniform = true; bool accumulate = false;

	Mat r_hist, g_hist, b_hist;

	/// 计算直方图:
	calcHist(&rgb_planes[0], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate);
	calcHist(&rgb_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate);
	calcHist(&rgb_planes[2], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate);

	// 创建直方图画布
	int hist_w = 400; int hist_h = 400;
	int bin_w = cvRound((double)hist_w / histSize);

	Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0));

	/// 将直方图归一化到范围 [ 0, histImage.rows ]
	normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
	normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
	normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());

	/// 在直方图画布上画出直方图
	draw(r_hist, histSize, histImage, bin_w, hist_h, 1);
	draw(g_hist, histSize, histImage, bin_w, hist_h, 2);
	draw(b_hist, histSize, histImage, bin_w, hist_h, 3);
	return histImage;
}
void draw(Mat hist, int histSize, Mat histImage, int bin_w, int hist_h, int rgb)
{
	Scalar a;
	switch (rgb)
	{
	case 1: a = Scalar(0, 0, 255); break;
	case 2: a = Scalar(0, 255, 0); break;
	case 3: a = Scalar(255, 0, 0); break;
	}
	int flag = 1, first;
	for (int i = 0; i < histSize; i++)
	{
		if (flag == 1)
		{
			if (cvRound(hist.at<float>(i) != 0))
			{
				flag = 2;
				first = i;
			}
			else
			{
				i++;
			}
		}
		else
		{
			if (cvRound(hist.at<float>(i) != 0))
			{
				line(histImage, Point(bin_w*(first), hist_h - cvRound(hist.at<float>(first))),
					Point(bin_w*(i), hist_h - cvRound(hist.at<float>(i))),
					a, 2, 8, 0);
				first = i;
			}
			else
			{
				i++;
			}
		}

	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值