opencv_c++学习(十四)

一、图像直方图的统计与绘制

在这里插入图片描述
如果直方图各个数字之间分布比较均衡,则其对比度就相对较低,反之亦然。同时也可以通过直方图可以大致了解图像的亮暗等。

calcHist(const Mat * images, int nimages,  const int * channels, lnputArray mask, OutputArray hist, int dims, const int* histSize, const float ** ranges, bool accumullate = false)

images:待统计直方图的图像数组。
nimages:输入的图像数量。
channels:需要统计的通道索引数组。
mask:可选的操作掩码。
hist:输出的统计直方图结果,是一个dims维度的数组。
dims:需要计算直方图的维度,必须是整数。
histSize:存放每个维度直方图的数组的尺寸。
ranges:每个图像通道中灰度值的取值范围。
uniform:直方图是否均匀的标志符,默认状态下为均匀(true) 。
accumulate:是否累积统计直方图的标志。

直方图使用案例:

int main() {

	//读取图片
	Mat src1 = imread("1.png");
	if (!src1.data)
	{
		printf("不能打开空图片");
		return -1;
	}

	//将彩色图像转化为灰度图像
	Mat gray;
	cvtColor(src1, gray, COLOR_BGR2GRAY);

	//定义存放直方图计算结果的变量
	Mat hist;

	//定义通道的索引
	const int channels[1] = { 0 };

	//定义直方图的维度,为灰度图像的最大值
	const int bins[1] = { 256 };
	float inRanges[2] = { 0,255 };

	//像素灰度值的取值范围
	const float* ranges[1] = { inRanges };

	//计算直方图
	calcHist(&gray, 1, channels, Mat(), hist, 1, bins, ranges);

	//绘制直方图

	//直方图背景图的大小
	int hist_w = 512;
	int hist_h = 400;

	//直方图矩形柱的宽度
	int width = 2;

	Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);

	//分别绘制直方图的矩形柱

	//for (int i = 1; i < hist.rows; i++)
	//{
	//	//将原始数据缩放为15倍:hist.at<float>(i - 1) / 15)
	//	rectangle(histImage, Point(width*(i - 1), hist_h - 1), Point(width*i - 1, hist_h - cvRound(hist.at<float>(i - 1) / 15)), Scalar(255, 255, 255), -1);
	//}
	
	//将直方图数据进行归一化操作
	Mat hist_INF;
	normalize(hist, hist_INF, 1, 0, NORM_INF, -1, Mat());

	for (int i = 1; i < hist_INF.rows; i++)
	{
		//将原始数据缩放为15倍:hist.at<float>(i - 1) / 15)
		rectangle(histImage, Point(width*(i - 1), hist_h - 1), Point(width*i - 1, hist_h - cvRound(hist_h*hist_INF.at<float>(i - 1)) -1), Scalar(255, 255, 255), -1);
	}


	imshow("histImage", histImage);
	imshow("gray", gray);
	waitKey(0);
	return 0;

}

在这里插入图片描述

二、直方图均衡化

图像像素拉伸:

直方图均衡化函数:

equalizeHist(lnputArray src, OutputArray dst)

src:需要直方图均衡化的CV_8UC1图像。
dst:直方图均衡化后的输出图像,与src具有相同尺寸和数据类型。
使用样例如下:

void drawHist(Mat &hist, int type, string name)
{
	//直方图背景图的大小
	int hist_w = 512;
	int hist_h = 400;

	//直方图矩形柱的宽度
	int width = 2;

	Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);

	//归一化
	normalize(hist, hist, 1, 0, NORM_INF, -1, Mat());

	for (int i = 1; i < hist.rows; i++)
	{
		rectangle(histImage, Point(width*(i - 1), hist_h - 1), Point(width*i - 1, hist_h - cvRound(hist_h*hist.at<float>(i - 1)) - 1), Scalar(255, 255, 255), -1);
	}

	imshow(name, histImage);

}

