道格拉斯-普克算法

道格拉斯-普克算法 (Douglas–Peucker algorithm,亦称为拉默-道格拉斯-普克算法、迭代适应点算法、分裂与合并算法)是乌尔斯·拉默(Urs Ramer)于1972年以及大卫·道格拉斯(David Douglas)和托马斯·普克(Thomas Peucker)于1973年提出的一种简化线的一种经典算法。

它是通过减少曲线中点的数量,得出一条尽可能完整的表达原有曲线的特征的曲线。

一般来讲,道格拉斯-普克算法需要一个极差D,极差D的值越大,证明曲线简化的越多,反之极差越小,表示简化的越小

通俗的理解,道格拉斯-普克算法是通过分治策略处理一组曲线,而极差D则可以理解为一个比较值,或者可以说是一个临界点,通过对垂距大于此临界点的点进行保留,对小于此临界点的点进行删除,达到简化曲线的效果

算法的基本思路是:

对曲线的首末点虚连一条直线,求此曲线其余所有点到直线的距离(垂距),从中找出最大距离值dmax ,用dmax与限差D相比:若dmax <D,这条曲线上的中间点全部舍去;若dmax ≥D,保留dmax 对应的坐标点,并以该点为界,把曲线分为两部分,对这两部分重复使用该方法,当曲线无法分为两部分时结束。

具体步骤如下:

(1) 在曲线首尾两点间虚连一条直线,求出其余各点到该直线的距离。

(2)选其最大者与极差D相比较,若大于极差D,则离该直线距离最大的点保留,否则将直线两端点间各点全部舍去。

(3)以保留的点为中心,将已知曲线分成两部分处理,重复执行第1、2步操作,迭代操作,即仍选该直线距离最大者与极差D比较,依次取舍,直到无点可舍去,最后得到满足给定精度限差为D的曲线点坐标

具体的实现过程如下图(此图来自于网络)

在计算最大距离的时候(垂距),一般来讲,我们知道三个点的坐标,两个坐标点形成得直线,求另一个坐标点到此直线的距离。

一般来讲,行列式算法,海伦公式,向量法,都可以求出面积;

这里介绍下行列式算法:

已知三个点坐标(x1,y1),(x2,y2),(x3,y3)

由此三角形构成的面积是|S|注意是S的绝对值,因为坐标的方向不确定。

下面是S的求值

求出面积后,用面积公式,得到高(垂距),找出所有点中垂距的最大值与极差D比较。

下面简要写出道格拉斯-普克算法的代码,由于是采用传统的迭代方法,存在一定的弊端

qt代码如下:

#include <QPoint>
#include <QVector>
/**
 * @brief CPointRarefyOprt::PerpendicularDistance 计算点到首尾连线间的距离(垂距)
 * @param Point1                                  首坐标
 * @param Point2                                  尾坐标
 * @param Point                                   要计算到直线距离的点
 * @return 
 */
double PerpendicularDistance(const QPoint &Point1, const QPoint &Point2, const QPoint &Point)
{
    //行列式算法的展开
    double area = fabsf(0.5 * (Point1.x * Point2.y + Point2.x * Point.y + Point.x * Point1.y - Point2.x * Point1.y - Point.x * Point2.y - Point1.x * Point.y));
    double bottom = sqrtf(pow(Point1.x - Point2.x, 2) + pow(Point1.y - Point2.y, 2));
    double height = area / bottom * 2;
    return height;
}
/**
 * @brief DouglasPeuckerReduction  道格拉斯——普克算法
 * @param Points                   要进行简化的曲线的点列
 * @param startPoint               进行此算法的曲线开始的点的数组下标
 * @param endPoint                 进行此算法的曲线结束的点的数组下标
 * @param tolerance                极差D(阈值)
 * @param resultPoints             得到的简化的曲线
 */
void DouglasPeuckerReduction(QVector<QPoint> Points,int startPoint
                             ,int endPoint, double tolerance,QVector<QPoint> resultPoints)
{
    double maxDistance = 0; //最远距离(垂距)
    int indexFarthest = -1;  //最远距离点的数组下标
    if(endPoint-startPoint<=1)
    {
        if(endPoint==startPoint)
        {
            //endPoint==startPoint相等时,只有一个点时,所以添加一个点
            resultPoints.append(points[startPoint]);
        }
        else
        {
            //有两个点时,添加两个点
            resultPoints.append(points[startPoint]);
            resultPoints.append(points[endPoint]);   
        }
        //当小于等于两个点时,直接返回
        return;
    }
    for (int index = startPoint; index < endPoint; index++)
    {
        double distance = PerpendicularDistance(points[startPoint],points[endPoint],points[index]);
        if (distance > maxDistance)
        {
            //当新得到的点的垂距大于之前的最大垂距时,更新最大垂距,并且更新最大垂距点的下标
            maxDistance = distance;
            indexFarthest = index;
        }
    }
    if (maxDistance > tolerance && indexFarthest != -1)
    {
        //对起始点到最大垂距点之间的点重复进行道格拉斯——普克算法
        DouglasPeuckerReduction(points, startPoint,indexFarthest-1, tolerance, resultPoints);
        //将最大垂距点保留
        resultPoints.append(points[indexFarthest]);
        //对最大垂距点到结束点之间的点重复进行道格拉斯——普克算法
        DouglasPeuckerReduction(points, indexFarthest+1,endPoint, tolerance, resultPoints);
    }
    
    return;
}

