凸形状内部的任意两点的连线都应该在形状里面。

1 道格拉斯-普克算法 Douglas-Peucker algorithm

这个算法在其他文章中讲述的非常详细,此处就详细撰述。

下图是引用维基百科的。ε称之为阈值 shreshold

图一

静态图如下:

具体详细的可以参考如下两篇文章。

相关文章如下:

道格拉斯-普克 抽稀算法 附javascript实现,该文章只看他的文字讲解就好,他的代码不是通过python实现的。

道格拉斯-普克算法(Douglas–Peucker algorithm),该文章讲的也比较详细。

Ramer-Douglas-Peucker算法,维基百科的名词诠释

2 实现函数 cv2.approxPloyDP

作用:对目标图像进行(按指定精度、阈值,两者是一个概念)进行近似多边形曲线拟合。

使用一个较少顶点的曲线/多边形去拟合一个顶点较多的曲线/多边形,两曲线/多边形间的距离小于或等于某一指定精度/阈值

cv2.approxPolyDP(curve, epsilon, closed) -> approxCurve

参数:

curve - 2D点矢量,为图像的 “ 轮廓 ” 值。

epsilon - 指定近似精度的参数ε,这是原始曲线与其近似值之间的最大距离。参数越小,两直线越接近

closed - 若为true,曲线第一个点与最后一个点连接形成闭合曲线,若为false,曲线不闭合。

返回值:

approxCurve - 曲线/多边形近似结果。

备注:

为什么已经有了一个能够精确表示的轮廓 2D点矢量,却还需要得到一个近似多边形呢?

这主要是近似得到的多边形是由一组直线构成的,故能够在一个区域内定义多边形,以便后续的操作和处理,该项操作在许多计算机视觉任务中非常重要。

代码示例:

# epsilon 为近似度参数,该值需要轮廓的周长信息
# 多边形周长与源轮廓周长之比就是epsilon
epsilon = 0.01 * cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt, epsilon, True)

# approx 为列表list,若approx为元组,则需要将其转换成列表list
# 为了安全起见,可将[approx]作为参数传入函数
cv2.drawContours(img, [approx], -1, (255, 255, 0), 2)

运行:

当 epsilon 的取值不同时,会存在不同的拟合程度。

3 凸包convexHull

作用:找到2D点集的凸包

cv2.convexHull(points[, clockwise[, returnPoints]]]) -> hull

参数:

points - 2D点集 2D point set

clockwise - 布尔类型,默认false;若为true,输出的凸包则为顺时针方向;若为false,输出的凸包则为逆时针方向。注意:这里的坐标系是x轴方向指向右侧,y轴方向指向上方。

returnPoints - 布尔类型,默认true,在矩阵情况下,若为true,则返回凸包点集;若为false,则返回整数向量的索引

返回值:

hull - 输出的凸包,是整数向量的索引(an integer vector of indices)或点集向量(vector of points)

代码示例:

hull = cv2.convexHull(cnt)

运行:

4 代码综合

4.1 保留原始图像

将上述代码进行综合,示例如下

import cv2
import numpy as np

