openCV学习笔记(十)-- 直方图

1.什么是直方图?
在这里插入图片描述
在这里插入图片描述
举个例子:
在这里插入图片描述

2.直方图均衡化
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码:

//先要将图像转换为灰度图像
	cvtColor(src, gray_src, CV_BGR2GRAY);

	namedWindow("input_image", WINDOW_AUTOSIZE);
	namedWindow("output_Img", WINDOW_AUTOSIZE);
	imshow("input_image", gray_src);
	
	//直方图均衡化--一般用于提高图像对比度
	
	equalizeHist(gray_src, dst);
	imshow("output_Img", dst);

3.计算直方图及绘制直方图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

具体使用:

//计算并绘制直方图
	//先将多通道图片分通道表示--分成b,g,r
	vector<Mat> bgr_planes;
	split(src, bgr_planes);//分割好的图像,分别存在Mat数组的0,1,2位置

	//计算直方图
	int histSize = 256;//划分为256个等级
	float range[] = { 0,255 };//范围定义为0-255
	const float* histRanges = { range };
	Mat b_hist, g_hist, r_hist;//定义三个数组存储
	calcHist(&bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRanges, true, false);//计算直方图并存储到对应数组
	calcHist(&bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRanges, true, false);//计算直方图并存储到对应数组
	calcHist(&bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRanges, true, false);//计算直方图并存储到对应数组

	//图像归一化
	//归一化就是要把需要处理的数据经过处理后(通过某种算法)限制在你需要的一定范围内。
	//归一化数据
	int hist_h = 400;
	int hist_w = 512;
	int bin_w = hist_w / histSize;
	Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0));
	normalize(b_hist, b_hist, 0, hist_h, NORM_MINMAX, -1, Mat());//0-下限 , hist_h归一化范围上限
	normalize(g_hist, g_hist, 0, hist_h, NORM_MINMAX, -1, Mat());
	normalize(r_hist, r_hist, 0, hist_h, NORM_MINMAX, -1, Mat());

	//画出直方图
	for (int i = 1; i < histSize; i++)
	{
		//直方图从左下角开始
		//cvRound():返回跟参数最接近的整数值,即四舍五入
		line(histImage, Point((i - 1) * bin_w, hist_h - cvRound(b_hist.at<float>(i - 1))),
			Point((i)*bin_w, hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2, LINE_AA);
		line(histImage, Point((i - 1) * bin_w, hist_h - cvRound(g_hist.at<float>(i - 1))),
			Point((i)*bin_w, hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2, LINE_AA);
		line(histImage, Point((i - 1) * bin_w, hist_h - cvRound(r_hist.at<float>(i - 1))),
			Point((i)*bin_w, hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2, LINE_AA);

	}
	imshow("output_img", histImage);

在完成以上步骤后,就可以通过API画出一个分别对于BGR三通道的直方图
在这里插入图片描述

4.直方图比较
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

具体直方图对比步骤:
在这里插入图片描述
在这里插入图片描述
具体代码:

	//直方图比较
	Mat base, test1, test2;
	Mat hsvbase, hsvtest1, hsvtest2;

	base = imread("C:/Users/18929/Desktop/博客项目/项目图片/08.jpg");
	test1 = imread("C:/Users/18929/Desktop/博客项目/项目图片/01.jpg");
	test2 = imread("C:/Users/18929/Desktop/博客项目/项目图片/07.jpg");

	//1.先转换为HSV图像
	cvtColor(base, hsvbase, CV_BGR2HSV);
	cvtColor(test1, hsvtest1, CV_BGR2HSV);
	cvtColor(test2, hsvtest2, CV_BGR2HSV);

	//设置hue大小为50,saturation(饱和度)值为60
	int h_bins = 50; int s_bins = 60;
	int histSize[] = { h_bins,s_bins };
	//hue值的范围从0-179,饱和度从0-255
	float h_ranges[] = { 0,180 };
	float s_ranges[] = { 0,256 };
	const float* ranges[] = { h_ranges,s_ranges };//范围要用const声明
	//使用第零通道到第一通道
	int channels[] = { 0,1 };

	//MatND -- 多维的Mat对象 Mat-二维,存放直方图的值
	MatND hist_base;
	MatND hist_test1;
	MatND hist_test2;


	//计算出直方图的值
	calcHist(&hsvbase, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false);
	normalize(hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat());

	calcHist(&hsvtest1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false);
	normalize(hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat());

	calcHist(&hsvtest2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false);
	normalize(hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat());

	//比较直方图
	double basebase = compareHist(hist_base, hist_base, CV_COMP_CORREL);//相关性比较,越接近1越相似
	double basetest1 = compareHist(hist_base, hist_test1, CV_COMP_BHATTACHARYYA);//巴氏比较,越接近1越相似
	double basetest2 = compareHist(hist_base, hist_test2, CV_COMP_BHATTACHARYYA);
	double test1test2 = compareHist(hist_test1, hist_test2, CV_COMP_BHATTACHARYYA);

	//在图上写结果
	Mat test12;
	test2.copyTo(test12);//做一张和test2一样的图
	putText(base, convertToString(basebase), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);
	putText(test1, convertToString(basetest1), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);
	putText(test2, convertToString(basetest2), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);
	putText(test12, convertToString(test1test2), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);

	namedWindow("base", CV_WINDOW_AUTOSIZE);
	namedWindow("test1", CV_WINDOW_AUTOSIZE);
	namedWindow("test2", CV_WINDOW_AUTOSIZE);
	namedWindow("test12", CV_WINDOW_AUTOSIZE);

	imshow("base", base);
	imshow("test1", test1);
	imshow("test2", test2);
	imshow("test12", test12);

	waitKey(0);
	return 0;

}

//将计算出来的double值转换为字符串打印
string convertToString(double d) {
	ostringstream os;
	if (os << d)
		return os.str();
	return "invalid conversion";
}
*/

5.直方图反向映射
https://blog.csdn.net/keith_bb/article/details/70154219
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include<opencv2/opencv.hpp>
#include<math.h>
#include<iostream>

using namespace cv;
using namespace std;


Mat src,dst,gray_src,hsv,hue;
int bins = 12;//定义维度,即分成多少份定义直方图
void Hist_And_Backprojection(int, void*);
int main(int argc, char** argv) {
	src = imread("C:/Users/18929/Desktop/博客项目/项目图片/01.jpg");
	if (src.empty()) {
		printf("could not load image");
		return -1;
	}
	const char* window_image = "input image";
	namedWindow(window_image, WINDOW_AUTOSIZE);

	//直方图反向映射
	//1.转换图片为hsv类图片
	cvtColor(src, hsv, CV_BGR2HSV);
	//2.将hsv图像的第一通道拷贝到hue图片的第一通道,且拷贝一组
	hue.create(hsv.size(), hsv.depth());
	int nchannels[] = { 0,0 };//定义从第一通道拷贝到第一通道
	mixChannels(&hsv, 1, &hue, 1, nchannels, 1);//1个hsv图像,1个hue图像,按nchannels规则拷贝一组

	createTrackbar("Histogram Bins:",window_image,&bins,180,Hist_And_Backprojection);
	Hist_And_Backprojection(0, 0);

	imshow(window_image, src);
	
	waitKey(0);
	return 0;

}
void Hist_And_Backprojection(int, void*) {
	//计算直方图
	float range[] = { 0,180 };//定义划分直方图范围
	const float* histRanges = { range };
	Mat h_hist;
	calcHist(&hue, 1, 0, Mat(), h_hist, 1, &bins, &histRanges, true, false);
	normalize(h_hist, h_hist, 0, 255, NORM_MINMAX, -1, Mat());

	//绘制直方反向映射图
	Mat backPrjImage;//直方映射图
	calcBackProject(&hue, 1, 0, h_hist, backPrjImage, &histRanges, 1, true);
	/*
		参数解释:
	1.const Mat* images:输入图像,图像深度必须位CV_8U,CV_16U或CV_32F中的一种,尺寸相同,每一幅图像都可以有任意的通道数
	2.int nimages:输入图像的数量
	3.const int* channels:用于计算反向投影的通道列表,通道数必须与直方图维度相匹配,第一个数组的通道是从0到image[0].channels()-1,第二个数组通道从图像image[0].channels()到image[0].channels()+image[1].channels()-1计数
	4.InputArray hist:输入的直方图,直方图的bin可以是密集(dense)或稀疏(sparse)
	5.OutputArray backProject:目标反向投影输出图像,是一个单通道图像,与原图像有相同的尺寸和深度
	6.const float ranges**:直方图中每个维度bin的取值范围
	7.double scale=1:可选输出反向投影的比例因子
	8.bool uniform=true:直方图是否均匀分布(uniform)的标识符,有默认值true
	*/
	imshow("BackProj", backPrjImage);

	
	//绘制直方图
	int hist_h = 400;
	int hist_w = 400;
	Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0));
	int bin_w = (hist_w / bins);//每个bins的宽度
	for (int i = 1; i < bins; i++) {
		rectangle(histImage, Point((i - 1) * bin_w, (hist_h - cvRound(h_hist.at<float>(i - 1) * 400 / 255))),
			Point((i)*bin_w, (hist_h - cvRound(h_hist.at<float>(i) * 400 / 255))), Scalar(0, 0, 255), -1);

	}
	imshow("Histogram", histImage);

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值