1. 概念介绍
- 点多边形测试就是测试一个点是否在给定多边形的内部、边缘或外部,可用于做归一化显示。
2. 相关API
2.1 cv::pointPolygonTest()
double pointPolygonTest(
InputArray contour,// 输入的轮廓
Point2f pt, // 测试点
bool measureDist // 是否返回距离值,如果是false,1表示在内面,0表示在边界上,-1表示在外部; true返回实际距离
)
3. 例程
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
using namespace cv;
using namespace std;
int Threshold=140;
void CallBack(int, void*);
int r = 100;
Mat src = Mat::zeros(r * 3, r * 3, CV_8UC3);
int main() {
//绘制一个五边形
vector<Point2f> pts(5);
pts[0] = Point(r, r);
pts[1] = Point(r * 2, r);
pts[2] = Point(r * 2, r*2);
pts[3] = Point(r, r*2);
pts[4] = Point(r - 50, r + 50);
for (int i = 0; i < 5; i++) {
line(src, pts[i], pts[(i + 1) % 5], Scalar(0, 255, 255), 2, 8);
}
imshow("input", src);
namedWindow("output");
createTrackbar("Threshold:", "output", &Threshold, 255, CallBack);
CallBack(0, 0);
waitKey(0);
return -1;
}
void CallBack(int, void*) {
//提取边缘
Mat canny_out;
Canny(src, canny_out, Threshold, Threshold * 2);
imshow("canny_out", canny_out);
vector<vector<Point>> contours;
findContours(canny_out, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE,Point(0,0));
//将各点与多边形的距离储存在raw_dist中
Mat raw_dist(src.size(), CV_32FC1);
for(int row=0;row<src.rows;row++)
for (int col = 0; col < src.cols; col++) {
for (size_t i = 0; i < contours.size(); i++) {
double dist = pointPolygonTest(contours[i], Point2f(static_cast<float>(col), static_cast<float>(row)),true);
raw_dist.at<float>(row, col) = static_cast<float>(dist);
}
}
//通过颜色渐变表示像素点距离多边形的远近
double minDist, maxDist;
minMaxLoc(raw_dist, &minDist, &maxDist);
for(int row=0;row<src.rows;row++)
for (int col = 0; col < src.cols; col++) {
float dist = raw_dist.at<float>(row, col);
if (dist > 0) src.at<Vec3b>(row, col)[0] = (uchar)((dist/maxDist)*255);//dist大于0,该像素点在多边形内,越接近多边形中心越蓝
if (dist < 0) src.at<Vec3b>(row, col)[1] = (uchar)(abs(dist / minDist) * 255);//dist小于0,该像素点在多边形外,越远离多边形中心越绿
else src.at<Vec3b>(row, col)[2] = (uchar)(abs(255-dist));//dist=0;像素点在多边形边上,变红
}
imshow("output", src);
return;
}