二十四、直方图比较
利用两张图片的直方图判断两张图片的相似性,也可以判断两个图片是否为同一图片。
1、直方图比较方法
对输入的两张图象计算得到直方图H1与H2,归一化到相同的尺度空间然后可以通过计算H1和H2之间的距离得到两个直方图的相似程度进而比较图像本身的相似程度。opencv提供的比较方法有4种:
Correlation
相关性比较HISTCMP_CORREL
如果两个数组H1、H2一样的情况下,相关性最大,得到的值为1。
Chi-Square
卡方比较HISTCMP_CHISQR
如果H1、H2完全相同,相关性最大,得到的值为0。
Intersection
十字交叉性HISTCMP_INTERSECT
(不准确,慎用)
Bhattacharyya distance
巴氏距离HISTCMP_BHATTACHARYYA
如果H1、H2完全相同,相关性最大,得到的值为0。
2、相关API
- 首先把图像从RGB色彩空间转换到HSV色彩空间
cvtColor
- 计算图像的直方图,然后归一化到0-1之间
calcHist
和normalize
- 使用上述四种方法之一进行比较
compareHist
compareHist(
InputArray h1,//直方图数据,下同
InputArray h2,
int method//比较方法,上述四种方法之一
)
示例代码:(直方图比较)
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
string convertToString(double d);//将double型数据转为字符型
int main(int argc, char* argv) {
Mat src, test1, test2;
src = imread("添加图片路径");
if (!src.data) {
cout << "could not load image..." << endl;
return -1;
}
test1 = imread("添加图片路径");
cvtColor(src, src, COLOR_BGR2HSV);//将测试图片转至HSV色彩空间,后面只取HS两个色彩空间计算直方图,因为色彩和饱和度是直方图中最敏感的表征量
cvtColor(test1, test1, COLOR_BGR2HSV);
int h_bins = 50; int s_bins = 60;//划分一张图片两个通道直方图的bin
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 hist_src;//ND表示多维
MatND hist_test1;
calcHist(&src, 1, channels, Mat(), hist_src, 2, histSize, ranges, true, false);//直方图计算
normalize(hist_src, hist_src, 0, 1, NORM_MINMAX, -1, Mat());//归一化
calcHist(&test1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false);
normalize(hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat());
double srcsrc = compareHist(hist_src, hist_src, HISTCMP_CORREL);//src与src做直方图相关性比较
//double srctest1 = compareHist(hist_src, hist_test1, HISTCMP_CORREL);//src与test1做直方图相关性比较
double srctest1 = compareHist(hist_src, hist_test1, HISTCMP_BHATTACHARYYA);//src与test1做直方图巴氏比较
printf("src compare with test1 correlation value : %f", srctest1);
putText(src, convertToString(srcsrc), Point(50, 50), FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 0), 2, LINE_AA);//在图像上打印比较结果
putText(test1, convertToString(srctest1), Point(50, 50), FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 0), 2, LINE_AA);
namedWindow("src", WINDOW_AUTOSIZE);
namedWindow("test1", WINDOW_AUTOSIZE);
imshow("src", src);
imshow("test1", test1);
waitKey(0);
return 0;
}
string convertToString(double d) {
ostringstream os;
if (os << d)
return os.str();
return "invalid conversion";
}
输出结果显示:
-
相关性比较方法
分析:用的图片分别是一张图片和其提升对比度后的图片,可以看出经过相关性比较,两张图片直方图比较的结果接近1,说明相似度很高。而左侧图片和自身对比的结果为1,说明两张图片相同。 -
巴氏距离比较方法
分析:两张一样的图片做对比,结果为0,验证了两张图片为同一张图。
一张图片和提升对比度后的图片做直方图巴氏比较,得到的值较小,说明两张图片相似性较高。