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:\opencv3\opencv\build\include\opencv2\core\mat.inl.hpp, line 918
表示操作通道數錯誤,本來是單通道,卻操作了多通道。
//Mat drawImg1 = Mat::zeros(src.size(),CV_8UC1);//錯誤
Mat drawImg1 = Mat::zeros(src.size(), CV_8UC3);
*/
#include <iostream>
#include <opencv2\opencv.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;

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM