OpenCV4入门教程081:图像直方图比较

索引地址:系列索引

如果有两幅相似的图,使用函数cv::compareHist获取一个数值参数,表示两个直方图相互匹配的程度。使用不同的指标来比较直方图:相关性、Chi-Square、交点、Bhattacharyya distance。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void getHistogram(const Mat &grayImg, Mat &histogram)
{
int bins = 256;
int nimages = 1;
int channels[] = {0};
Mat mask;
int dims = 1;
int histSize[] = { bins };
float rangeGS[] = {0, 256};
const float* ranges[] = { rangeGS };
bool uniform = true;
bool accumulate = false;
calcHist(&grayImg,
nimages,
channels,
mask,
histogram,
dims,
histSize,
ranges,
uniform,
accumulate);
}

int main()
{
Mat image1 = imread("Test.png");
Mat image2 = imread("Test2.png");
if(image1.empty() || image2.empty())
{
cout << "Empty input image!";
return -1;
}

Mat grayImg1, grayImg2, histogram1, histogram2;
cvtColor(image1, grayImg1, COLOR_BGR2GRAY);
cvtColor(image2, grayImg2, COLOR_BGR2GRAY);

getHistogram(grayImg2, histogram1);
getHistogram(grayImg1, histogram2);

cout << "HISTCMP_CORREL: " << compareHist(histogram1, histogram2, HISTCMP_CORREL) << endl;
cout << "HISTCMP_CHISQR: " << compareHist(histogram1, histogram2, HISTCMP_CHISQR) << endl;
cout << "HISTCMP_INTERSECT: " << compareHist(histogram1, histogram2, HISTCMP_INTERSECT) << endl;
cout << "HISTCMP_BHATTACHARYYA: " << compareHist(histogram1, histogram2, HISTCMP_BHATTACHARYYA) << endl;
cout << "HISTCMP_HELLINGER: " << compareHist(histogram1, histogram2, HISTCMP_HELLINGER) << endl;
cout << "HISTCMP_CHISQR_ALT: " << compareHist(histogram1, histogram2, HISTCMP_CHISQR_ALT) << endl;
cout << "HISTCMP_KL_DIV: " << compareHist(histogram1, histogram2, HISTCMP_KL_DIV) << endl;

return 0;
}

测试图片:

compare

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
//---------------------------------【头文件、命名空间包含部分】----------------------------
// 描述:包含程序所使用的头文件和命名空间
//------------------------------------------------------------------------------------------------
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;

//--------------------------------------【main( )函数】-----------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main() {
//【1】声明储存基准图像和另外两张对比图像的矩阵( RGB 和 HSV )
Mat srcImage_base, hsvImage_base;
Mat srcImage_test1, hsvImage_test1;
Mat srcImage_test2, hsvImage_test2;
Mat hsvImage_halfDown;

//【2】载入基准图像(srcImage_base) 和两张测试图像srcImage_test1、srcImage_test2,并显示
srcImage_base = imread("1.jpg", 1);
srcImage_test1 = imread("2.jpg", 1);
srcImage_test2 = imread("3.jpg", 1);
//显示载入的3张图像
imshow("Base", srcImage_base);
imshow("Testing1", srcImage_test1);
imshow("Testing2", srcImage_test2);

// 【3】将图像由BGR色彩空间转换到 HSV色彩空间
cvtColor(srcImage_base, hsvImage_base, COLOR_BGR2HSV);
cvtColor(srcImage_test1, hsvImage_test1, COLOR_BGR2HSV);
cvtColor(srcImage_test2, hsvImage_test2, COLOR_BGR2HSV);

//【4】创建包含基准图像下半部的半身图像(HSV格式)
hsvImage_halfDown = hsvImage_base(Range(hsvImage_base.rows / 2, hsvImage_base.rows - 1),
Range(0, hsvImage_base.cols - 1));

//【5】初始化计算直方图需要的实参
// 对hue通道使用30个bin,对saturatoin通道使用32个bin
int h_bins = 50;
int s_bins = 60;
int histSize[] = {h_bins, s_bins};
// hue的取值范围从0到256, saturation取值范围从0到180
float h_ranges[] = {0, 256};
float s_ranges[] = {0, 180};
const float *ranges[] = {h_ranges, s_ranges};
// 使用第0和第1通道
int channels[] = {0, 1};

// 【6】创建储存直方图的 MatND 类的实例:
MatND baseHist;
MatND halfDownHist;
MatND testHist1;
MatND testHist2;

// 【7】计算基准图像,两张测试图像,半身基准图像的HSV直方图:
calcHist(&hsvImage_base, 1, channels, Mat(), baseHist, 2, histSize, ranges, true, false);
normalize(baseHist, baseHist, 0, 1, NORM_MINMAX, -1, Mat());

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

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

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

//【8】按顺序使用4种对比标准将基准图像的直方图与其余各直方图进行对比:
for (int i = 0; i < 4; i++) {
//进行图像直方图的对比
int compare_method = i;
double base_base = compareHist(baseHist, baseHist, compare_method);
double base_half = compareHist(baseHist, halfDownHist, compare_method);
double base_test1 = compareHist(baseHist, testHist1, compare_method);
double base_test2 = compareHist(baseHist, testHist2, compare_method);
//输出结果
printf(" 方法 [%d] 的匹配结果如下:\n\n 【基准图 - 基准图】:%f, 【基准图 - "
"半身图】:%f,【基准图 - 测试图1】: %f, 【基准图 - 测试图2】:%f "
"\n-----------------------------------------------------------------\n",
i, base_base, base_half, base_test1, base_test2);
}

printf("检测结束。");
waitKey(0);
return 0;
}

加载基础图像和2个测试图像进行比较。生成基本图像的下半部分的1个图像将图像转换为HSV格式计算所有图像的HS直方图,并对它们进行归一化,以便进行比较。比较基本图像的直方图与2个测试直方图,下半部基本图像的直方图以及相同的基本图像直方图。显示获得的数值匹配参数。

测试结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
方法 [0] 的匹配结果如下:

【基准图 - 基准图】:1.000000, 【基准图 - 半身图】:0.909230,【基准图 - 测试图1】: 0.266814, 【基准图 - 测试图2】:0.130479
-----------------------------------------------------------------
方法 [1] 的匹配结果如下:

【基准图 - 基准图】:0.000000, 【基准图 - 半身图】:21.251731,【基准图 - 测试图1】: 4940.943629, 【基准图 - 测试图2】:3960.965260
-----------------------------------------------------------------
方法 [2] 的匹配结果如下:

【基准图 - 基准图】:58.699014, 【基准图 - 半身图】:33.209244,【基准图 - 测试图1】: 7.322875, 【基准图 - 测试图2】:4.538224
-----------------------------------------------------------------
方法 [3] 的匹配结果如下:

【基准图 - 基准图】:0.000000, 【基准图 - 半身图】:0.359217,【基准图 - 测试图1】: 0.603080, 【基准图 - 测试图2】:0.663177
-----------------------------------------------------------------
检测结束。

OpenCV4入门教程081:图像直方图比较
https://feater.top/opencv/opencv-image-compare-histogram/
作者
JackeyLea
发布于
2020年6月21日
许可协议