OpenCV4入门教程098:Hu矩实现轮廓匹配

索引地址:系列索引

OpenCV提供了一个名为matchShapes的函数,它接收两个图像(或轮廓)并使用Hu Moments找到它们之间的距离。所以,不必在自己计算hu矩。只需将图像二值化并使用matchShapes。

说明

函数比较两个形状,3个被实现的方法都使用hu 不变量。

声明

1
2
3
4
5
6
double matchShapes( 
InputArray contour1,//第一张轮廓或者灰度图像
InputArray contour2,//第二张轮廓或灰度图像
int method, //比较方法
double parameter //特定方法的参数,目前不支持
);

method 参数

1
2
3
4
5
enum ShapeMatchModes {
CONTOURS_MATCH_I1 =1,
CONTOURS_MATCH_I2 =2,
CONTOURS_MATCH_I3 =3
};

令 D(A,B)为形状A和B之间的距离,并且$H_i^A $和 HiBH_i^B为形状A和B的对数变换的Hu矩。定义对应于三种情况的距离:

1.CONTOURS_MATCH_I1

D(A,B)=i=061HiB1HiAD(A,B)=\sum_{i=0}^6 |\frac{1}{H_i^B}-\frac{1}{H_i^A}|

2.CONTOURS_MATCH_I2 =2

D(A,B)=i=06HiBHiAD(A,B)=\sum_{i=0}^6 |H_i^B -H_i^A|

3.CONTOURS_MATCH_I3 =3

D(A,B)=i=06HiAHiBHiAD(A,B)=\sum_{i=0}^6 \frac{|H_i^A-H_i^B|}{|H_i^A|}

如果两幅图一样那么距离为0。可以推测值越大两幅图越不像

测试代码:

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
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void getHuMoments(Mat &src1,Mat &src2){
//1.转化为灰度图像
Mat gray1, binary1, dst1;
Mat gray2, binary2, dst2;
cvtColor(src1, gray1, COLOR_BGR2GRAY);
cvtColor(src2, gray2, COLOR_BGR2GRAY);

imshow("src1", src1);
imshow("src2", src2);

//2.二值化
threshold(gray1, binary1, 127, 255, THRESH_BINARY | THRESH_OTSU);
imshow("binary1", binary1);
threshold(gray2, binary2, 127, 255, THRESH_BINARY | THRESH_OTSU);
imshow("binary2", binary2);

//3.计算hu矩
Moments ms1,ms2;
ms1 = moments(binary1, false);
ms2 = moments(binary2, false);
double hu1[7],hu2[7];
HuMoments(ms1, hu1);
HuMoments(ms2, hu2);

//4.log转化
cout << endl << endl;
cout << " img1:" << endl;
for (size_t i = 0; i < 7; i++)
{
hu1[i] = -1 * copysign(1.0, hu1[i]) * log10(abs(hu1[i]));
cout << " hu1[" << i+1 << "]=" << hu1[i] << endl;
}
cout << endl;

cout << " img2:" << endl;
for (size_t i = 0; i < 7; i++)
{
hu2[i] = -1 * copysign(1.0, hu2[i]) * log10(abs(hu2[i]));
cout << " hu2[" << i+1 << "]=" << hu2[i] << endl;
}

//5.形状匹配
double d1 = matchShapes(binary1, binary2, CONTOURS_MATCH_I1, 0);
double d2 = matchShapes(binary1, binary2, CONTOURS_MATCH_I2, 0);
double d3 = matchShapes(binary1, binary2, CONTOURS_MATCH_I3, 0);

cout << " hu矩匹配值:" << endl;
cout << " CONTOURS_MATCH_T1 :" << d1 << endl;
cout << " CONTOURS_MATCH_T2 :" << d2 << endl;
cout << " CONTOURS_MATCH_T3 :" << d3 << endl;
}

int main() {
Mat src1 = imread("1.jpg");
Mat src2 = imread("1.png");

if (src1.empty()||src2.empty()) {
cout << " input the image error!" << endl;
}
getHuMoments(src1, src2);

waitKey(0);
return 0;
}

测试图片1为tifa,测试图片2为从图片1中截取的部分脸

结果为:

humoments


OpenCV4入门教程098:Hu矩实现轮廓匹配
https://blog.jackeylea.com/opencv/opencv-edge-match-with-hu-moment/
作者
JackeyLea
发布于
2020年10月6日
许可协议