int main() {

	//读取图片
	Mat src1 = imread("1.png");
	if (!src1.data)
	{
		printf("不能打开空图片");
		return -1;
	}
	
	Mat gray, hist, hist2;

	//将彩色图像转化为灰度图像
	cvtColor(src1, gray, COLOR_BGR2GRAY);

	Mat equalImg;

	//将图像均衡化
	equalizeHist(gray, equalImg);

	//定义通道的索引
	const int channels[1] = { 0 };

	//定义直方图的维度,为灰度图像的最大值
	const int bins[1] = { 256 };
	float inRanges[2] = { 0,255 };

	//像素灰度值的取值范围
	const float* ranges[1] = { inRanges };

	//计算直方图
	calcHist(&gray, 1, channels, Mat(), hist, 1, bins, ranges);
	calcHist(&equalImg, 1, channels, Mat(), hist2, 1, bins, ranges);

	//绘制直方图
	drawHist(hist, NORM_INF, "hist");
	drawHist(hist2, NORM_INF, "hist2");

	imshow("1", gray);
	imshow("2", equalImg);

	waitKey(0);
	return 0;

}

三、直方图匹配

在这里插入图片描述
具体实现细节如下:


void drawHist(Mat &hist, int type, string name)
{
	//直方图背景图的大小
	int hist_w = 512;
	int hist_h = 400;

	//直方图矩形柱的宽度
	int width = 2;

	Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);

	//归一化
	normalize(hist, hist, 1, 0, type, -1, Mat());

	for (int i = 1; i < hist.rows; i++)
	{
		rectangle(histImage, Point(width*(i - 1), hist_h - 1), Point(width*i - 1, hist_h - cvRound(20*hist_h*hist.at<float>(i - 1)) - 1), Scalar(255, 255, 255), -1);
	}

	imshow(name, histImage);

}


int main() {

	//读取图片
	Mat src = imread("1.png");
	Mat src1 = imread("1.png");
	if (src.empty() || src1.empty())
	{
		printf("不能打开空图片");
		return -1;
	}

	Mat hist, hist2;

	//定义通道的索引
	const int channels[1] = { 0 };

	//定义直方图的维度,为灰度图像的最大值
	const int bins[1] = { 256 };
	float inRanges[2] = { 0,255 };

	//像素灰度值的取值范围
	const float* ranges[1] = { inRanges };

	//计算直方图
	calcHist(&src, 1, channels, Mat(), hist, 1, bins, ranges);
	calcHist(&src1, 1, channels, Mat(), hist2, 1, bins, ranges);

	//绘制直方图
	drawHist(hist, NORM_INF, "hist");
	drawHist(hist2, NORM_INF, "hist2");

	//计算两张直方图的累计概率
	float hist1_cdf[256] = { hist.at<float>(0) };
	float hist2_cdf[256] = { hist2.at<float>(0) };
	for (int i = 0; i < 256; i++)
	{
		hist1_cdf[i] = hist1_cdf[i - 1] + hist.at<float>(i);
		hist2_cdf[i] = hist2_cdf[i - 1] + hist2.at<float>(i);
	}

	//构建累计概率误差矩阵
	float diff_cdf[256][256];
	for (int i = 0; i < 256; i++)
	{
		for (int j = 0; j < 256; j++)
		{
			diff_cdf[i][j] = fabs(hist1_cdf[i] - hist2_cdf[j]);
		}
	}

	//生成LUT映射表
	Mat lut(1, 256, CV_8U);

	for (int i = 0; i < 256; i++)
	{
		//查找源灰度级为1的映射灰度和i的累积概率差值最小的规定化灰度

		float min = diff_cdf[i][0];
		int index = 0;

		//寻找累积概率误差矩阵中每一行中的最小值
		for (int j = 0; j < 256; j++)
		{
			if (min > diff_cdf[i][j])
			{
				min = diff_cdf[i][j];
				index = j;
			}
		}
		lut.at<uchar>(i) = (uchar)index;
	}

	Mat result, hist3;
	LUT(src, lut, result);
	imshow("待匹配图像", src);
	imshow("匹配的模板图像", src1);
	imshow("直方图匹配结果", result);

	//计算直方图
	calcHist(&result, 1, channels, Mat(), hist3, 1, bins, ranges);
	drawHist(hist3, NORM_INF, "hist3");

	waitKey(0);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值