Opencv4:优化轮廓中提取Polygon点的实现

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)算法处理结果:

             如果后续有进一步优化会继续更新。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值