点多边形测试
- 测试一个点是否在给定的多边形内部、边缘或外部。
API介绍
- double pointPolygonTest (
InputArray contour, // 输入的轮廓
Point2f pt, // 测试点
bool measureDist
) - 第三个参数 measureDist:
当 measureDist 设置为 true 时,返回实际距离值。若返回值为正,表示点在多边形内部;返回值为负,表示在多边形外部;返回值为0,表示在多边形上。且越靠近内部,值越大,越远离边缘,值越小(绝对值越大)。
当 measureDist 设置为 false 时,返回 -1、0、1三个固定值。若返回值为+1,表示点在多边形内部;返回值为-1,表示在多边形外部;返回值为0,表示在多边形上。该过程不计算距离值,运行速度更快。
程序示例
int main()
{
// 输入并显示图像
Mat src = imread("E:/Image/fy.jpg");
if (src.empty())
{
cout << "could not load image..." << endl;
return 0;
}
imshow("src", src);
// 灰度和二值化处理
cvtColor(src, src, CV_BGR2GRAY);
threshold(src, src, 180, 255, CV_THRESH_BINARY);
// 寻找轮廓
vector<vector<Point>> contours;
vector<Vec4i> hierachy;
Mat dst = Mat::zeros(src.size(), src.type());
findContours(src, contours, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
// 计算距离
Mat dist = Mat::zeros(src.size(), CV_32FC1);
for (int i = 0; i < src.cols; i++)
{
for (int j = 0; j < src.rows; j++)
{
//contours共有两个,这里取contours[1],contours[0]包含图像的四个点
//这里Point2f(j,i) 代表的x,y是不是反了?不清楚为什么
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 drawImg = Mat::zeros(src.size(), CV_8UC3);
for (int i = 0; i < src.cols; i++)
{
for (int j = 0; j < src.rows; j++)
{
double distance = dist.at<float>(i, j);
// abs()函数用于求绝对值
if (distance > 0)
{
//越靠近内部,值越大
drawImg.at<Vec3b>(i, j)[0] = (uchar)(abs(1 - distance / maxVal) * 230);
drawImg.at<Vec3b>(i, j)[1] = (uchar)(abs(1 - distance / maxVal) * 210);
}
else if (distance < 0)
{
//越远离边缘,值越小(绝对值越大)
//drawImg.at<Vec3b>(i, j)[0] = (uchar)(abs(1 - distance / maxVal) * 127); // 加上这里,效果原因暂时未知
drawImg.at<Vec3b>(i, j)[2] = (uchar)(abs(1 - distance / minVal) * 127);
}
else
{
drawImg.at<Vec3b>(i, j) = Vec3b(255, 255, 255);
}
}
}
imshow("drawImg", drawImg);
waitKey(0);
return 0;
}
结果展示