OpenCV之图像处理(三十三) 点多边形测试

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

pointPolygonTest( // 点多边形测试,返回数据是double类型
    InputArray  contour, // 输入的轮廓
    Point2f  pt, // 测试点
    bool  measureDist // 是否返回距离值,如果是false,1表示在内面,0表示在边界上,-1表示在外部,true返回实际距离(pt和轮廓中与pt坐标位置最近的点的距离?)
)

代码

    #include "../common/common.hpp"

    void main(int argc, char** argv)
    {
        //绘制一张6边形的图像
        const int r = 100;
        Mat src = Mat::zeros(r * 4, r * 4, CV_8UC1);
        vector<Point2f> vert(6);
        vert[0] = Point(3 * r / 2, static_cast<int>(1.34*r));
        vert[1] = Point(1 * r, 2 * r);
        vert[2] = Point(3 * r / 2, static_cast<int>(2.866*r));
        vert[3] = Point(5 * r / 2, static_cast<int>(2.866*r));
        vert[4] = Point(3 * r, 2 * r);
        vert[5] = Point(5 * r / 2, static_cast<int>(1.34*r));
        for (int i = 0; i < 6; i++) {
            line(src, vert[i], vert[(i + 1) % 6], Scalar(255), 3, 8, 0);
        }
        imshow("src33", src);

        vector<vector<Point>> contours;
        vector<Vec4i> hierachy;
        Mat csrc;
        src.copyTo(csrc);// findContours 会改动输入图像 src 中元素的值,所以这里需要完全复制一份src
        findContours(csrc, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));//发现轮廓
        printf("contours.size=%d\n", contours.size());// 2
        Mat raw_dist = Mat::zeros(csrc.size(), CV_32FC1);//存放图像每个坐标位置到轮廓的距离
        for (int row = 0; row < raw_dist.rows; row++) {
            for (int col = 0; col < raw_dist.cols; col++) {
                double dist = pointPolygonTest(contours[0], 
                    Point2f(static_cast<float>(col), static_cast<float>(row)), true);//点多边形测试
                printf("dist(%d,%d) = %.2f,", row, col, dist);
                raw_dist.at<float>(row, col) = static_cast<float>(dist);
            }
        }
        //绘制原图轮廓
        Mat dst = Mat::zeros(src.size(), CV_8UC3);
        for (size_t i = 0; i < contours.size(); i++) {
            drawContours(dst, contours, i, Scalar(0, i == 0 ? 0 : 255, 255), 2, 8, hierachy, 0, Point(0, 0));
        }
        imshow("foundContours33", dst);

        // 绘制距离色差图,类似于 距离变换
        double minValue, maxValue;
        minMaxLoc(raw_dist, &minValue, &maxValue, 0, 0, Mat());//获取最大最小距离,方便颜色归一化到255之间
        printf("\nminValue=%.2f, maxValue=%.2f\n", minValue, maxValue);
        Mat drawImg = Mat::zeros(src.size(), CV_8UC3);//用彩色图反差距离
        for (int row = 0; row < drawImg.rows; row++) {
            for (int col = 0; col < drawImg.cols; col++) {
                float dist = raw_dist.at<float>(row, col);
                if (dist > 0) { // 轮廓内部,越靠近轮廓中心点越黑
                    drawImg.at<Vec3b>(row, col)[0] = (uchar)(abs(1.0 - (dist / maxValue)) * 255);//蓝
                }
                else if (dist < 0) { // 轮廓外部,越远离轮廓越黑
                    drawImg.at<Vec3b>(row, col)[2] = (uchar)(abs(1.0 - (dist / minValue)) * 255);//红
                }
                else { // 轮廓边线上,白色
                    drawImg.at<Vec3b>(row, col)[0] = (uchar)(abs(255 - dist));
                    drawImg.at<Vec3b>(row, col)[1] = (uchar)(abs(255 - dist));
                    drawImg.at<Vec3b>(row, col)[2] = (uchar)(abs(255 - dist));
                }
            }
        }
        imshow("pointPolygonTest", drawImg);

        waitKey(0);
    }

效果图

这里写图片描述

猜你喜欢

转载自blog.csdn.net/huanghuangjin/article/details/81191011