OpenCV学习三十三:pointPolygonTest 检测点是否在轮廓内

opencv函数

pointPolygonTest:

C++: double pointPolygonTest(InputArray contour, Point2f pt, bool measureDist)

用于测试一个点是否在多边形中
当measureDist设置为true时,返回实际距离值。若返回值为正,表示点在多边形内部,返回值为负,表示在多边形外部,返回值为0,表示在多边形上。
当measureDist设置为false时,返回 -1、0、1三个固定值。若返回值为+1,表示点在多边形内部,返回值为-1,表示在多边形外部,返回值为0,表示在多边形上。

#include <opencv2/opencv.hpp>
#include "iostream"

using namespace std;
using namespace cv;

int main( int argc, char** argv )
{
	Mat img = imread("fengye.jpg");
	threshold(img, img, 127, 255, CV_THRESH_BINARY);
	cvtColor(img ,img ,CV_BGR2GRAY);
	
	vector<vector<Point>> contours;
	vector<Vec4i> hierachy;
	findContours(img, contours, hierachy, RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
	drawContours(img, contours, 1, Scalar::all(255), 2, 8, hierachy);

	//这里说明下,轮廓1是圈出的枫叶
	Mat dist = Mat::zeros(img.size(), CV_32FC1);
	for (int i=0; i<img.rows; i++)	{
		for (int j=0; j<img.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(img.size(), CV_8UC3);
	int thredVal1 = 1;
	for (int i=0; i<img.rows; i++)	{
		for (int j=0; j<img.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("drawImg1", drawImg1);
	imwrite("drawImg1.jpg", drawImg1);



	normalize(dist, dist, -255, 255, NORM_MINMAX);
	Mat drawImg2 = Mat::zeros(img.size(), CV_8UC3);
	int thredVal2 = 3;
	for (int i=0; i<img.rows; i++)	{
		for (int j=0; j<img.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);
	imwrite("drawImg2.jpg", drawImg2);
	
	imshow("img", img);
		
	waitKey();
	return 0;
}

原图

 

drawImg1

 

drawImg2

说明下:白色线的位置差异是由于归一化的方式不同,在第一种方式中肯定可以锁定到轮廓上,在第二种方式中由于最大最小距离的绝对值不同。

  • 11
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值