OpenCV25-判断一个点是否在多边形的内部_点多边形测试pointPolygonTest

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;

}
欢迎讨论,相互学习。 txwtech@163.com
原文地址:https://www.cnblogs.com/txwtech/p/14706949.html