29、【opencv入门】轮廓查找与绘制(7)——位置关系及轮廓匹配 一、计算点与轮廓的距离及位置关系---pointPolygonTest()

CV_EXPORTS_W double pointPolygonTest(InputArray contour, Point2f pt, bool measureDist);

  contour: 所需检测的轮廓对象

  pt: Point2f 类型的pt, 待判定位置的点

  measureDist: 是否计算距离的标志, 当其为true时, 计算点到轮廓的最短距离, 当其为false时, 只判定轮廓与点的位置关系, 具体关系如下:    

    ①返回值为-1, 表示点在轮廓外部    

    ②返回值为0, 表示点在轮廓上    

    ③返回值为1, 表示点在轮廓内部

示例:

1 double a0 = pointPolygonTest(contours[0], Point(3,3), true);
2 double b0 = pointPolygonTest(contours[0], Point(3,3), false);

注意:如果你不需要知道具体的距离,建议你将第三个参数设为false,这样速度会提高2到3倍。

 1 //计算点到轮廓的距离
 2 #include "opencv2/opencv.hpp"
 3 #include <iostream>
 4 
 5 using namespace std;
 6 using namespace cv;
 7 
 8 int main()
 9 {
10     //计算点到轮廓的距离与位置关系
11     Mat srcImg = imread("1.png");
12     imshow("src", srcImg);
13 
14     Mat dstImg = srcImg.clone();
15     cvtColor(srcImg, srcImg, CV_BGR2GRAY);
16     threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY);
17     imshow("threshold", srcImg);
18 
19     //查找轮廓
20     vector<vector<Point>> contours;
21     vector<Vec4i> hierarcy;
22     findContours(srcImg, contours, hierarcy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);//TREE:提取所有轮廓    NONE:画出轮廓所有点
23     cout << "contours.size()=" << contours.size() << endl;
24     for (int i = 0; i < contours.size(); i++)//遍历每个轮廓
25     {
26         for (int j = 0; j < contours[i].size(); j++)//遍历轮廓每个点
27         {
28             cout << "(" << contours[i][j].x << "," << contours[i][j].y << ")" << endl;
29         }
30     }
31 
32     double a0 = pointPolygonTest(contours[0], Point(3, 3), true);//点到轮廓的最短距离
33     double b0 = pointPolygonTest(contours[0], Point(212, 184), false);//点与轮廓的位置关系:-1表示外部;0表示在轮廓上;1表示轮廓内部
34     cout << "a0=" << a0 << endl;
35     cout << "b0=" << b0 << endl;
36     waitKey(0);
37     return 0;
38 }

二、轮廓的矩的计算---moments()

1 CV_EXPORTS_W Moments moments(InputArray array, bool binaryImage=false);

  array: 输入参数, 可以是光栅图像或二维数组

  binaryImage:默认值false, 非零像素取其本身值, 若为true, 则非零像素取1 返回值: Moments类的对象, 返回对应的轮廓的空间矩/中心矩和归一化中心矩(最高3阶), 如下:

29、【opencv入门】轮廓查找与绘制(7)——位置关系及轮廓匹配
一、计算点与轮廓的距离及位置关系---pointPolygonTest()

更多关于轮廓的矩的计算,参见:

1 http://blog.csdn.net/cp32212116/article/details/38374015 
2 http://blog.csdn.net/huixingshao/article/details/42060231
 1 //轮廓矩的计算
 2 #include "opencv2/opencv.hpp"
 3 #include <iostream>
 4 
 5 using namespace std;
 6 using namespace cv;
 7 
 8 int main()
 9 {
10     Mat srcImg = imread("1.png");
11     imshow("src", srcImg);
12 
13     Mat dstImg = srcImg.clone();
14     cvtColor(srcImg, srcImg, CV_BGR2GRAY);
15     threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY);
16     //imshow("threshold", srcImg);
17 
18     vector<vector<Point>> contours;
19     vector<Vec4i> hierarcy;
20     findContours(srcImg, contours, hierarcy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);
21     cout << "contours.size()=" << contours.size() << endl;
22     Moments moment0 = moments(contours[0], false);
23     cout << moment0.m00<< endl;
24     waitKey(0);
25     return 0;
26 }

三、形状匹配---matchShapes()

1 CV_EXPORTS_W double matchShapes(InputArray contour1, InputAaary contour2, int method, double parameter);

  contour1: 所需比较的轮廓1

  contour2: 所需比较的轮廓2

  method: 轮廓比较的方法

  parameter: 比较方法的特殊参数(目前不支持)

注意:  matchShapes()函数比较轮廓相似度是基于Hu矩来计算的, 结果越小相似度越高。

Hu矩是归一化中心矩的线性组合, 是为了获取图像某个特征的矩函数(对应变化如平移、缩放、旋转、镜像)  

 1 //形状匹配
 2 #include "opencv2/opencv.hpp"
 3 #include <iostream>
 4 #include <iomanip>
 5 
 6 using namespace std;
 7 using namespace cv;
 8 
 9 int main()
10 {
11     Mat srcImg = imread("1.jpg");  //模板图像
12     imshow("src", srcImg);
13     cvtColor(srcImg, srcImg, CV_BGR2GRAY);
14     threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY);
15     vector<vector<Point>> contours;
16     vector<Vec4i> hierarcy;
17     findContours(srcImg, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
18 
19     Mat srcImg2 = imread("2.jpg");  //待测试图片
20     imshow("src2", srcImg2);
21     Mat dstImg = srcImg2.clone();
22     cvtColor(srcImg2, srcImg2, CV_BGR2GRAY);
23     threshold(srcImg2, srcImg2, 100, 255, CV_THRESH_BINARY);
24     vector<vector<Point>> contours2;
25     vector<Vec4i> hierarcy2;
26     findContours(srcImg2, contours2, hierarcy2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
27     while (1)
28     {
29         for (int i = 0; i<contours2.size(); i++)
30         {
31             double matchRate = matchShapes(contours[0], contours2[i], CV_CONTOURS_MATCH_I1, 0.0);//形状匹配:值越小越相似
32             cout << "index=" << i << "---" << setiosflags(ios::fixed) << matchRate << endl;//setiosflags(ios::fixed)是用定点方式表示实数,保留相同位数,相同格式输出
33             if (matchRate <= 0.1)
34                 drawContours(dstImg, contours2, i, Scalar(0, 255, 0), 2, 8);
35             imshow("dst", dstImg);
36             /*char key = waitKey();
37             if (key == 27)
38                 break;*/
39         }
40         break;
41     }
42     waitKey(0);
43     return 0;
44 }