//第一次写博客,以前一直想写,但总不知道写些什么,或者感觉想写的东西太过于简单,或者感觉想写的东西自己无法合理的表示//写这个东西用了两个多小时,借鉴了一些文档,但其中还是不免有许多错误,求指点,感激不尽//或许很简单,或许很多错误,但是当我鼓足勇气写完之后,忽然发现,原来坚持写比什么都重要

转载于:https://www.cnblogs.com/wpch1993/p/6558086.html

170316.道格拉斯-普克算法相关推荐

  1. c++多边形扫描线填充算法_基于MATLAB的道格拉斯普克算法递归实现

    道格拉斯普克算法 (道格拉斯-普克)Douglas-Peukcer算法由D.Douglas和T.Peueker于1973年提出,是线状要素抽稀的经典算法.用它处理大量冗余的几何数据点,既可以达到数据量 ...

  2. opencv 凸包convexHull、道格拉斯-普克算法Douglas-Peucker algorithm、approxPloyDP 函数

    凸包convexHull.道格拉斯-普克算法Douglas-Peucker algorithm.approxPloyDP 函数 道格拉斯-普克算法(Douglas–Peucker algorithm) ...

  3. OpenCV 学习笔记03 凸包convexHull、道格拉斯-普克算法Douglas-Peucker algorithm、approxPloyDP 函数...

    凸形状内部的任意两点的连线都应该在形状里面. 1 道格拉斯-普克算法 Douglas-Peucker algorithm 这个算法在其他文章中讲述的非常详细,此处就详细撰述. 下图是引用维基百科的.ε ...

  4. 基于道格拉斯普克算法的轮廓点简化

    道格拉斯普克算法(DP)对元素进行简化,这里介绍对轮廓点进行简化,如下图展示了轮廓点提取.DP保留的关键点.关键点生成的矢量线:  简化点连接生成的多边形 DP简化轮廓点后的关键点  关键点相连生成的 ...

  5. 道格拉斯-普克算法(Douglas–Peucker algorithm)

    道格拉斯-普克算法(Douglas–Peucker algorithm,亦称为拉默-道格拉斯-普克算法.迭代适应点算法.分裂与合并算法)是将曲线近似表示为一系列点,并减少点的数量的一种算法.该算法的原 ...

  6. matlab Douglas-Peucker 道格拉斯-普克算法

    c道格拉斯-普克算法 [1]  (Douglas–Peucker algorithm,亦称为拉默-道格拉斯-普克算法.迭代适应点算法.分裂与合并算法)是将曲线近似表示为一系列点,并减少点的数量的一种算 ...

  7. 道格拉斯-普克算法(经纬度或坐标点抽稀)

    起因 最近在做一个车联网项目,有一个场景是车辆定时上报当前所在经纬度等位置信息上报给平台,平台通过web页面在高德地图上展示车辆行驶路径. 由于车辆上报规则是每隔4s上报一次,一个小时也就是900个点 ...

  8. 【图像处理】道格拉斯-普克算法(曲线的折线段逼近)

    目录 一.提要 二.为什么要道格拉斯-普克算法 三.算法描述 四.代码实现 4.1 Python代码1 4.2 python代码2 五.结论 该文的应用见文章:[Halcon算子]get_contou ...

  9. C语言程序实现道格拉斯—普克算法(Douglas--Peucker)

    算法简介 道格拉斯-普克算法(Douglas-Peucker)也称,线简化算法.作用在于,删除冗余数据,减少数据的存贮量,节省存贮空间,加快后继处理的速度. 格拉斯-普克算法(Douglas-Peuc ...

最新文章

  1. javascript数组集锦
  2. html wbr标签,HTML wbr标签
  3. redis 漏洞利用与防御
  4. 160. Intersection of Two Linked Lists
  5. MongoDB存储文件之GridFS
  6. 深入理解Three.js(WebGL)贴图(纹理映射)和UV映射
  7. 短网址PHP源码Shortny
  8. 不要再使用JS框架了
  9. jvm虚拟机创建对象
  10. 搜索引擎只能抓取html文件,为什么有些明明存在的网页不能被搜索到?
  11. 初级通信工程师考试教程:电信网的划分
  12. [转]420个JS网页特效
  13. 短信接口的功能及适用范围
  14. DongDong数颜色 树状数组,dfs序,统计区间不同数字个数
  15. 基于相似性网络融合的目标分类研究
  16. D-Link DCS系列监控账号密码信息泄露
  17. win10系统无法正常自动启动服务
  18. 货币金融学——金融体系监管
  19. Undetected
  20. Java中Lambda表达式使用及详解

热门文章

  1. u盘排序软件_华硕电脑u盘启动设置
  2. int** 赋值_Python的赋值、浅拷贝、深拷贝之间的区别
  3. php文件教程,php的文件上传入门教程(实例讲解)
  4. php try catch 作用域,php作用域
  5. python 字符串去重且相同字符最多出现2次_Python实现计算字符串中出现次数最多的字符示例...
  6. amd 深度学习模型部署_Web服务部署深度学习模型-续集
  7. java与c 通信_Java与C之间的socket通信
  8. (六) shiro在web中自定义Realm
  9. java面试题二十八 从未用过的 native
  10. log4j 调试时候配置