opencv之点与多边形位置关系测试

概念介绍

测试一个点是否在给定的多边形内部,边缘或者外部


API介绍

API
double cv::pointPolygonTest(InputArray contour, Point2f pt, bool measureDist)
参数介绍

  • 第一个参数InputArray contour,输入的轮廓
  • 第二个参数Point2f pt,需要测试的点坐标
  • 第三个参数bool measureDist
    • measureDist设置为true时,返回实际距离值。若返回值为正,表示点在多边形内部,返回值为负,表示在多边形外部,返回值为0,表示在多边形上。
    • measureDist设置为false时,返回 -101三个固定值。若返回值为+1,表示点在多边形内部,返回值为-1,表示在多边形外部,返回值为0,表示在多边形上。
  • 返回值为double类型

演示代码处理步骤

  • 构建一张400x400大小的图片,Mat::zero(400,400,cv_8UC1);
  • 画上一个六边形闭合区域line
  • 发现轮廓
  • 对图像中所有的点做点、多边形测试,得到距离,归一化后显示。

代码演示


#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace cv;
using namespace std;
int main(void)
{
	int r = 100;     //定义图片边缘
	Mat src = Mat::zeros(4*r,4*r,CV_8UC1);  //创建一张图片

	//绘制六边形
	vector<Point2f> vect(6);
	//六边形顶点赋值
	vect[0] = Point(3 * r / 2, static_cast<int>(1.34 * r));
	vect[1] = Point(1 * r , 2 * r);
	vect[2] = Point(3 * r / 2, static_cast<int>(2.866 * r));
	vect[3] = Point(5 * r / 2, static_cast<int>(2.886 * r));
	vect[4] = Point(3 * r , 2 * r);
	vect[5] = Point(5 * r / 2, static_cast<int>(1.34 * r));
	
	if (src.empty()) {
		cout << "图片不存在" << endl;
		return -1;
	}

	//绘制六边形
	for (size_t i = 0; i < 6; i++)
	{
		line(src, vect[i], vect[(i + 1)%6], Scalar(255), 2, 8, 0);   //循环划线绘制闭合多边形
	}
	namedWindow("原始图片", WINDOW_AUTOSIZE);
	imshow("原始图片", src);

	//寻找轮廓
	vector<vector<Point>> contours;   //定义轮廓点集
	vector<Vec4i> hierarchy;          //定义轮廓拓扑关系
	findContours(src, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));   //寻找轮廓

	Mat raw_dist = Mat::zeros(src.size(), CV_32FC1);   //存储点与轮廓的距离信息
	for(size_t row = 0;row<raw_dist.rows;row++)   //行数
		for (size_t col = 0; col < raw_dist.cols; col++)
		{
			//获取每个点与轮廓的距离  并 存储
			double dist = pointPolygonTest(contours[0], Point(static_cast<float>(col), static_cast<float>(row)), true);
			raw_dist.at<float>(row, col) = static_cast<float>(dist);
		}

	double minValue, maxValue;   //定义最大值 最小值变量
	minMaxLoc(raw_dist, &minValue, &maxValue);   //获取图片距离的最大值最小值

	Mat dst = Mat::zeros(400,400,CV_8UC3);  //创建一个rgb3通道图,用来显示距离关系

	for (size_t row = 0; row < dst.rows; row++)   //行数
		for (size_t col = 0; col < dst.cols; col++)
		{
			float distance = raw_dist.at<float>(row, col);
			if (distance > 0)   //多边形内部
			{
				dst.at<Vec3b>(row, col)[0] = (uchar)(abs(distance / maxValue * 255));   //通道b 赋值
			}
			else if (distance < 0)  //多边形外部
			{
				dst.at<Vec3b>(row, col)[2] = (uchar)(abs(distance/minValue * 255));     //通道r 赋值
			}
			else   //在边缘上赋值
			{
				dst.at<Vec3b>(row, col)[0] = (uchar)(abs(255-distance));
				dst.at<Vec3b>(row, col)[1] = (uchar)(abs(255 - distance));
				dst.at<Vec3b>(row, col)[2] = (uchar)(abs(255 - distance));
			}
		}
	namedWindow("最终图片", WINDOW_AUTOSIZE);
	imshow("最终图片", dst);
	
	waitKey(0);
	destroyAllWindows();
	return 0;
}

程序运行结果

在这里插入图片描述


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值