CV14 轮廓检测:入门

在线体验各类最新模型,更有模型 免费Token 额度领取!
立即体验
简介: 为什么?因为cv2.findContours()函数只能读黑白图,所以需要调用cv2.threshold()函数,而 阈值函数只能读灰度图

1.前言


轮廓检测是计算机检测图像和视频主体轮廓的重要步骤,常用于人脸检测和物体追踪等方向


本节我们将学习:边界、最小矩形及最小外接圆轮廓检测、凸轮廓Douglas-Peucker算法


2.边界、最小矩形及最小外接圆


在Opencv中确定主体的边框、最小外接矩形和圆非常简单


我们只需要使用cv2.findContours()函数即可完成


2.1程序流程


  • 首先,从文件中读取一幅图像,并转换成灰度图
  • 对灰度图像阈值化,使之转换为黑白图


为什么?因为cv2.findContours()函数只能读黑白图,所以需要调用cv2.threshold()函数,而 阈值函数只能读灰度图


  • 针对每一个轮廓寻找并画出边框,最小外接矩形和最小外接圆
  • 最后,绘制轮廓并在窗口中显示


代码如下:


import cv2
import numpy as np
img = cv2.imread('hammer.jpg',cv2.IMREAD_UNCHANGED)
img = cv2.pyrDown(img)
img2 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(img2,127, 255, cv2.THRESH_BINARY)
contours,hier = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
    # 画出边框
    x,y,w,h = cv2.boundingRect(c)
    cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
    # 找到最小外接矩形
    rect = cv2.minAreaRect(c)
    # 计算最小外接矩形的坐标
    box = cv2.boxPoints(rect)
    # 将坐标归一化为整数
    box = np.int0(box)
    # 画图
    cv2.drawContours(img,[box],0,(0,0,255),3)
    # 计算最小外接圆的半径和圆心
    (x,y),radius = cv2.minEnclosingCircle(c)
    # 转化为整数
    center = (int(x),int(y))
    radius = int(radius)
    # 画圆
    cv2.circle(img,center,radius,(255,0,255),5)
# 画轮廓
cv2.drawContours(img,contours,-1,(255,0,0),3)
cv2.imshow("contour",img)
cv2.waitKey(0)
cv2.destroyAllWindows()


注意:轮廓检测是在黑白图像上进行的,因此该阶段颜色信息已经丢失了。但我们是在原始彩色图像上绘制的,所以显示的是彩色结果


b9886d28a80a2266d752b9657a14a3db.png


2.2cv2.findContours()函数


cv2.findContours()函数


功能:查找检测物体的轮廓


输入参数:


1.黑白图(thresh),不是灰度图

2.指定函数返回的层次结构树类型

3.轮廓的近似办法


返回值:


1.轮廓本身

2.每条轮廓对应的属性


2.3cv2.drawContours()函数


cv2drawContours()函数


功能:根据cv2.findContours()返回的contours,绘制轮廓


输入参数:


1.输入图像(img)

2.轮廓(contours)

3.绘制轮廓的范围(-1是绘制所有的轮廓线;否则,绘制数组索引的轮廓线)

4.颜色(B,G,R)

5.线宽


2.4bug的发现与解决


在写代码的过程中,发现一个小bug


我将源图片转成黑白图并在这张图上绘制轮廓(而不是在彩色图片上绘制)


如下图,第79行cv2.circle(img,center,radius,(255,0,255),5),假设B=0,G、R>0,那么无法绘制圆形轮廓


然而,若B>0时,则会出现想要的轮廓


为什么?


# 画圆,输入参数依次为:1.图片,2.圆心,3.半径,4.颜色,5.线宽(-1表示填充整个圆形)
cv2.circle(img,(300,300),50,(0,0,255),-1)


在cv2.circle()函数中,第4个参数,若img是彩色图,那么可以用(0,0,255)表示颜色,若img是灰度图,那么只能由一个数(0~255),表示绘制线的亮度


所以,当我在灰度图中,放了一个(0,0,255)/(0,255,0),由于灰度图只读第一个参数(这里读到的是第一个参数—— 0),所以不会绘制任何轮廓


如果我放了(255,0,0),第一个参数不是0,那么就可以绘制出轮廓


3.凸轮廓和Douglas-Peucker算法


处理轮廓时,会遇到各种奇形怪状的图形,这时我们可用下面三条函数绘制轮廓


3.1相关程序


import cv2
import numpy as np
img = cv2.imread('hammer.jpg', cv2.IMREAD_UNCHANGED)
img = cv2.pyrDown(img)
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(img2, 127, 255, cv2.THRESH_BINARY)
contours, hier = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (255, 0, 0), 3)
for c in contours:
   epsilon = 0.01*cv2.arcLength(c,True)
   approx = cv2.approxPolyDP(c,epsilon,True)
   # 绘制凸形
   hull = cv2.convexHull(c)
   cv2.drawContours(img,[c],-1,(0,255,0),2)
   cv2.drawContours(img,[approx],-1,(255,0,255),2)
   cv2.drawContours(img,[hull],-1,(0,0,255),2)
