opencv学习:图像轮廓识别及代码实现

news2025/1/15 19:41:50

图像轮廓

1.获取图像轮廓

cv2.findContours() 函数是 OpenCV 库中用于检测图像中轮廓的函数。它可以检测到图像中所有连通区域的边界,并返回这些轮廓的列表。从 OpenCV 3.4 版本开始,这个函数的返回值和参数有所变化,以下是详细的参数说明:

方法:

contours, hierarchy = cv2.findContours( img, mode, method )

参数说明

  1. img:输入图像,必须是二值图像。图像中的轮廓将基于此图像进行检测。

  2. mode:轮廓检索模式,用于指定要检索哪些轮廓。可用的模式有:

    • cv2.RETR_EXTERNAL:只检索最外层的轮廓。
    • cv2.RETR_LIST:检索所有轮廓,但不建立任何父子关系。
    • cv2.RETR_CCOMP:检索所有轮廓,并将它们组织成两级层次结构。
    • cv2.RETR_TREE:检索所有轮廓,并重建完整的层次结构。
  3. method:轮廓近似方法,用于指定如何存储轮廓点。可用的方法有:

    • cv2.CHAIN_APPROX_NONE:存储所有轮廓点。
    • cv2.CHAIN_APPROX_SIMPLE:只存储轮廓的拐点,这可以减少轮廓点的数量。

返回值

  • contours:这是一个 Python 列表,其中包含了检测到的轮廓。每个轮廓都是一个形状为 (n, 1, 2) 的 numpy 数组,其中 n 是轮廓点的数量。
  • hierarchy:这是一个 numpy 数组,包含了轮廓的层次信息。层次信息可以用来了解轮廓之间的父子关系。

2.绘制图像轮廓

        在OpenCV中,cv2.drawContours()函数用于在图像上绘制轮廓。这个函数非常强大,因为它允许你指定轮廓的颜色、线条粗细以及其他参数。下面是这个函数的详细参数说明:

方法:

cv2.drawContours(img, contours, contourIdx, color, thickness, lineType=None, hierarchy=None)

参数说明

  1. img:目标图像,即你要在其上绘制轮廓的图像。这个图像应该是一个可以修改的图像数组。

  2. contours:这是一个轮廓列表。轮廓可以是OpenCV中找到的任何轮廓,通常是一个形状为(N, 1, 2)的numpy数组,其中N是轮廓中的点数。

  3. contourIdx:指定要绘制的轮廓的索引。如果传递的是-1,则绘制所有轮廓。

  4. color:轮廓线的颜色。这应该是一个具有三个元素的元组,表示BGR颜色(例如,红色为(0, 0, 255))。

  5. thickness:线条的粗细。如果设置为正数,则线条的粗细为指定的像素数;如果设置为cv2.FILLED-1,则轮廓将被填充。

  6. lineType(可选):线条的类型。默认是cv2.LINE_8,表示8连通性线。其他选项包括cv2.LINE_4(4连通性线)和cv2.LINE_AA(抗锯齿线)。

  7. hierarchy(可选):轮廓的层次结构。这是一个与contours数组相对应的数组,其中包含每个轮廓的层次信息。如果提供,可以用来绘制轮廓的父子关系。

实验代码

1.获取图像

import cv2

# 读取图像
phone = cv2.imread('cat.png')  # 读取名为'cat.png'的图像

# 将图像转换为灰度图像
phone_gray = cv2.cvtColor(phone, cv2.COLOR_BGR2GRAY)  # 将彩色图像转换为灰度图

# 应用阈值操作以创建二值图像
ret, phone_binary = cv2.threshold(phone_gray, 120, 255, cv2.THRESH_BINARY)  # 使用阈值120将灰度图转换为二值图
# cv2.imshow('1',phone_binary)  # 显示二值图像

2.查找轮廓

# 查找轮廓
_, contours, hierarchy = cv2.findContours(phone_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)  # 在二值图中查找轮廓
# 打印轮廓数量和层次结构信息
print(hierarchy)  # 打印轮廓的层次结构信息
print(len(contours))  # 打印轮廓的数量

3.复制图像用于绘制轮廓

# 复制图像用于绘制轮廓
image_copy = phone.copy()
image_copy = cv2.drawContours(image=image_copy, contours=contours, contourIdx=-1, color=(0, 255, 0), thickness=3)  # 在图像上绘制所有轮廓
# cv2.imshow('contours',image_copy)  # 显示绘制了轮廓的图像
cv2.waitKey(0)  # 等待按键

4.计算轮廓面积和周长

# 计算第一个和第二个轮廓的面积
area_0 = cv2.contourArea(contours[0])
area_1 = cv2.contourArea(contours[1])
print(area_0, area_1)  # 打印面积

