【opencv学习笔记】026之直方图比较 - compareHist函数详解

1.前言

        想了解直方图比较中每种比较的方式,比较的原理,希望大家能有一定的概率论基础,或者统计学基础,如果对这块理论不太了解,还想深入学习算法,建议先学习一下概率论或统计学。

2.直方图比较概述

        对输入的两张图像进行直方图均衡化及直方图计算步骤后,可以对两个图像的直方图进行对比,并通过对比的结果得到一些我们想要的结论。

3.直方图比较应用

(1)图像相似度比较

        如果我们有两张图像,并且这两张图像的直方图一样,或者有极高的相似度,那么在一定程度上,我们可以认为这两幅图是一样的,这就是直方图比较的应用之一。

(2)分析图像之间关系

        两张图像的直方图反映了该图像像素的分布情况,可以利用图像的直方图,来分析两张图像的关系。

4.直方图比较原理

        要比较两个直方图(H1 和 H2),首先必须要选择一个衡量直方图相似度的对比标准,我们设为d(H1,H2),

5.直方图比较方法

(1)相关性比较(Correlation)

        相关性比较公式如下:


        其中

        如果H1 = H2,即两个图的直方图一样,分子等于分母,值为1,所以在不严格的情况下,当值为1时,可以认为两个图是一样的。但是也有可能会出现两个图不一样,但是两个图的直方图是一样的情况。因为直方图计算的是像素点个数的分布情况,但是不会显示像素点的位置,所以有可能会出现两幅图片不一样,但是相同像素的个数完全一样,那他们的直方图也是一样的,不过这种情况,不常有。

        相关性比较公式来源于统计学中的相关系数,最早由统计学家卡尔·皮尔逊设计的统计指标,是研究变量之间线性相关程度的量,一般用字母 r 表示。

        其中,Cov(X,Y)为X与Y的协方差,Var[X]为X的方差,Var[Y]为Y的方差。如果想学算法,但是又觉得数学很枯燥的话,可以推荐大家一本书,据说很有趣,叫《漫画统计学》。当然,如果是做研究,还是养成不怕枯燥的好习惯。

        在那本书上讲到:相关系数适合数值与数值之间的关联性分析。这个公式里面比上面多了一点,是这个公式的取值范围

        下面是该公式更加详细的取值范围分析:并且如果两个变量的相关性越强,相关系数就会越接近±1,相关性越弱,相关系数越接近0。

        相关系数的值若为正值,称为正相关;相关系数的值若为负值,称为负相关;相关系数的值为0,称为不相关。


(2)Chi-Square(卡方比较)

        通过这个公式我们能够发现,卡方比较和相关性比较恰恰相反,相关性比较的值为0,相似度最低,越趋近于1,相似度越低;卡方比较则是,值为0时说明H1= H2,这个时候相似度最高。

        卡方比较来源于卡方检验,卡方检验就是统计样本的实际观测值与理论推断值之间的偏离程度,实际观测值与理论推断值之间的偏离程度就决定卡方值的大小,卡方值越大,越不符合;卡方值越小,偏差越小,越趋于符合,若两个值完全相等时,卡方值就为0,表明理论值完全符合。卡方检验的公式如下,其中fi是观测频率,npi是期望频率,X²是卡方值。

(3)Intersection(十字交叉性)

        这个就比较简单了,对比H1,H2并求出最小值,最后求和。

(4)Bhattacharyya distance(巴氏距离)

        在直方图相似度计算时,巴氏距离获得的效果最好,但计算是最为复杂的。巴氏距离的计算结果,其值完全匹配为1,完全不匹配则为0。

        在统计学中,巴氏距离(巴塔恰里雅距离 / Bhattacharyya distance)用于测量两离散概率分布。它常在分类中测量类之间的可分离性。在同一定义域X中,概率分布p和q的巴氏距离定义如下:离散概率分布;连续概率分布。

6.API介绍——compareHist

(1)步骤

        a.先用cvtColor()把图像从RGB色彩空间转换到HSV色彩空间;

        b.计算图像的直方图,然后归一化到[0~1]之间,用到函数 calcHist() 和 normalize() ;

        c.使用上述的四种方法之一进行比较,用到函数compareHist()。

(2)API介绍

        函数一共有三个参数,一个输入图像,一个输出图像,一个比较方法。比较方法的取值的情况为上面的四种方法,在OpenCV中,每个都有自己的名字:Correlation ( CV_COMP_CORREL );Chi-Square ( CV_COMP_CHISQR );Intersection ( CV_COMP_INTERSECT );Bhattacharyya 距离( CV_COMP_BHATTACHARYYA )。