cv2.imshow("contour", img)
cv2.waitKey(0)
cv2.destroyAllWindows()


先看效果


9f2bd7c95adef66f7317d4d4dd77ed48.png


3.2cv2.approxPolyDP()函数


cv2.approxPolyDP()函数


功能:描绘近似多边形轮廓


输入参数:


1.轮廓

2.原始轮廓和近似多边形之间的最大误差δ值

3.布尔标志,如果是True,表示多边形是闭合的


δ值:δ是近似多边形周长和原始轮廓线周长之差的最大值,δ值越低,近似值越接近原始轮廓


一般我们可以用轮廓的周长作为参考值:


δ = epsilon =0.01*cv2.arcLength(c,True)


epsilon = 0.01*cv2.arcLength(c,True)
approx = cv2.approxPolyDP(c,epsilon,True)


此时,δ 是原弧度的1%


4.结语


本来还想讲一下霍夫变换的,无奈本人才疏学浅,天性愚钝🤔而且霍夫变换的理论部分又晦涩难懂,便留到下一节再讲吧


讲完霍夫变换,入门篇也差不多学完了,接下来打算实战一下,把15篇博客统一整理一下。毕竟蓦然回首当初写的文章,不能说拉跨吧,只能说完全看不下去😅😅😅


或许可以整理成一本书?让我们看看接下来会发生什么哈哈哈哈哈哈🤣🤣🤣

相关文章
|
4月前
|
人工智能 机器人 定位技术
不会写代码也能懂:OpenClaw四层架构图解
本文用四张示意图,通俗拆解OpenClaw四大核心层:交互层(多端消息统一翻译)、网关层(路由/排队/调度中枢)、智能体层(会话、上下文、执行与记忆)、执行层(本地/远端节点+插件化技能)。帮你快速定位问题、理解消息全流程,零代码也能心中有图。
|
8月前
|
存储 安全 API
微服务安全之 OAuth2 协议深度解析:从原理到实战落地
本文深入解析OAuth2协议在微服务安全中的应用,涵盖核心概念、四种授权模式(授权码、简化、密码、客户端凭证)、令牌机制(JWT结构、存储管理)、资源服务器实现及安全最佳实践,结合Spring Security实战代码,助力开发者构建安全可靠的系统。
1209 5
|
10月前
|
运维 监控 Java
Linux常用命令行大全:14个核心指令详解+实战案例
在服务器管理与开发运维领域,Linux 指令是构建技术能力体系的基石。无论是日常的系统监控、文件操作,还是复杂的服务部署与故障排查,熟练掌握指令的使用逻辑都是提升工作效率的核心前提。然而,对于初学者而言,Linux 指令体系往往呈现出“参数繁多易混淆”“组合使用门槛高”“实际场景适配难”等痛点——例如 ls 命令的 -l 与 -a 参数如何搭配查看隐藏文件详情,grep 与管道符结合时如何精准过滤日志内容,这些问题常常成为技术进阶的阻碍。
|
设计模式 API 数据处理
C# 一分钟浅谈:GraphQL 客户端调用
本文介绍了如何在C#中使用`GraphQL.Client`库调用GraphQL API,涵盖基本查询、变量使用、批量请求等内容,并详细说明了常见问题及其解决方法,帮助开发者高效利用GraphQL的强大功能。
415 57
|
安全 Linux 数据安全/隐私保护
linux root登陆,密码正确但,错误提示su: Authentication failure
通过系统化的排查和解决方案,可以有效应对 `su: Authentication failure` 问题,确保系统安全和用户权限的正确管理。
8827 36
|
安全 Java API
什么是用于 REST API 的 Bearer Token以及如何通过代码和工具进行调试
Bearer Token 是一种基于 OAuth 2.0 的身份验证机制,广泛应用于 REST API 的授权访问中。它通过在 HTTP 请求头中传递令牌,确保用户凭据安全传输并验证。本文深入解析了 Bearer Token 的概念、实现步骤及调试方法,包括其无状态特性、灵活性与安全性优势。同时,提供了 Java 实现示例和使用 Apipost、cURL 等工具测试的实践指导,帮助开发者掌握这一核心技能,保障 API 系统的安全与高效运行。
|
异构计算 机器学习/深度学习 算法
探索FPGA在硬件加速中的应用
【5月更文挑战第31天】本文探讨了FPGA在硬件加速中的应用,阐述了FPGA基于可编程逻辑单元和连接资源实现高效并行处理的优势,如高性能、低功耗、可重构性和灵活性。FPGA广泛用于图像处理、数据压缩、深度学习加速和网络安全等领域。然而,FPGA也面临功耗、散热及开发复杂度的挑战。未来,FPGA将通过优化设计和工具,与CPU、GPU等协同工作,助力异构计算和新兴技术发展。
|
消息中间件 存储 运维
线上环境大规模RocketMQ集群不停机优雅升级实践
线上环境大规模RocketMQ集群不停机优雅升级实践
线上环境大规模RocketMQ集群不停机优雅升级实践
|
数据采集 存储 自然语言处理
HTTP协议简介
HTTP协议简介
555 1
|
算法 计算机视觉
OTSU(大津算法)
OTSU(大津算法)