# 计算第一个轮廓的周长
length = cv2.arcLength(contours[0], closed=True)
print(length)  # 打印周长

5.查找轮廓

# 筛选面积大于10000的轮廓
a_list = []
for i in range(len(contours)):
    if cv2.contourArea(contours[i]) > 10000:
        a_list.append(contours[i])

# 找到第七个轮廓的最小包围圆
cnt = contours[6]
(x, y), r = cv2.minEnclosingCircle(cnt)
phone_circle = cv2.circle(phone, (int(x), int(y)), int(r), (0, 255, 0), 2)  # 在图像上绘制最小包围圆
cv2.imshow('phone_circle', phone_circle)  # 显示绘制了最小包围圆的图像

# 找到第七个轮廓的最小包围矩形
x, y, w, h = cv2.boundingRect((cnt))
phone_rectangle = cv2.rectangle(phone, (x, y), (x + w, y + h), (0, 255, 0), 2)  # 在图像上绘制最小包围矩形
cv2.imshow('phone_rectangle', phone_rectangle)  # 显示绘制了最小包围矩形的图像

6.轮廓近似

# 重新查找轮廓
image, contours, hierarchy = cv2.findContours(phone_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

# 对最后一个轮廓进行轮廓近似
epsilon = 0.001 * cv2.arcLength(contours[-1], True)
approx = cv2.approxPolyDP(contours[-1], epsilon, True)
phone_new = phone.copy()
image_contours = cv2.drawContours(phone_new, [approx], contourIdx=-1, color=(0, 255, 0), thickness=3)  # 在图像上绘制近似轮廓
cv2.imshow('image_contours', image_contours)  # 显示绘制了近似轮廓的图像

cv2.waitKey(0)

实验分析

  • 通过阈值操作,图像中的轮廓被清晰地分离出来,这为后续的轮廓处理提供了便利。
  • 轮廓的面积和周长的计算对于理解图像中对象的大小和形状特征非常重要。
  • 最小包围圆和最小包围矩形的绘制有助于识别和定位图像中的主要对象。
  • 轮廓近似可以简化轮廓的形状,减少计算复杂度,同时保留轮廓的主要特征。

结论

        本实验通过使用OpenCV库成功地完成了图像处理的各个步骤,包括图像的读取、转换、阈值操作、轮廓查找、面积和周长计算、最小包围圆和矩形的绘制以及轮廓近似。这些技术在图像识别、对象检测和图像分析等领域有着广泛的应用。

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

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

相关文章

如何根据屋顶的面积和形状设计光伏板的排布?

首先我们得了解项目的具体的情况数据: 测量屋顶尺寸:准确测量屋顶的长、宽等数据,了解其面积大小 分析屋顶形状:观察屋顶是平顶、坡顶还是其他形状,这会影响排布方式。 支架的排布:要保证发电量的同时&a…

序列标注任务

序列标注任务 1.序列标注任务2.序列标注--中文分词2.1数据标注方法一2.2数据标注方法二 3.序列标注--NER3.1序列标注--CRF3.2篱笆墙解码3.3beam search3.4维特比解码3.5效率对比3.6评价指标 4.基于规则-NER4.1序列标注--文本加标点4.2序列标注--句子级别分类4.3实体抽取问题4.4…

田纳西州橡树岭全球最快的超级计算机名为Frontier

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

【VuePress 个人博客搭建】

个人博客搭建免服务器 一、安装 VuePress1、创建文件夹并进入该目录2、初始化项目3、安装VuePress4、在 package.json 中修改 scripts5、创建目录和配置文件6、创建第一篇文档Hello VuePress7、 运行项目二、部署1、新建github 仓库2、在 config.js 添加 base 路径配置:3、创建…

使用 Parallel 类进行多线程编码(下)

2.Parallel.ForEach() 的使用 从 ForEach() 这个名字可以看出该方法是用来遍历泛型集合的,新建一个 ASP.NET Core Web应用的项目,如下: 在 Index.cshtml.cs 文件中增加一个 UserInfo.cs 的类,代码如下: public class U…

【第26章】Spring Cloud之Sentinel适配API Gateway

文章目录 前言一、准备1. 引入库2. 注册过滤器3. 添加配置4. 效果展示 二、基于网关的流控1. 新增流控规则2. 测试准备3. 测试结果 总结 前言 Sentinel从1.6.0 版本开始,Sentinel 提供了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流&a…

基于IndexDB+md-editor-v3实现的简单的文章书写小系统

基于IndexDBmd-editor-v3实现的简单的文章书写小系统 文章说明核心代码效果展示源码下载 文章说明 采用vue3 IndexDB 实现的个人仓库系统,采用markdown书写文章,并将文章信息存储在IndexDB数据库中,通过JavaScript原生自带的分词API进行文章…

盘点10款顶级加密软件,让企业数据安全得到保障!

随着数字化进程的加快,企业数据的安全性面临着越来越多的威胁。无论是内部的数据泄露还是外部的网络攻击,企业必须采用强大的加密软件来确保敏感信息的安全。2024年,企业数据安全需求日益增长,各类加密软件应运而生,提…

收银系统源码-收银台(exe、apk安装包)自由灵活操作简单!

收银系统现在已经成为门店经营必备工具,尤其是连锁多门店。一套好的收银系统可以帮助门店管理门店、管理商品、管理会员等,可以更好的经营决策。线下收银端更是门店每天高频使用的。但线下收银端需要具备哪些亮点才能更加高效呢? 1.收银端支…

CPP/C语言中的位运算

背景: leetcode 汉明距离问题看题解时,遇见了这个问题这里简单总结一下。 实例: 异或运算符 ^ 会将左右两边的数据转化为二进制形式,按位与 4\^1100\^0011015或运算 | 同样将左右两边数据转化为二进制形式,按位或 4|1100|0011015与运算…

数据结构之红黑树的 “奥秘“

目录: 一.红黑树概念 二. 红黑树的性质 三.红黑树的实现 四.红黑树验证 五.AVL树和红黑树的比较 一.红黑树概念 1.红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何 一条从根…

03 Flask-添加配置信息

回顾之前学习的内容 02 Flask-快速上手 Flask 中最简单的web应用组成 1. 导入核心库 Flask from flask import Flask2. 实例化 web应用 注意:不要漏了 app Flask(__name__) 中的 __name__ 表示:是从当前的py文件实例化 app Flask(__name__)3. 创…

内网隧道:端口转发

目录 LCX端口转发 场景一 场景二 SSH的端口转发 一、本地转发(正向访问A): 二、远程转发(反向访问A) 三.NETSH端口转发 端口转发和端口映射 端口转发,有时被称为做隧道,是安全壳( SSH)为网络安全通信使用的一种方…

视频监控接入平台web客户端有时无法登录,有时打开实时视频出现黑屏的问题解决

目录 一、背景说明 二、解决过程 1、问题产生 2、命令介绍 ①基本用法 ②常用选项 ③示例 3、问题解决 三、最终结果 一、背景说明 在本地登录视频监控平台的服务器进行测试时,发现客户端登录不上。 检查服务器的服务和数据库,运行状况正常&#xff0c…

45个图源二维码分享及使用方法

我们曾在《40个图源二维码分享及使用方法》一文中,为你分享了40个图源二维码。 现在在此基础之上新增5个图源二维码,共分享45个。 如果你需要这些图源,请在文末查看领取方式。 45个图源 打开下面的网址进入水经微图(简称“微图…

Swift 创建扩展(Extension)

类别(Category) 和 扩展(Extension) 的 用法很多. 常用的 扩展(Extension) 有分离代码和封装模块的功能,例如登陆页面有注册功能,有登陆功能,有找回密码功能,都写在一个页面就太冗余了,可以考虑使用 扩展(Extension) 登陆页面的方法来分离代码 本文介绍Swift 如何创建扩展(Ex…

maven项目下使用Jacoco测试覆盖率

【本文前提是了解maven项目及其Pom.xml机制,不熟悉可以看该博客的0.Pre部分Auto-Unit-Test-Case-Generator -- java项目自动测试生成-CSDN博客】 JaCoCo(Java Code Coverage)是一个开源的代码覆盖率工具,专门用于测量 Java 应用程…

Web测试中如何简单定位Bug

定位bug之前要确定自己对用例的理解是否有问题。(在工作中,很多测试结果错误都是因为自己对用例的理解没有到位,以致于操作错误导致结果不符合预期) 一般来说bug分为前端bug和后端bug,前端bug为请求数据错误,后端bug为…

web基础之信息泄露

1、目录遍历漏洞 (1)原理:本质是没有过滤用户输入的 ../ 相关的目录跳转符,使得攻击者通过目录跳转符来遍历服务器中的任意文件。 (2)题解: eg:根据提示遍历网页目录信息,会在某一个…

vscode---snippets配置全局代码片段,快捷开发!

代码片段的作用:在开发一个项目时,经常会遇到好多同一个代码逻辑,可配置固顶逻辑的代码块,避免重复敲同一代码; 举例:比如跳转登录,需要调用app的客户端方法,api调用跳转&#xff1…