Opencv4:轮廓中提取Polygon点的实现
(1)轮廓中提取Polygon点的传统方法:
①设定一个阈值threshold;
②在目标轮廓选取两点A,B;
③计算在目标轮廓上A,B两点间所有点到AB直线间的距离,确定其中距AB直线间的距离最大的点C,它所对应的最大距离为distance;
④比较最大距离distance和阈值threshold,如果距离小于阈值,迭代结束;
⑤C点将目标轮廓分为AC和CB两条曲线,对这两条曲线重复以上步骤,递归调用,不断迭代求解,直到目标图象的边界曲线上所有点与拟合多边形各边的距离小于设定的阈值,记录所有距离符合条件的点。
(2)优化轮廓中提取Polygon点的思路:
①设定一个阈值threshold;
②在目标轮廓选取一个子段起点A,选取一个子段终点B=A+threshold*3;
③已知起点A到A+threshold之间的点,与A+threshold*2到终点B之间的点到AB直线之间的距离一定不大于threshold,只需计算A+threshold与A+threshold*2之间的点到AB直线的距离;
④确定其中距离最大的点C,比较C点对应的最大距离distance和阈值threshold,如果距离小于阈值,进行下一步,如果距离大于阈值,保存这个点;
⑤以A+threshold点为起点重复以上步骤,直到遍历整个轮廓,记录所有距离符合条件的点,如图所示。
(3)优化轮廓中提取Polygon点的代码实现:
#include <opencv2\opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
//【1】polygon点提取算法
vector<Point> GenPolygonContoursXld(vector<vector<Point>> &contours,int thresh)
{
vector<Point> Points;
float distance, distanceMax=0;
//[1]一层循环:遍历轮廓集合中各轮廓
for (int i = 0; i < contours.size(); i++)
{
//[2]二层循环:遍历轮廓上点作为polygon检测的起点
if(contours[i].size()>=thresh * 3)
{
for (int j = 0; j < contours[i].size()-thresh * 3-1; j=j+thresh)
{
distanceMax = 0;
int indexMax = 0;
//[3]三层循环:遍历T到2T内,距离起点和3T点所连直线距离最大的点,判断是否大于T,大于则保留
CvPoint A = contours[i][j];
int b = j + thresh * 3;
CvPoint B = contours[i][b];
for (int k= thresh;k<thresh*2;k++)
{
distance = Distance_pl(contours[i][j+k], A, B);
if (distance > distanceMax)
{
distanceMax = distance;
indexMax = k;
}
}
if (distanceMax >= thresh)
{
Points.push_back(contours[i][j + indexMax]);
}
}
}
}
return Points;
}
【2】点到直线距离计算
float Distance_pl(CvPoint pointP, CvPoint pointA, CvPoint pointB)
{
//求直线方程
int A = 0, B = 0, C = 0;
A = pointA.y - pointB.y;
B = pointB.x - pointA.x;
C = pointA.x*pointB.y - pointA.y*pointB.x;
//代入点到直线距离公式
float distance = 0;
distance = ((float)abs(A*pointP.x + B*pointP.y + C)) / ((float)sqrtf(A*A + B*B));
return distance;
}
int main()
{
//【1】图像读取
Mat image = imread("12.png", 0);
Mat imageThreshold;
vector<vector<Point>>contours;
vector<Vec4i>hierarchy;
//【2】图像处理
//已封装的查找轮廓函数,可用findcontours()替换
Mat imageResult=ContoursThreshold(image,imageThreshold, contours, hierarchy,30,Scalar(255, 255, 255));
vector<Point> Points = GenPolygonContoursXld(contours, 1);
for (size_t i=0; i < Points.size(); i++)
{
circle(image, Points[i], 2, Scalar(255,255, 255), -1, 20, 0);
}
//【3】结果显示
imshow(" window1", image);
waitKey(0);
system("pause");
return 0;
}
(4)算法处理结果:
如果后续有进一步优化会继续更新。