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;
}