一、计算点与轮廓的距离及位置关系---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阶), 如下:
更多关于轮廓的矩的计算,参见:
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 }