7.效果展示

(1)步骤分解

a.加载图像

b.将图像从BGR空间转化为HSV空间

c.计算直方图并归一化处理

d.直方图比较

e.展示图像

(2)源码及效果

#define INPUT_TITLE0 "input image src"
#define INPUT_TITLE1 "input image srctest1"
#define INPUT_TITLE2 "input image srctest2"
#define OUTPUT_TITLE "name"

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

using namespace std;
using namespace cv;

string convertToString(double d);

int main() {
	// 加载图像 
	Mat src, srctest1, srctest2;
	src = imread("D:/SunWuKong.jpg");
	srctest1 = imread("D:/SunWuKong1.jpg");
	srctest2 = imread("D:/GraySunWuKong.jpg");
	
	if (!src.data|| !srctest1.data|| !srctest2.data)
	{
		cout << "ERROR : could not load image.";
		return -1;
	}
	
	imshow("【src 原图】", src);
	imshow("【srctest1 原图】", srctest1);
	imshow("【srctest2 原图】", srctest2);

	//从RGB色彩空间转化为HSV色彩空间
	cvtColor(src, src, CV_BGR2HSV);
	cvtColor(srctest1, srctest1, CV_BGR2HSV);
	cvtColor(srctest2, srctest2, CV_BGR2HSV);

	//定义直方图计算所需要的各种参数
	int h_bins = 50;
	int s_bins = 60;
	int histSize[] = { h_bins,s_bins };

	float h_ranges[] = { 0,180 };
	float s_ranges[] = { 0,256 };
	const float* ranges[] = { h_ranges, s_ranges };

	int channels[] = { 0,1 };

	//MatND 是 Mat的别名,方便区分经过直方图计算处理后和输入图像
	MatND hist_src;
	MatND hist_srctest1;
	MatND hist_srctest2;

	//计算直方图并归一化处理
	calcHist(&src, 1, channels, Mat(), hist_src, 2, histSize, ranges, true, false);
	normalize(hist_src, hist_src, 0, 1, NORM_MINMAX, -1, Mat());

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

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

	//直方图比较
	double src_src = compareHist(hist_src, hist_src, CV_COMP_CORREL);
	double src_srctest1 = compareHist(hist_src, hist_srctest1, CV_COMP_CORREL);
	double src_srctest2 = compareHist(hist_src, hist_srctest2, CV_COMP_CORREL);
	double srctest1_srctest2 = compareHist(hist_srctest1, hist_srctest2, CV_COMP_CORREL);

	cout << "src compare with src correlation value : " << src_src << endl;
	cout << "src compare with srctest1 correlation value : " << src_srctest1 << endl;
	cout << "src compare with srctest2 correlation value : " << src_srctest2 << endl;

	//给每个图像上添加文字,内容为该图片和原始图片的比较结果
	putText(src, convertToString(src_src), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 255, 255), 2, LINE_AA);
	putText(srctest1, convertToString(src_srctest1), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);
	putText(srctest2, convertToString(src_srctest2), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(255, 0, 255), 2, LINE_AA);

	//图像的显示
	namedWindow(INPUT_TITLE0, CV_WINDOW_AUTOSIZE);
	namedWindow(INPUT_TITLE1, CV_WINDOW_AUTOSIZE);
	namedWindow(INPUT_TITLE2, CV_WINDOW_AUTOSIZE);
	//namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);

	imshow(INPUT_TITLE0, src);
	imshow(INPUT_TITLE1, srctest1);
	imshow(INPUT_TITLE2, srctest2);
	

	waitKey(0);
	return 0;
}

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

【原图】

【相关性比较】

取值为[0,1],越接近1,直方图相似度越高。


【卡方比较】

取值大于0,越接近0,直方图相似度越高。


下面两种方式图像跟上面相同,只有数值不同,下面将得数分享给大家:

【十字交叉性】

src compare with src correlation value :           53.7653
src compare with srctest1 correlation value :   29.2811
src compare with srctest2 correlation value :   0.56726

【巴氏距离】

src compare with src correlation value :         0
src compare with srctest1 correlation value : 0.562044
src compare with srctest2 correlation value : 0.947251



猜你喜欢

转载自blog.csdn.net/shuiyixin/article/details/80257822