img = cv2.imread('Mjolnir.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) 

for cnt in contours:

    # ----源轮廓-------
    cv2.drawContours(img, [cnt], -1, (0, 255, 0), 2)

    # 近似多边形
    # epsilon 为近似度参数,该值需要轮廓的周长信息
    # 多边形周长与源轮廓周长之比就是epsilon
    epsilon = 0.01 * cv2.arcLength(cnt,True)
    approx = cv2.approxPolyDP(cnt, epsilon, True)
    cv2.drawContours(img, [approx], -1, (255, 255, 0), 2)

    # 凸包
    hull = cv2.convexHull(cnt)
    cv2.drawContours(img, [hull], -1, (0, 0, 255), 2)

cv2.imshow("approx",img)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行

4.2 在新建幕布上绘制轮廓

当然在书(OpenCV 3 计算机视觉)第三章 3.10 凸轮廓与Douglas-Peucker算法 中,是将三个轮廓放在了黑色图像上。

实现代码如下:

import cv2
import numpy as np

img = cv2.imread('Mjolnir.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
# 生成黑色"幕布"
black = cv2.cvtColor(np.zeros((img.shape[1], img.shape[0]), dtype=np.uint8), cv2.COLOR_GRAY2BGR)

for cnt in contours:

    # ----源轮廓-------
    cv2.drawContours(black, [cnt], -1, (0, 255, 0), 2)

    # 近似多边形
    # epsilon 为近似度参数,该值需要轮廓的周长信息
    # 多边形周长与源轮廓周长之比就是epsilon
    epsilon = 0.01 * cv2.arcLength(cnt,True)
    approx = cv2.approxPolyDP(cnt, epsilon, True)
    cv2.drawContours(black, [approx], -1, (255, 255, 0), 2)

    # 凸包
    hull = cv2.convexHull(cnt)
    cv2.drawContours(black, [hull], -1, (0, 0, 255), 2)

cv2.imshow("approx",black)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行

参考:

OpenCV入门之寻找图像的凸包(convex hull)关于凸包,讲的不错。

Convex Hull在Python和C ++中使用OpenCV 讲解的非常详细以及每一步的实现语言

opencv学习(四十一)之寻找凸包convexHull() 虽然实现语言不同,但是讲解还挺详细的

Convex Hull 这个粉红色的,是不是萌妹版

边缘检测,框出物体的轮廓(使用opencv-python)

Python+OpenCV教程番外篇9:凸包及更多轮廓特征

结构分析和形状描述符 官方文档

opencv-python的中文教程 - OpenCV中的轮廓 较为系统性

Convex Hull在Python和C ++中使用OpenCV  较为系统性

代码图像素材

OpenCV 学习笔记03 凸包convexHull、道格拉斯-普克算法Douglas-Peucker algorithm、approxPloyDP 函数的更多相关文章

  1. OpenCV 学习笔记03 边界框、最小矩形区域和最小闭圆的轮廓

    本节代码使用的opencv-python 4.0.1,numpy 1.15.4 + mkl 使用图片为 Mjolnir_Round_Car_Magnet_300x300.jpg 代码如下: impor ...

  2. OpenCV 学习笔记03 findContours函数

    opencv-python   4.0.1 1 函数释义 词义:发现轮廓! 从二进制图像中查找轮廓(Finds contours in a binary image):轮廓是形状分析和物体检测和识别的 ...

  3. GIS矢量数据化简:一种改进的道格拉斯-普克算法以及C++实现

    GIS领域的同志都知道,传统的道格拉斯-普克算法都是递归实现.然而有时候递归的层次太深的话会出现栈溢出的情况.在此,介绍一种非递归的算法. 要将递归算法改为非递归算法,一般情况下分为两种场景.第一种是 ...

  4. 道格拉斯-普克算法(JavaScript实现)

    需求: 有时候当移动速度很慢,GPS定位的轨迹点就非常的多,这时候为了缩减数据量,需要将不突出的点去掉. 思路: (1) 在曲线首尾两点间虚连一条直线,求出其余各点到该直线的距离. (2)选其最大者与 ...

  5. OpenCV 学习笔记03 boundingRect、minAreaRect、minEnclosingCircle、boxPoints、int0、circle、rectangle函数的用法

    函数中的代码是部分代码,详细代码在最后 1 cv2.boundingRect 作用:矩形边框(boundingRect),用于计算图像一系列点的外部矩形边界. cv2.boundingRect(arr ...

  6. OpenCV 学习笔记 04 深度估计与分割——GrabCut算法与分水岭算法

    1 使用普通摄像头进行深度估计 1.1 深度估计原理 这里会用到几何学中的极几何(Epipolar Geometry),它属于立体视觉(stereo vision)几何学,立体视觉是计算机视觉的一个分 ...

  7. OpenCV 学习笔记03 直线和圆检测

    检测边缘和轮廓不仅重要,还经常用到,它们也是构成其他复杂操作的基础. 直线和形状检测与边缘和轮廓检测有密切的关系. 霍夫hough 变换是直线和形状检测背后的理论基础.霍夫变化是基于极坐标和向量开展的 ...

  8. OpenCV 学习笔记03 drawContours函数

    opencv-python   4.0.1 轮廓的绘制或填充. cv2.drawContours(image, contours, contourIdx, color[, thickness[, li ...

  9. OpenCV 学习笔记03 threshold函数

    opencv-python   4.0.1 简介:该函数是对数组中的每一个元素(each array element)应用固定级别阈值(Applies a fixed-level threshold) ...

随机推荐

  1. android学习四(Activity的生命周期)

    要学好活动(Activity).就必需要了解android中Activity的声明周期.灵活的使用生命周期.能够开发出更好的程序,在android中是使用任务来管理活动的,一个任务就是一组存放在栈里的 ...

  2. 微信、支付宝App支付-JPay0.0.2发布

    JPay 对微信App支付.支付宝App支付的二次封装,对外提供一个相对简单的接口以及支付结果的回调 GitHub:https://github.com/Javen205/JPay OsChina:h ...

  3. OpenGL ES 3.0(五)

    使用EGL(在iOS中是EAGL)创建屏幕渲染 加载顶点和片段着色器 创建程序对象,连接顶点和片段着色器,连接程序对象 设置视口 清除颜色缓冲区 绘制一个简单的图元(三角形) 显示缓冲区内容 1.创建 ...

  4. 具体解说Android的图片下载框架UniversialImageLoader之磁盘缓存(一)

    沉浸在Android的开发世界中有一些年头的猴子们,预计都可以深深的体会到Android中的图片下载.展示.缓存一直是心中抹不去的痛.鄙人亦是如此.Ok,闲话不说.为了督促自己的学习.以下就逐一的挖掘 ...

  5. jQuery开发技巧

    jQuery 事件 - submit() 方法 $("form").submit(function(e){}); 当提交表单时,会发生 submit 事件. 该事件只适用于表单元素 ...

  6. JavaWeb之tomcat安装、配置与使用(一)

    一.Tomcat下载与安装: 1.直接到官网下载Tomcat安装程序包:http://tomcat.apache.org/ 2.下载下来后是个压缩包,如:apache-tomcat-7.0.40.zi ...

  7. 第五周 Word注释与交叉引用

    第五周 Word注释与交叉引用 教学时间 2013-3-26 教学课时 2 教案序号 4 教学目标 1.掌握脚注.尾注.题注的概念和应用 2.掌握交叉引用的操作方法 教学过程: 复习提问 1.如何利用 ...

  8. hadoop mahout 算法和API说明

    org.apache.mahout.cf.taste.hadoop.item.RecommenderJob.main(args) --input 偏好数据路径,文本文件.格式 userid\t ite ...

  9. poj 1664 放苹果(递推)

    题目链接:http://poj.org/problem? id=1664 放苹果 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions ...

  10. node中__dirname、__filename、process.cwd()表示的路径

    直接上结论:__dirname 表示当前文件所在的目录的绝对路径__filename 表示当前文件的绝对路径module.filename ==== __filename 等价process.cwd( ...