当前位置: 首页 > news >正文

RDP直线圆弧分割算法

参考资料:https://blog.csdn.net/x454045816/article/details/52703628

介绍

RDP(Ramer-Douglas-Peucker)算法用来对连续的边缘点集进行多边形逼近。因此也用来对边缘进行直线和圆弧的分割。

关于直线和圆弧分割算法,在halcon中有一个算子,segment_contours_xld,

关于直线和圆弧的连接算法,halcon中有两个算子,

union_cocircular_contours_xld,union_collinear_contours_xld

这两个算法的实现都依赖于RDP算法。因此本文对RDP算法的原理和代码实现进行介绍。

后续会有边缘分割和共线共圆边缘聚合的相关算法原理与实现的介绍,其实早就实现了,只是平时太忙了,这次趁着国庆假期做一些总结。

原理

首先,在轮廓的起点和终点之间建立一条线段,然后计算所有轮廓控制点到线段的距离,并从中选出距离最大的控制点。如果此距离比指定的阈值大,那么在对应最大距离控制点处将当前线段再次细分成两段。在新得到的线段上重复进行上述处理。如下图所示:
请添加图片描述

编码实现

计算轮廓上任意一点到轮廓首尾连线的垂直距离最大值及取最大值时点的索引。

const std::pair<int, double> findMaximumDistance(const vector<PointF>& Points)const 
{
	auto firstpoint = Points[0];
	auto lastpoint = Points[Points.size() - 1];
	int index = 0;  //index to be returned
	double Mdist = -1; //the Maximum distance to be returned

	//distance calculation
	PointF p = lastpoint - firstpoint;
	for (int i = 1; i < Points.size() - 1; i++)
	{ 
		//traverse through second point to second last point
		PointF pp = Points[i] - firstpoint;

		//formula for point-to-line distance
		double Dist = fabs(pp * p) / p.Norm(); 
		if (Dist > Mdist)
		{
			Mdist = Dist;
			index = i;
		}
	}
	return std::make_pair(index, Mdist);
}

采用递归的方式,将一条边缘化简为一个多边形逼近的顶点。显然,如果边缘很直,则化简后点数量很少,反之,如果边缘弯曲位置很多,比如圆弧的情况,则化简后点数量较多。

vector<PointF> simplifyWithRDP(vector<PointF>& Points, double epsilon)const 
{
	if (Points.size() < 3)
	{  
		//终止情况1,点数少于3个
		return Points;
	}
	std::pair<int, double> maxDistance = findMaximumDistance(Points);
	if (maxDistance.second >= epsilon)
	{
		int index = maxDistance.first;
		auto it = Points.begin();
		vector<PointF> path1(Points.begin(), it + index + 1); 
		vector<PointF> path2(it + index, Points.end());

		auto r1 = simplifyWithRDP(path1, epsilon);
		auto r2 = simplifyWithRDP(path2, epsilon);

		//Concat simplified path1 and path2 together
		vector<PointF> rs(r1);
		rs.pop_back();
		rs.insert(rs.end(), r2.begin(), r2.end());
		return rs;
	}
	else
	{ 
		//终止条件2: 中间的所有点都可以被拿掉
		vector<PointF> r(1, Points[0]);
		r.push_back(Points[Points.size() - 1]);
		return r;
	}
}

这个算法当前没有一个可视的效果,后续在写亚像素找边,边缘分割,边缘聚合相关算法时会有一个总体的demo,用来展示效果。

相关文章:

  • 为什么有的python内置函数怎么就一个pass?
  • 主从复制 读写分离
  • flink-taskmanager内存计算
  • 大数据复习(day03)
  • C++ 优先队列 priority_queue 使用篇
  • 同事嫌我改Bug慢,原来是没掌握这些代码Debug技巧
  • 图文讲解带你拿捏MyBatis(一)——MyBatis入门
  • [Python]Django类视图
  • 重识Nginx - 12 SSL/TLS 浅析
  • 神经网络做多元线性回归,神经网络是线性模型吗
  • 如何查看Debian/Ubuntu和RHEL/AlmaLinux/Rocky软件包的更新日志
  • Java—多线程
  • 【第九篇】商城系统-商城首页功能
  • 【SpringBoot+MyBatisPlus】系统全局异常处理器的使用以及添加员工功能的实现
  • FreeRTOS大杂烩
  • Angular 响应式表单 基础例子
  • emacs初体验
  • NLPIR语义挖掘平台推动行业大数据应用服务
  • React16时代,该用什么姿势写 React ?
  • vue-router的history模式发布配置
  • 阿里云Kubernetes容器服务上体验Knative
  • 它承受着该等级不该有的简单, leetcode 564 寻找最近的回文数
  • 小程序测试方案初探
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • 选择阿里云数据库HBase版十大理由
  • # Maven错误Error executing Maven
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (pojstep1.1.1)poj 1298(直叙式模拟)
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (第二周)效能测试
  • (经验分享)作为一名普通本科计算机专业学生,我大学四年到底走了多少弯路
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • (转)http-server应用
  • (转)大道至简,职场上做人做事做管理
  • (转贴)用VML开发工作流设计器 UCML.NET工作流管理系统
  • *Django中的Ajax 纯js的书写样式1
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法
  • .NET Core跨平台微服务学习资源
  • .NET DevOps 接入指南 | 1. GitLab 安装
  • .NET Reactor简单使用教程
  • .NET基础篇——反射的奥妙
  • @zabbix数据库历史与趋势数据占用优化(mysql存储查询)
  • [2016.7 test.5] T1
  • [ASP]青辰网络考试管理系统NES X3.5
  • [Bugku]密码???[writeup]
  • [C#]DataTable常用操作总结【转】
  • [CareerCup] 14.5 Object Reflection 对象反射
  • [CISCN2019 华东北赛区]Web2
  • [github全教程]github版本控制最全教学------- 大厂找工作面试必备!
  • [hdu 3065] 病毒侵袭持续中 [AC自动机] [病毒特征码匹配]
  • [HNOI2015]实验比较
  • [HTTP]HTTP协议的状态码
  • [LeetBook]【学习日记】获取子字符串 + 颠倒子字符串顺序