点与轮廓的距离及位置关系

函数原型

double pointPolygonTest( InputArray contour, Point2f pt, bool measureDist );
  • contour: 所需检测的轮廓对象
  • pt: Point2f 类型的pt, 待判定位置的点
  • measureDist: 是否计算距离的标志, 当其为true时, 计算点到轮廓的最短距离, 当其为false时, 只判定轮廓与点的位置关系, 具体关系如下:
    ①返回值为-1, 表示点在轮廓外部
    ②返回值为0, 表示点在轮廓上
    ③返回值为1, 表示点在轮廓内部

代码

///计算点到轮廓的距离与位置关系
Mat srcImg = imread("D:\\1\\00.png");
imshow("src", srcImg);


cvtColor(srcImg, srcImg, CV_BGR2GRAY);
threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY);
imshow("threshold", srcImg);

vector<vector<Point>> contours;
vector<Vec4i> hierarcy;

findContours(srcImg, contours, hierarcy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);

//输出轮廓数目
cout<<"contours.size()="<<contours.size()<<endl;

//输出轮廓的每个坐标
for(int i=0; i<contours.size(); i++)
{
    for(int j=0; j<contours[i].size(); j++)
    {
        cout<<"("<<contours[i][j].x<<","<<contours[i][j].y<<")"<<endl;
    }
}

double a0 = pointPolygonTest(contours[0], Point(212, 184), true);
double b0 = pointPolygonTest(contours[0], Point(212, 184), false);
cout<<"a0="<<a0<<endl;
cout<<"b0="<<b0<<endl;
waitKey(0);

运行结果

opencv计算不规则区域宽度_opencv计算不规则区域宽度

opencv计算不规则区域宽度_中心矩_02

轮廓的矩

轮廓矩的介绍


opencv计算不规则区域宽度_相似度_03

opencv计算不规则区域宽度_opencv_04

opencv计算不规则区域宽度_opencv_05

opencv计算不规则区域宽度_opencv计算不规则区域宽度_06

计算函数原型

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

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

binaryImage:默认值false, 非零像素取其本身值, 若为true, 则非零像素取1

返回值: Moments类的对象, 返回对应的轮廓的空间矩/中心矩和归一化中心矩(最高3阶), 如下:

opencv计算不规则区域宽度_相似度_07

代码

Mat srcImg = imread("d:\\1\\00.png");
imshow("src", srcImg);

cvtColor(srcImg, srcImg, CV_BGR2GRAY);
threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY);
imshow("threshold", srcImg);

vector<vector<Point>> contours;
vector<Vec4i> hierarcy;

findContours(srcImg, contours, hierarcy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);
cout<<"contours.size()="<<contours.size()<<endl;
Moments moment0 = moments(contours[0], false);
cout<<moment0.m00<<endl;
waitKey(0);

运行结果

opencv计算不规则区域宽度_相似度_08

形状匹配—比较两个形状或轮廓间的相似度

函数原型—matchShapes()

double matchShapes( InputArray contour1, InputArray contour2,
                    int method, double parameter );
  • contour1: 所需比较的轮廓1
  • contour2: 所需比较的轮廓2
  • method: 轮廓比较的方法
  • parameter: 比较方法的特殊参数(目前不支持)

opencv计算不规则区域宽度_ios_09

注意

matchShapes()函数比较轮廓相似度是基于Hu矩来计算的, 结果越小相似度越高。
Hu矩是归一化中心矩的线性组合, 是为了获取图像某个特征的矩函数(对应变化如平移、缩放、旋转、镜像)

应用实例

opencv计算不规则区域宽度_ios_10

代码

Mat srcImg = imread("D:\\1\\1.jpg");  //读取模板图像
imshow("src", srcImg);
cvtColor(srcImg, srcImg, CV_BGR2GRAY);
threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY);
vector<vector<Point>> contours;
vector<Vec4i> hierarcy;
findContours(srcImg, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);


Mat srcImg2 = imread("D:\\1\\2.jpg");  //读取待测试图片
imshow("src2", srcImg2);
Mat dstImg = srcImg2.clone();
cvtColor(srcImg2, srcImg2, CV_BGR2GRAY);
threshold(srcImg2, srcImg2, 100, 255, CV_THRESH_BINARY);
vector<vector<Point>> contours2;
vector<Vec4i> hierarcy2;
findContours(srcImg2, contours2, hierarcy2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

while(1)
{
    for(int i=0; i<contours2.size(); i++)
    {
        double matchRate = matchShapes(contours[0], contours2[i], CV_CONTOURS_MATCH_I1, 0.0);
        cout<<"index="<<i<<"---"<<setiosflags(ios::fixed)<<matchRate<<endl;
        if(matchRate<=0.1)
            drawContours(dstImg, contours2, i, Scalar(0, 255, 0), 2, 8);
        imshow("dst", dstImg);
        char key = waitKey();
        if(key==27)
            break;
    }
    break;
}
waitKey(0);

运行结果

opencv计算不规则区域宽度_ios_11

opencv计算不规则区域宽度_opencv计算不规则区域宽度_12

知识点讲解

1.

Mat srcImg = imread("D:\\1\\1.jpg");  //读取模板图像
imshow("src", srcImg);
cvtColor(srcImg, srcImg, CV_BGR2GRAY);
threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY);
vector<vector<Point>> contours;
vector<Vec4i> hierarcy;
findContours(srcImg, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

模板图像和待测图像的处理方式必须相同