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

OpenCV-36 多边形逼近与凸包

目录

一、多边形的逼近

二、凸包


一、多边形的逼近

findContours后的轮廓信息countours可能过于复杂不平滑,可以用approxPolyDP函数对该多边形曲线做适当近似,这就是轮廓的多边形逼近。

apporxPolyDP就是以多边形去逼近轮廓,采用的是Douglas-Peucker算法(方法名中的DP)

DP算法原理比较简单,核心就是不断去找多边形最远的点加入形成新的多边形,直到最短距离小于指定的精度(阈值)

approxPolyDP(curve, epsilon, closed[, approxCurvel])

  • curve 要逼近的轮廓
  • epsilon 即DP算法使用的阈值
  • closed 轮廓是否闭合

阈值越大,逼近效果越粗糙;阈值越小,逼近效果越好。

得到的approx本质是一个数组ndarray类型,因此画轮廓的时候需要加上[]变成列表类型。

示例代码如下:

import cv2
import numpy as np
# 导入图片
hand = cv2.imread("hand.png")
# 变为单通道黑白图片
gray = cv2.cvtColor(hand, cv2.COLOR_BGR2GRAY)
# 二值化操作
ret, new_img = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# 查找轮廓
contours, hierarchy = cv2.findContours(new_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 复制一份原图
hand_copy = hand.copy()
# 直接在img_copy上面操作
cv2.drawContours(hand_copy, contours, -1, (0, 0, 255), 2)
# 使用多边形逼近,近似模拟手的轮廓
approx = cv2.approxPolyDP(contours[2], 20, closed=True)
# approx本质上是一个轮廓数据,是一个ndarray类型
print(approx)
print(type(approx))
# 二contours是一个元组/列表类型
# 画出近似逼近的轮廓
cv2.drawContours(hand_copy, [approx], -1, (0, 255, 0), 2)
cv2.imshow("img", np.hstack((hand, hand_copy)))
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果如下:

二、凸包

逼近多边形是轮廓的高度近似,但是有时候,我们希望使用一个多边形的凸包来简化它。 凸包和逼近多边形很像,只不过它是物体最外层的凸多边形。凸包指的是完全包含原有轮廓,并且仅由轮廓上的点所构成的多边形。凸包的每一处都凸的,即在凸包内连接任意两点的直线都在凸包的内部。在凸包内,任意连续三个点的内角小于180°。

convexHull(points[,hull [,clockwise[, returnpoints]]]])

  • points 即轮廓
  • colckwise 顺时针绘制

示例代码如下:

import cv2
hand = cv2.imread("hand.png")
# 二值化操作
gray = cv2.cvtColor(hand, cv2.COLOR_BGR2GRAY)
# 二值化操作
thresh, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# 查找轮廓
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
cv2.drawContours(hand, contours, 0, (0, 0, 255), 2)
# 多边形逼近
approx = cv2.approxPolyDP(contours[2], 20, True)
# 画出多边形逼近的轮廓
cv2.drawContours(hand, [approx], 0, (0, 0, 255), 2)
# 计算凸包
hull = cv2.convexHull(contours[2])
# 画出凸包
cv2.drawContours(hand, [hull], 0, (255, 0, 0), 2)
cv2.imshow("hand", hand)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果如下:

相关文章:

  • 【C++】C++11上
  • OCP的operator——(4)用户任务:使用Operator创建etcd集群
  • ubuntu屏幕小的解决办法
  • ES实战--集群扩展
  • 专业140+总分420+东北大学841通信专业基础考研经验东大电子信息与通信工程,真题,大纲,参考书。
  • 【Spring面试题】
  • 跟着pink老师前端入门教程-day26
  • Acwing语法基础课 8.STL(笔记)
  • 【sgCreateTableColumn】自定义小工具:敏捷开发→自动化生成表格列html代码(表格列生成工具)[基于el-table-column]
  • Flume(二)【Flume 进阶使用】
  • .NET开源的一个小而快并且功能强大的 Windows 动态桌面软件 - DreamScene2
  • 【MySQL】Java的JDBC编程
  • AI:125-基于深度学习的航拍图像中地物变化检测
  • 汽车零部件制造业MES系统解决方案
  • 什么是“感知机”?
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • Angular6错误 Service: No provider for Renderer2
  • CSS实用技巧干货
  • Docker容器管理
  • HashMap ConcurrentHashMap
  • Java 网络编程(2):UDP 的使用
  • JavaScript 基本功--面试宝典
  • JavaWeb(学习笔记二)
  • PAT A1120
  • React-Native - 收藏集 - 掘金
  • Unix命令
  • 分布式熔断降级平台aegis
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 前嗅ForeSpider采集配置界面介绍
  • Linux权限管理(week1_day5)--技术流ken
  • 翻译 | The Principles of OOD 面向对象设计原则
  • ​​​​​​​ubuntu16.04 fastreid训练过程
  • ​iOS实时查看App运行日志
  • ​软考-高级-信息系统项目管理师教程 第四版【第23章-组织通用管理-思维导图】​
  • !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结
  • # Java NIO(一)FileChannel
  • # 达梦数据库知识点
  • (3)nginx 配置(nginx.conf)
  • (c语言)strcpy函数用法
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (二)hibernate配置管理
  • (论文阅读40-45)图像描述1
  • (三)c52学习之旅-点亮LED灯
  • (十五)使用Nexus创建Maven私服
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • (转)C#调用WebService 基础
  • (自用)learnOpenGL学习总结-高级OpenGL-抗锯齿
  • .net 4.0 A potentially dangerous Request.Form value was detected from the client 的解决方案
  • .NET Standard / dotnet-core / net472 —— .NET 究竟应该如何大小写?
  • .Net 垃圾回收机制原理(二)
  • .NET框架设计—常被忽视的C#设计技巧
  • .NET业务框架的构建