opencv3.0.1+vs2015——直方图均衡化、直方图计算、直方图的比较

(一)直方图均衡化

在这里插入图片描述
图像直方图是指对整个图像在灰度范围内的像素值(0~255)统计出现频率次数,据此生成的直方图,称为图像直方图。直方图反映了图像灰度的分布情况。是图像的统计学特征。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

直方图均衡化API说明
在这里插入图片描述
直方图均衡化的demo如下所示:

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
	Mat src, dst;
	src = imread("D:/studytest/lena.jpg");
	if (src.empty())
	{
		printf("could not load image...\n");
		return -1;
	}
	namedWindow("input image", CV_WINDOW_AUTOSIZE);
	namedWindow("output image", CV_WINDOW_AUTOSIZE);
	Mat gray_src;
	cvtColor(src, gray_src, CV_BGR2GRAY);//转化为灰度图像
	equalizeHist(gray_src, dst);//直方图均衡化
	imshow("input image", src);
	imshow("gray image", gray_src);
	imshow("output image", dst);
	waitKey(0);
	return 0;
}

在这里插入图片描述

(二)直方图计算

API学习:
split(const Mat &src,Mat *mvbegin);//把多通道图像分为多个单通道图像
其中,src是输入图像,mvbegin是输出的通道图像数组

calcHist(const Mat* images, int images, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false );//计算图像直方图
参数说明:
const Mat* images:输入图像
int images:输入图像的个数
const int* channels:需要统计直方图的第几通道
InputArray mask:掩膜,计算掩膜内的直方图 …Mat()
OutputArray hist:输出的直方图数组
int dims:需要统计直方图通道的个数
const int* histSize:直方图级数,指的是直方图分成多少个区间,就是 bin的个数
const float** ranges: 统计像素值得区间
bool uniform=true:是否对得到的直方图数组进行归一化处理
bool accumulate=false:在多个图像时,是否累计计算像素值得个数

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
	Mat src, dst;
	src = imread("D:/studytest/lena.jpg");//读取一张图像
	if (src.empty())//判断是否成功读取一张图像
	{
		printf("could not load image...\n");
		return -1;
	}
	namedWindow("input image", CV_WINDOW_AUTOSIZE);
	namedWindow("output image", CV_WINDOW_AUTOSIZE);
	imshow("input image", src);//显示输入的图像
	//分通道显示
	vector<Mat> bgr_planes; //定义一个Mat数组
	split(src, bgr_planes);//将src划分到各个同道中
	//计算直方图
	int histSize = 256;//直方图级数
	float range[] = { 0,256 };
	const float *histRanges = { range };//像素区间
	Mat b_hist, g_hist, r_hist;//b,g,r的直方图图像
	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));//一张纯黑色的3通道大小宽为hist_w,高为hist_h的图像
	normalize(b_hist, b_hist, 0, hist_h, NORM_MINMAX, -1, Mat());
	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()是四舍五入,cvFloor()是向下取整,cvCeil()是向上取整
		//直角坐标系(x从左到右增加,y从下到上增加)、屏幕坐标系(x从左到右增加,y从上到下增加),人眼看的是直角坐标系,而电脑采用屏幕坐标系,所以方便人眼去看,我们将屏幕坐标系转换为直角坐标系
		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 image", histImage);
	waitKey(0);
	return 0;
}

输出图像如下图所示:
在这里插入图片描述

(三)直方图的比较

直方图比较方法——概述
对输入的两张图像计算得到直方图H1与H2,归一化到相同的尺度空间,然后可以通过计算H1与H2之间的距离得到两个直方图的相似程度进而比较图像本身的相似程度。opencv提供的比较方法有四种:
①Correlation 相关性比较
②Chi-Square 卡方比较
③Intersection 十字交叉性
④Bhattacharyya distance 巴氏距离

直方图比较方法——相关性计算(CV_COMP_CORREL)
在这里插入图片描述
从上面公式可以看出,H1、H2越相近,d的值越靠近1。

直方图比较方法——卡方计算(CV_COMP_CHISQR)
在这里插入图片描述
从上面公式可以看出,H1、H2越相近,d的值越靠近0。

直方图比较方法——十字计算(CV_COMP_INTERSECT)
在这里插入图片描述

直方图比较方法——巴氏距离计算(CV_COMP_BHATTACHARYYA)
在这里插入图片描述
从上面公式可以看出,H1、H2越相近,d的值越靠近0。

#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
using namespace std;
using namespace cv;
string convertToString(double d);//把double的值变为string
int main(int argc, char **argv)
{
	Mat base, test1, test2;//其中base是lena原图,test1是有噪声的lena图像,test2是lena的灰度图像。
	Mat hsvbase, hsvtest1, hsvtest2;
	base = imread("D:/studytest/lena.jpg");
	if (!base.data)
	{
		printf("could not load image...\n");
		return -1;
	}
	test1 = imread("D:/studytest/lenanoise.jpg");
	test2 = imread("D:/studytest/graylena.jpg");
	//将图像转换为HSV图像
	cvtColor(base, hsvbase, CV_BGR2HSV);
	cvtColor(test1, hsvtest1, CV_BGR2HSV);
	cvtColor(test2, hsvtest2, CV_BGR2HSV);
	int h_bins = 50;//灰度等级
	int s_bins = 60;
	int histSize[] = { h_bins,s_bins };
	//hue varies from 0 to 179,saturation from 0 to 255
	float h_ranges[] = { 0,180 };
	float s_ranges[] = { 0,255 };
	const float* ranges[] = { h_ranges,s_ranges };
	//use the o-th and 1-st channels
	int channels[] = { 0,1 };
	MatND hist_base;//MatND表示多维
	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());
	Mat test12;
	test2.copyTo(test12);//将test12复制成test2
	//进行CORREL比较
	double basebase = compareHist(hist_base, hist_base, CV_COMP_CORREL);
	double basetest1 = compareHist(hist_base, hist_test1, CV_COMP_CORREL);
	double basetest2 = compareHist(hist_base, hist_test2, CV_COMP_CORREL);
	double test1test2 = compareHist(hist_test1, hist_test2, CV_COMP_CORREL);
	printf("test1 compare with  test2 correlation value :%f", test1test2);
	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);
}
string convertToString(double d)
{
	ostringstream os;
	if (os << d)
		return os.str();
	return "invalid conversion";
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值