OpenCV25-判断一个点是否在多边形的内部_点多边形测试pointPolygonTest opencv函数 pointPolygonTest: C++: double pointPolygonTest(InputArray contour, Point2f pt, bool measureDist) 用于测试一个点是否在多边形中 当measureDist设置为true时,返回实际距离值。若返回值为正,表示点在多边形内部,返回值为负,表示在多边形外部,返回值为0,表示在多边形上。 当measureDist设置为false时,返回 -1、0、1三个固定值。若返回值为+1,表示点在多边形内部,返回值为-1,表示在多边形外部,返回值为0,表示在多边形上 pointPolygonTest( InputArray contour,// 输入的轮廓 Point2f pt, // 测试点 bool measureDist // 是否返回距离值,如果是false,1表示在内面,0表示在边界上,-1表示在外部,true返回实际距离 ) 返回数据是double类型 步骤: 发现轮廓 对图像中所有像素点做点 多边形测试,得到距离,归一化后显示。 OpenCV Error: Assertion failed ((unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels())) in cv::Mat::at, file d:opencv3opencvuildincludeopencv2coremat.inl.hpp, line 918 表示操作通道数错误,本来是单通道,却操作了多通道。 //Mat drawImg1 = Mat::zeros(src.size(),CV_8UC1);//错误 Mat drawImg1 = Mat::zeros(src.size(), CV_8UC3); */ #include <iostream> #include <opencv2opencv.hpp> using namespace std; using namespace cv; int main(int argc, char *argv[]) { Mat src = imread("e:\pictures\五角星.jpg"); //Mat src = imread("e:\pictures\牡丹花.jpg",CV_LOAD_IMAGE_COLOR); if (!src.data) { printf("failed to load image"); return -1; } //namedWindow("原图",CV_WINDOW_AUTOSIZE); imshow("原图",src); threshold(src,src,126,255,CV_THRESH_BINARY);//二值化 //转灰度图像 cvtColor(src,src,CV_BGR2GRAY); vector<vector<Point>> contours; vector<Vec4i> hierachy; //发现轮廓 findContours(src,contours,hierachy,RETR_TREE,CV_CHAIN_APPROX_SIMPLE,Point(0,0)); //画轮廓 drawContours(src,contours,1,Scalar::all(255),2,8,hierachy); imshow("轮廓",src); //waitKey(); //return 0; //距离 Mat dist = Mat::zeros(src.size(),CV_32FC1); for (int i = 0; i < src.rows; i++) { for (int j = 0; j < src.cols; j++) { //检测距离 double distance = pointPolygonTest(contours[1], Point2f(j, i), true); dist.at<float>(i, j) = static_cast<float>(distance); } } double minVal, maxVal; minMaxLoc(dist,&minVal,&maxVal,0,0,Mat()); //Mat drawImg1 = Mat::zeros(src.size(),CV_8UC1);//错误 Mat drawImg1 = Mat::zeros(src.size(), CV_8UC3); int thredVal1 = 1; for (int i = 0; i < src.rows; i++) { for (int j = 0; j < src.cols; j++) { double distance = dist.at<float>(i,j); if (distance > thredVal1) { drawImg1.at<Vec3b>(i, j)[0] = (uchar)(abs(distance/maxVal)*255); } else if (distance < (thredVal1*(-1))) { drawImg1.at<Vec3b>(i, j)[2] = (uchar)(abs(distance/minVal)*255); } else { drawImg1.at<Vec3b>(i, j)[0]=(uchar)(abs(255 - distance)); drawImg1.at<Vec3b>(i, j)[1]=(uchar)(abs(255 - distance)); drawImg1.at<Vec3b>(i, j)[2]=(uchar)(abs(255 - distance)); } } } imshow("drawImag1",drawImg1); //imwrite("drawImg1.jpg",drawImg1);//保存图像 //归一化 normalize(dist,dist,-255,255,NORM_MINMAX); Mat drawImg2 = Mat::zeros(src.size(),CV_8UC3); int thredVal2 = 3; for (int i = 0; i < src.rows; i++) { for (int j = 0; j < src.cols; j++) { double distance = dist.at<float>(i,j); if (distance > thredVal2) { drawImg2.at<Vec3b>(i, j)[0] = (uchar)(distance); } else if (distance < (thredVal2*(-1))) { drawImg2.at<Vec3b>(i, j)[2] = (uchar)(distance*(-1)); } else { drawImg2.at<Vec3b>(i, j)[0] = (uchar)(255); drawImg2.at<Vec3b>(i, j)[1] = (uchar)(255); drawImg2.at<Vec3b>(i, j)[2] = (uchar)(255); } } } imshow("drawImg2",drawImg2); waitKey(); return 0; }