点多边形测试

点多边形测试

  • 测试一个点是否在给定的多边形内部、边缘或外部。

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;
}

结果展示
在这里插入图片描述在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值