检测点是否在轮廓、多边形的内部

OpenCV官网

代码

#include 
#include 

using namespace cv;
using namespace std;


int main(void)
{
	
    const int r=100;
    Mat src = Mat::zeros(Size(4*r, 4*r), CV_8U);

    vector<Point> vert(6);
    vert[0] = Point(3*r/2,static_cast<int>(1.34*r));
    vert[1] = Point(r,2*r);
    vert[2] = Point(3*r/2, static_cast<int>(2.866*r));
    vert[3] = Point(5*r/2, static_cast<int>(2.866*r));
    vert[4] = Point(3*r, 2*r);
    vert[5] = Point(5*r/2, static_cast<int>(1.34*r));

    for(int i=0; i<6; i++)
    {
	line(src, vert[i], vert[(i+1)%6], Scalar(255), 3);  //在src中创建一个六边形
    }



    vector<vector<Point>> contours;
    findContours(src, contours, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE); //检测六边形的轮廓

	
    Mat raw_dist(src.size(), CV_32F); //存放每个点的检测结果,所以定义为CV_32F
    for(int i=0; i<src.rows; i++)
    {
		for(int j=0; j<src.cols; j++)
		{
	    	raw_dist.at<float>(i,j) = (float)cv::pointPolygonTest(contours[0], Point2f((float)j, (float)i), true); // 对于每个点都去检测
		}	    
    }

    double minVal, maxVal;
    Point maxDistPt;
    cv::minMaxLoc(raw_dist,&minVal, &maxVal, NULL, &maxDistPt); //找到最大值和最小值,以及他们的位置
    minVal = abs(minVal);  //因为最小值肯定是负值,在contour外都是负值,所以取绝对值
    maxVal = abs(maxVal);

    Mat drawing = Mat::zeros(src.size(), CV_8UC3);  //将结果显示此图中
    for(int i=0; i<src.rows; i++)
    {
		for(int j=0; j<src.cols; j++)
		{
	    	if(raw_dist.at<float>(i,j) < 0)  //在contour外
	    	{
				drawing.at<Vec3b>(i,j)[0] = (uchar)(255-abs(raw_dist.at<float>(i,j))*255/minVal);  //,minVal已经取abs,minVal是contour外距离最远点,距离边界越远,蓝色成分越小	
	    	}
	    	else if(raw_dist.at<float>(i,j)>0) //在contour内
	    	{
				drawing.at<Vec3b>(i,j)[2] = (uchar)(255-raw_dist.at<float>(i,j)*255/maxVal); //距离边界越远,红色成分越小
	    	}
	    		else  // 边界上,白色
	    	{
				drawing.at<Vec3b>(i,j)[0] = 255 ;
				drawing.at<Vec3b>(i,j)[1] = 255 ;
				drawing.at<Vec3b>(i,j)[2] = 255 ;

	    }
		}
    }

    circle(drawing, maxDistPt, (int)maxVal, Scalar(255,255,255)); //maxDistPt 应该是contours里面最中心的位置,maxVal:到边界的距离,所以应该是一个内接圆
    imshow("source", src);
    imshow("Distance and inscribed circle", drawing);

    waitKey();

	return 0;
};

结果:和代码中注释分析一样,接近contour颜色深,远离边界(往内,往外两个方向),颜色开始变浅到黑。

检测点是否在轮廓、多边形的内部_第1张图片



OpenCV API

  1. 判断一个点是否在 polygon的内部

double cv::pointPolygonTest

( 	    InputArray  	contour,  //一组点组成contour vector
		Point2f  	pt,           // 被检测的点
		bool  	measureDist       // true: 内部是正数,边界是0,外部是负数,绝对值是点到最近一条边的距离;  false: 检测点是否在内部、外部、边界,返回+1、-1、0
) 	




你可能感兴趣的:(opencv)