OpenCV官网
#include
#include
using namespace cv;
using namespace std;
int main(void)
{
const int r=100;
Mat src = Mat::zeros(Size(4*r, 4*r), CV_8U);
vector<Point> vert(6);
vert[0] = Point(3*r/2,static_cast<int>(1.34*r));
vert[1] = Point(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); //在src中创建一个六边形
}
vector<vector<Point>> contours;
findContours(src, contours, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE); //检测六边形的轮廓
Mat raw_dist(src.size(), CV_32F); //存放每个点的检测结果,所以定义为CV_32F
for(int i=0; i<src.rows; i++)
{
for(int j=0; j<src.cols; j++)
{
raw_dist.at<float>(i,j) = (float)cv::pointPolygonTest(contours[0], Point2f((float)j, (float)i), true); // 对于每个点都去检测
}
}
double minVal, maxVal;
Point maxDistPt;
cv::minMaxLoc(raw_dist,&minVal, &maxVal, NULL, &maxDistPt); //找到最大值和最小值,以及他们的位置
minVal = abs(minVal); //因为最小值肯定是负值,在contour外都是负值,所以取绝对值
maxVal = abs(maxVal);
Mat drawing = Mat::zeros(src.size(), CV_8UC3); //将结果显示此图中
for(int i=0; i<src.rows; i++)
{
for(int j=0; j<src.cols; j++)
{
if(raw_dist.at<float>(i,j) < 0) //在contour外
{
drawing.at<Vec3b>(i,j)[0] = (uchar)(255-abs(raw_dist.at<float>(i,j))*255/minVal); //,minVal已经取abs,minVal是contour外距离最远点,距离边界越远,蓝色成分越小
}
else if(raw_dist.at<float>(i,j)>0) //在contour内
{
drawing.at<Vec3b>(i,j)[2] = (uchar)(255-raw_dist.at<float>(i,j)*255/maxVal); //距离边界越远,红色成分越小
}
else // 边界上,白色
{
drawing.at<Vec3b>(i,j)[0] = 255 ;
drawing.at<Vec3b>(i,j)[1] = 255 ;
drawing.at<Vec3b>(i,j)[2] = 255 ;
}
}
}
circle(drawing, maxDistPt, (int)maxVal, Scalar(255,255,255)); //maxDistPt 应该是contours里面最中心的位置,maxVal:到边界的距离,所以应该是一个内接圆
imshow("source", src);
imshow("Distance and inscribed circle", drawing);
waitKey();
return 0;
};
结果:和代码中注释分析一样,接近contour颜色深,远离边界(往内,往外两个方向),颜色开始变浅到黑。
double cv::pointPolygonTest
( InputArray contour, //一组点组成contour vector
Point2f pt, // 被检测的点
bool measureDist // true: 内部是正数,边界是0,外部是负数,绝对值是点到最近一条边的距离; false: 检测点是否在内部、外部、边界,返回+1、-1、0
)