OpenCV-Python(21):OPenCV查找及绘制轮廓

1.认识轮廓

1.1 目标

  • 理解什么是轮廓
  • 学习掌握找轮廓、绘制轮廓等
  • 学习使用cv2.findContours()、cv2.drawContours()函数的用法

1.2 什么是轮廓

        在OpenCV中,轮廓是图像中连续的边界线的曲线,具有相同的颜色或者灰度,用于表示物体的形状。轮廓在图像处理和计算机视觉中非常重要,常用于物体检测、形状分析、图像分割等任务。

提示:

  • 为了使轮廓更加准确,要使用二值化图像。所以,在寻找轮之前,要进行阈值化处理或者Canny边界检测。
  • 查找轮廓的函数会修改原始图像。如果你在找到轮廓之后想使用原始图像的话,你应该将原始图像存储到其他变量中。
  • 在OpenCV 中,查找廓就像在黑色背景中查找白色物体。你应该记住,要找的物体应该是白色而背景应该是黑色。

在OpenCV中,可以通过以下步骤找到图像中的轮廓:

  1. 对图像进行预处理,如灰度化、二值化等操作。
  2. 使用cv2.findContours()函数找到图像中的轮廓。该函数会返回一个包含轮廓信息的列表。
  3. 遍历轮廓列表,可以使用cv2.drawContours()函数将轮廓绘制到图像上。
  4. 对轮廓进行进一步的分析和操作,如计算轮廓的面积、周长,寻找轮廓的凸包等。

cv2.findContours()是一个用于查找图像中轮廓的函数。它的语法如下:

contours, hierarchy = cv2.findContours(image, mode, method[, contours[, hierarchy[, offset]]])

参数说明:

  • image:输入的二值化图像,通常为灰度图像或二值图像。
  • mode:轮廓检索模式,指定轮廓的层级结构。常用的取值有:
    • cv2.RETR_EXTERNAL:只检测最外层的轮廓。
    • cv2.RETR_LIST:检测所有的轮廓,不建立层级关系。
    • cv2.RETR_CCOMP:检测所有的轮廓,并将它们组织为两层的层级结构。
    • cv2.RETR_TREE:检测所有的轮廓,并完整地重建轮廓之间的层级关系。
  • method:轮廓近似方法。常用的取值有:
    • cv2.CHAIN_APPROX_NONE:保存所有的轮廓点。
    • cv2.CHAIN_APPROX_SIMPLE:压缩水平、垂直和对角线方向上的轮廓,仅保留终点。
  • contours:输出的轮廓列表,每个轮廓由一系列点组成。
  • hierarchy:可选输出的层级关系,用于表示轮廓之间的层级关系。
  • offset:可选的偏移量,用于调整轮廓的位置。

4.0以上的版本cv2.findContours()函数会返回两个值(OpenCV 3.0系列版本会返回3个值,多出的第一个值是图像),分别是轮廓列表和层级关系。轮廓列表是一个包含每个轮廓的Numpy数组,每个数组中的元素表示轮廓上的一个点,包含对边界点(x,y)的坐标。层级关系是一个包含每个轮廓的层级关系信息的Numpy数组,用于表示轮廓之间的层级关系,可用于进一步分析轮廓的形状和结构。以下是一个使用cv2.findContours()函数查找轮廓的示例代码:

import cv2# 读取图像
image = cv2.imread("image.jpg")# 灰度化
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 二值化
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)# 寻找轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 三个参数的返回
'''
_,contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
'''# 绘制轮廓
cv2.drawContours(image, contours, -1, (0, 255, 0), 3)# 显示图像
cv2.imshow("Contours", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

代码中,首先读取了一张图像,并对其进行了灰度化和二值化处理。然后使用cv2.findContours()函数找到图像中的轮廓,并将其绘制到原始图像上。最后显示图像并等待按键关闭窗口。

1.3 怎样绘制轮廓

    cv2.drawContours()是一个用于绘制轮廓的函数,它可以根据你提供的边界点绘制任何形状。它的语法如下:

cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]])

参数说明:

  • image:要绘制轮廓的图像。
  • contours:轮廓列表,即cv2.findContours()函数返回的轮廓列表。
  • contourIdx:要绘制的轮廓的索引,绘制独立轮廓时很有用,-1表示绘制所有轮廓。
  • color:绘制轮廓的颜色,可以是一个BGR元组或一个整数。
  • thickness:轮廓线的粗细,默认为1。
  • lineType:轮廓线的类型,默认为cv2.LINE_8,表示8连通线。
  • hierarchy:层级关系,即cv2.findContours()函数返回的层级关系。
  • maxLevel:绘制轮廓的最大层级,默认为0,表示只绘制当前层级的轮廓。
  • offset:可选的偏移量,用于调整轮廓的位置。

