直方图比较

1、直方图比较方法;
2、相关API;
3、代码演示;

直方图比较方法

1、直方图比较方法用来衡量两张图片之间的相似程度;
2、比较方法:将输入的两张图片归一化到相同的尺度空间才能进行比较,先进行归一化,再计算H1与H2之间的距离得到两个直方图的相似程度进而比较图像本身的相似程度 ,OpenCV提供了相关性比较的4种方法(数学知识):①相关性比较;②卡方比较;③十字交叉性;④巴氏距离;

相关性比较(CV_COMP_CORREL)

1、计算公式如下:

注:BIN表示像素划分的梯度等级的个数
2、如果H1 == H2, 则 d ( H 1 , H 2 ) d(H_1,H_2) d(H1,H2) = 1,表示两幅图像具有很强的相关性;计算结果 d ( H 1 , H 2 ) d(H_1,H_2) d(H1,H2)位于(-1,+1)之间;

卡方计算(CV_COMP_CHISQR)

1、计算公式:

2、如果 H 1 H_1 H1 == H 2 H_2 H2,d( H 1 H_1 H1, H 2 H_2 H2) =0, 此时表示两幅图像具有最强的相关性;

十字计算(CV_COMP_INTERSECT)

1、计算公式:

2、度量不好用;

巴氏距离计算(CV_COMP_BHATTACHARYYA)

1、计算公式:

2、d( H 1 H_1 H1, H 2 H_2 H2) 位于(0,1)之间;如果d( H 1 H_1 H1, H 2 H_2 H2) = 0,表示两幅图像相关性最强(H1==H2);如果d( H 1 H_1 H1, H 2 H_2 H2) = 1,表示两幅图像没有相关性(最不相似);

直方图计算

1、直方图比较方法建立在已经计算出直方图的基础上,OpenCV支持多通道图像的直方图计算,计算步骤如下:
①先将图像从RGB彩色空间转换到HSV色彩空间(取H,S分量);
②计算图像直方图,然后归一化到[0~1]之间;
③使用直方图比较方法进行比较;

直方图比较API

1、API : cv::compareHist(); 计算之后得到一个double返回值,根据返回值判断图像相关性;

Code

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

using namespace std;
using namespace cv;

string convertToString(double d);

int main(int argc, char** argv)
{
   
	Mat base, test1, test2;
	Mat hsvbase, hsvtest1, hsvtest2;
	//读进原图 彩色图像和灰度图像默认不同
	base = imread("C:\\Users\\hello\\Desktop\\lena.tiff",IMREAD_ANYDEPTH | IMREAD_ANYCOLOR);
	test1 = imread("C:\\Users\\hello\\Desktop\\lena.bmp", IMREAD_ANYDEPTH | IMREAD_ANYCOLOR);
	test2 = imread("C:\\Users\\hello\\Desktop\\lena.jpg", IMREAD_ANYDEPTH | IMREAD_ANYCOLOR);
	if (base.empty() || test1.empty() || test2.empty())
	{
   
		cout << "could not load the image..." << endl;
		return -1;
	}
	//色彩空间转换
	cvtColor(base, hsvbase, CV_BGR2HSV);
	cvtColor(test1, hsvtest1, CV_GRAY2BGR); //原图像是灰度图像
	cvtColor(hsvtest1, hsvtest1, CV_BGR2HSV);
	cvtColor(test2, hsvtest2, CV_BGR2HSV);

	//定义一些数据给calcHist()使用
	//设置灰度等级
	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,256 };
	const float* ranges[] = {
    h_ranges,s_ranges };
	//use the 0-th and 1-th channnels
	int channels[] = {
    0 ,1 };

	MatND hist_base;    //ND表示多维
	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());   //归一化到0-1之间

	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);
	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);
	//绘制文本 fontScale : 字体缩放
	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(test2, convertToString(test1test2), Point(50, 150), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);

	namedWindow("base", WINDOW_AUTOSIZE);
	namedWindow("test1", WINDOW_AUTOSIZE);
	namedWindow("test2", WINDOW_AUTOSIZE);

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

	waitKey(0);
	return 0;

}


string convertToString(double d)
{
   
	ostringstream os;
	if (os << d)
		return os.str();
	return "invalid convertion";
}

效果

1、CV_COMP_CORREL: (接近1代表相似度高)

2、CV_COMP_BHATTACHARYYA: 接近0代表相似度高


3、CV_COMP_CHISQR: 相似度越高越接近0 ,越低值越大


4、CV_COMP_INTERSECT:趋近于0,相似度低;