点多边形测试
测试一个点是否在给定的多边形内部、边缘或外部。API介绍
double pointPolygonTest ( InputArray contour, // 输入的轮廓 Point2f pt, // 测试点 bool measureDist )第三个参数 measureDist: 当 measureDist 设置为 true 时,返回实际距离值。若返回值为正,表示点在多边形内部;返回值为负,表示在多边形外部;返回值为0,表示在多边形上。且越靠近内部,值越大,越远离边缘,值越小(绝对值越大)。 当 measureDist 设置为 false 时,返回 -1、0、1三个固定值。若返回值为+1,表示点在多边形内部;返回值为-1,表示在多边形外部;返回值为0,表示在多边形上。该过程不计算距离值,运行速度更快。程序示例
int main() { // 输入并显示图像 Mat src = imread("E:/Image/fy.jpg"); if (src.empty()) { cout << "could not load image..." << endl; return 0; } imshow("src", src); // 灰度和二值化处理 cvtColor(src, src, CV_BGR2GRAY); threshold(src, src, 180, 255, CV_THRESH_BINARY); // 寻找轮廓 vector<vector<Point>> contours; vector<Vec4i> hierachy; Mat dst = Mat::zeros(src.size(), src.type()); findContours(src, contours, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0)); // 计算距离 Mat dist = Mat::zeros(src.size(), CV_32FC1); for (int i = 0; i < src.cols; i++) { for (int j = 0; j < src.rows; j++) { //contours共有两个,这里取contours[1],contours[0]包含图像的四个点 //这里Point2f(j,i) 代表的x,y是不是反了?不清楚为什么 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 drawImg = Mat::zeros(src.size(), CV_8UC3); for (int i = 0; i < src.cols; i++) { for (int j = 0; j < src.rows; j++) { double distance = dist.at<float>(i, j); // abs()函数用于求绝对值 if (distance > 0) { //越靠近内部,值越大 drawImg.at<Vec3b>(i, j)[0] = (uchar)(abs(1 - distance / maxVal) * 230); drawImg.at<Vec3b>(i, j)[1] = (uchar)(abs(1 - distance / maxVal) * 210); } else if (distance < 0) { //越远离边缘,值越小(绝对值越大) //drawImg.at<Vec3b>(i, j)[0] = (uchar)(abs(1 - distance / maxVal) * 127); // 加上这里,效果原因暂时未知 drawImg.at<Vec3b>(i, j)[2] = (uchar)(abs(1 - distance / minVal) * 127); } else { drawImg.at<Vec3b>(i, j) = Vec3b(255, 255, 255); } } } imshow("drawImg", drawImg); waitKey(0); return 0; }结果展示