cv2.drawContours()函数用于在图像上绘制轮廓。可以通过设置contourIdx参数来指定要绘制的轮廓的索引,-1表示绘制所有轮廓。可以通过设置color参数来指定绘制轮廓的颜色。绘制的轮廓线的粗细可以通过thickness参数进行设置,默认为1。轮廓线的类型可以通过lineType参数进行设置,默认为cv2.LINE_8,表示画8连通线。

以下是一个使用cv2.drawContours()函数绘制轮廓的示例代码:

import cv2# 读取图像
image = cv2.imread("image.jpg")# 灰度化
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 二值化
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)# 寻找轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 绘制轮廓
cv2.drawContours(image, contours, -1, (0, 255, 0), 3)# 显示图像
cv2.imshow("Contours", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

在上述代码中,首先读取了一张图像,并对其进行了灰度化和二值化处理。然后使用cv2.findContours()函数找到图像中的轮廓,并使用cv2.drawContours()函数将轮廓绘制到原始图像上。最后显示图像并等待按键关闭窗口。

绘制独立的廓,如第四个轮廓:

img = cv2.drawContour(img, contours, -1, (0,255,0), 3)

但是大多数时候下面的方法更有用:

img = cv2.drawContours(img, contours, 3, (0,255,0), 3)

注意:最后这两种方法结果是一样的,但是后面的知识会告诉你最后一种方法更有用。

1.4 轮廓的近似方法

        上面查找轮廓的时候,提到了是函数cv2.findCountours() 有一个轮廓的近似方法参数,那么它到底代表什么意思呢?
        上面我们已经提到轮廓是一个形状具有相同灰度值的边界。它会存储形状边界上所有的(x,y)坐标。但是,需要将所有的这些边界点都存储吗?这就是这个参数要告诉函数cv2.findContours 的。
        这个参数如果被设置为cv2.CHAIN_APPROX_NONE,所有的边界点都会被存储。但是我们真的需要这么么多点吗?例如,当我们找的边界是一条直线时。你用需要把直线上所有的点来表示直线吗?不是的,我们只需要这条直线的两个端点而已。这就是cv2.CHAIN_APPROX_SIMPLE 要做的。它会将将廓上的冗余点去掉,压缩轮廓,从而节省内存开支。
        我们用下图中的矩形来演示这个技术。在轮廓列表中的每一个坐标上画一个蓝色圆圈。第一个图显示使用cv2.CHAIN_APPROX_NONE 的效果,一共734 个点。第二个图是使用cv2.CHAIN_APPROX_SIMPLE 的结果,只有4 个点。看到他的威力了吧:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2660722.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

linux用户态与内核态通过字符设备交互

linux用户态与内核态通过字符设备交互 简述 Linux设备分为三类,字符设备、块设备、网络接口设备。字符设备只能一个字节一个字节读取,常见外设基本都是字符设备。块设备一般用于存储设备,一块一块的读取。网络设备,Linux将对网络…

web自动化(4)——POM设计重构

1. 什么是POM Page Object Model 是ui自动化测试中常见的封装方式。 原理:将页面封装为PO对象,然后通过面向对象的方式实现UI自动化 2. 封装原则 PO无需包含全部UI元素PO应当验证元素PO不应该包含断言PO不应该暴露元素 3. 怎么进行POM封装 面向对象…

Centos7:Jenkins+gitlab+node项目启动(2)

Centos7:Jenkinsgitlabnode项目启动(1) Centos7:Jenkinsgitlabnode项目启动(1)-CSDN博客 Centos7:Jenkinsgitlabnode项目启动(2) Centos7:Jenkinsgitlabnode项目启动(2)-CSDN博客 Centos7:Jenkinsgitlabnode项目启…

自动化网络故障修复管理

什么是故障管理 故障管理是网络管理的组成部分,涉及检测、隔离和解决问题。如果实施得当,网络故障管理可以使连接、应用程序和服务保持在最佳水平,提供容错能力并最大限度地减少停机时间。专门为此目的设计的平台或工具称为故障管理系统。 …

目标检测损失函数:IoU、GIoU、DIoU、CIoU、EIoU、alpha IoU、SIoU、WIoU原理及Pytorch实现

前言 损失函数是用来评价模型的预测值和真实值一致程度,损失函数越小,通常模型的性能越好。不同的模型用的损失函数一般也不一样。损失函数主要是用在模型的训练阶段,如果我们想让预测值无限接近于真实值,就需要将损失值降到最低…

vue3(十)-基础入门之Swiper轮播与自定义指令

一、Swiper html : 注意&#xff1a; class“swiper-wrapper”、class“swiper-slide” 等类名不能写错 <body><!-- 导入下载好的包或通过 CDN 导入vue、swiper.js、swiper.css --><!-- <script src"https://unpkg.com/vue3/dist/vue.global.js"&…

RK3568平台开发系列讲解(Linux系统篇)PWM系统编程

🚀返回专栏总目录 文章目录 一、什么是PWM二、PWM相关节点三、PWM应用编程沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍 PWM 的系统编程。 一、什么是PWM PWM,即脉冲宽度调制(Pulse Width Modulation)

【PowerMockito:编写单元测试过程中采用when打桩失效的问题】

问题描述 正如上图所示&#xff0c;采用when打桩了&#xff0c;但是&#xff0c;实际执行的时候还是返回null。 解决方案 打桩时直接用any() 但是这样可能出现一个mybatisplus的异常&#xff0c;所以在测试类中需要加入以下代码片段&#xff1a; Beforepublic void setUp() …

Awesome Chrome Form UI - 框架设计与基础实现

Money is not evil by itself. Its just paper with perceived value to obtain other things we value in other ways. If not money what is evil you may ask? Evil is the unquenchable, obsessive and moral bending desire for more. Evil is the bottomless,soulless …

解决VSCode中C/C++ Project Generator插件创建的项目只能运行单个程序的问题

初六&#xff0c;履霜&#xff0c;坚冰至。 释意&#xff1a;初六&#xff0c;当你踩着微霜之时&#xff0c;严寒与坚冰也就即将到来。 目录 一、前言 二、问题描述 三、解决方案 1、思路总结 2、思考过程 3、解决方案&#xff08;直接用&#xff0c;报错找我(&#xff8…

超声功率放大器怎么用

超声功率放大器是一种用于放大超声信号的设备&#xff0c;广泛应用于医疗领域、工业领域和科学研究中。它能够将超声信号的能量增加到足够大的水平&#xff0c;以便进行高强度超声疗法、材料加工和实验研究等应用。下面将详细介绍超声功率放大器的使用方法和其工作原理。 首先&…

数据结构——红黑树 and B-树

红黑树 根据平衡条件第4、5两点 最短路径&#xff0c;都是黑色 最长路径&#xff0c;红黑相间 最长是最短的两倍 B-树

《深入理解Java虚拟机(第三版)》读书笔记:Java内存区域与内存溢出异常、垃圾收集器与内存分配策略

下文是阅读《深入理解Java虚拟机&#xff08;第3版&#xff09;》这本书的读书笔记&#xff0c;如有侵权&#xff0c;请联系删除。 文章目录 第2章 Java内存区域与内存溢出异常2.2 运行时数据区域2.3 HotSpot虚拟机对象探秘 第3章 垃圾收集器与内存分配策略3.2 对象已死&…

安装Node修改Node镜像地址搭建Vue脚手架创建Vue项目

1、安装VSCode和Node 下载VSCode Visual Studio Code - Code Editing. Redefined 下载Node Node.js (nodejs.org) 检验是否安装成功&#xff0c;WinR,输入cmd命令&#xff0c;使用node -v可以查看到其版本号 2、修改镜像地址 安装好node之后&#xff0c;开始修改镜像地址 …

【 YOLOv5】目标检测 YOLOv5 开源代码项目调试与讲解实战(4)-自制数据集及训练(使用makesense标注数据集)

如何制作和训练自己的数据集 看yolov5官网创建数据集1.搜索需要的图片2.创建标签标注数据集地址&#xff1a;放入图片后选择目标检测创建文档&#xff0c;每个标签写在单独的一行上传结果此处可以编辑类别把车框选选择类别即可导出数据 3.新建一个目录放数据写yaml文件 4. 测试…

重装系统以后无法git跟踪

总结&#xff1a;权限问题 故障定位 解决方案&#xff1a; 复制一份新的文件夹。&#xff08;新建的文件创建和写入权限都变了&#xff09; 修改文件为新的用户 执行提示的命令

docker +gitee+ jenkins +maven项目 (一)

jenkins环境和插件配置 文章目录 jenkins环境和插件配置前言一、环境版本二、jenkins插件三、环境安装总结 前言 现在基本都是走自动化运维&#xff0c;想到用docker 来部署jenkins &#xff0c;然后jenkins来部署java代码&#xff0c;做到了开箱即用&#xff0c;自动发布代码…

磁盘相关知识

一、硬盘数据结构 1.扇区&#xff1a; 盘片被分为多个扇形区域&#xff0c;每个扇区存放512字节的数据&#xff08;扇区越多容量越大&#xff09; 存放数据的最小单位 512字节 &#xff08;硬盘最小的存储单位是扇区&#xff0c;512 个字节&#xff0c;八个扇区组成一块&…

H5向微信小程序发送信息(小程序web-view打开H5)

引入weixin-js-sdk npm i weixin-js-sdk 页面引入 // 引入wxjsimport wx from "weixin-js-sdk"; 点击触发方法 methods: {goweap(id){console.log(wx);// H5传递数据 &#xff08;navigateBack&#xff09;wx.miniProgram.navigateBack({delta: 1});wx.min…

Android APK未签名提醒

最近新建了一个项目&#xff0c;在build.gradle中配置好了签名&#xff0c;在执行打包的时候打出的包显示已签名&#xff0c;但是在上传市场的时候提示未签名。于是排查了好久&#xff0c;发现在build.gradle中配置的minsdk 24&#xff0c;会导致不使用V1签名&#xff0c;于是我…