目录

简介

一、轮廓检测

1.查找轮廓的API

2.代码分析

2.1.图像二值化处理

2.2轮廓检测

2.3轮廓绘制

2.4轮廓面积计算

2.5轮廓周长计算

2.6筛选特定面积的轮廓

2.7查找最大面积的轮廓

2.8绘制轮廓的外接圆

2.9绘制轮廓的外接矩形

二、轮廓的近似

三、模板匹配 


简介

        今天继续学习opencv,今天学习轮廓检测、轮廓的近似

计算机视觉第一课opencv(三)保姆级教学

计算机视觉第一课opencv(一)保姆级教学

计算机视觉第一课opencv(二)保姆级教学

一、轮廓检测

1.查找轮廓的API

image, contours, hierarchy = cv2.findContours(img, mode, method)
参数:img: 需要实现轮廓检测的原图
mode: 轮廓的检索模式,主要有四种方式:cv2.RETR_EXTERNAL:只检测外轮廓,所有子轮廓被忽略cv2.RETR_LIST:检测的轮廓不建立等级关系,所有轮廓属于同一等级cv2.RETR_CCOMP:返回所有的轮廓,只建立两个等级的轮廓,一个对象的外轮廓为第1级组织结构,而对象内中空的轮廓为第2级组织结构,空间中的任何对象的轮廓又是第 1 级组织结构。
-> cv2.RETR_TREE:返回所有的轮廓,建立一个完整的组织结构的轮廓。
method: 轮廓的近似方法,主要有以下两种:
-> cv2.CHAIN_APPROX_NONE:存储所有的轮廓点。
-> cv2.CHAIN_APPROX_SIMPLE:压缩模式,只保留该方向的终点坐标,例如一个矩形轮廓只画4个点来保存轮廓信息。
返回:image: 返回类型的原图contours:包含图像中所有轮廓的list对象,其中每一个独立的轮廓信息以边界点坐标(x,y)的形式储存在numpy数组中。hierarchy:轮廓的层次结构,一个包含4个值的数组:[Next, Previous, First Child, Parent]Next:与当前轮廓处于同一层级的下一条轮廓Previous:与当前轮廓处于同一层级的上一条轮廓First Child:当前轮廓的第一条子轮廓Parent:当前轮廓的父轮廓注意:做轮廓检测前需要将图片读取为二值数据,即像素值只为0和255。

2.代码分析

图像读取与预处理

import cv2
phone = cv2.imread('phone.png')  # 读取原图,默认以BGR格式加载
phone_gray = cv2.cvtColor(phone, cv2.COLOR_BGR2GRAY)  # 转换为灰度图
cv2.imshow('phone_0', phone_gray)  # 显示灰度图
cv2.waitKey(0)  # 等待用户按键,0表示无限等待
  • 这部分代码首先读取图像,然后将彩色图像转为灰度图(减少计算量,便于后续处理)
  • cv2.imshow()用于显示图像,cv2.waitKey(0)确保图像窗口不会立即关闭

2.1.图像二值化处理

ret, phone_binary = cv2.threshold(phone_gray, 120, 255, cv2.THRESH_BINARY)  # 二值化处理
cv2.imshow('phone_binary', phone_binary)
cv2.waitKey(0)
  • 二值化是轮廓检测的前提,将灰度图转换为只有黑白两种颜色的图像
  • 参数解释:
    • 120:阈值,像素值高于此值会被处理
    • 255:最大值,满足条件的像素会被设置为此值
    • cv2.THRESH_BINARY:二值化类型,大于阈值的设为 255,否则设为 0

2.2轮廓检测

contours = cv2.findContours(phone_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[-2]  # 检测轮廓
print(len(contours))  # 打印检测到的轮廓数量
  • cv2.findContours()是轮廓检测的核心函数
  • 参数解释:
    • cv2.RETR_TREE:轮廓检索模式,检测所有轮廓并建立完整的层次结构
    • cv2.CHAIN_APPROX_NONE:轮廓近似方法,存储所有轮廓点
    • [-2]:兼容不同 OpenCV 版本的写法,确保获取到轮廓列表

2.3轮廓绘制

image_copy = phone.copy()  # 复制原图,避免在原图上直接绘制
cv2.drawContours(image=image_copy, contours=contours, contourIdx=-1,  # -1表示绘制所有轮廓color=(0,0,255),  # 红色(BGR格式)thickness=2  # 线条粗细
)
cv2.imshow('Contours_show', image_copy)
cv2.waitKey(0)
  • cv2.drawContours()用于在图像上绘制轮廓
  • 这里创建原图副本是为了保留原图,方便后续其他处

2.4轮廓面积计算

area_0 = cv2.contourArea(contours[0])  # 计算第一个轮廓的面积
print(area_0)
area_1 = cv2.contourArea(contours[1])  # 计算第二个轮廓的面积
print(area_1)
  • cv2.contourArea()用于计算轮廓所包围的面积
  • 面积单位是像素,值越大表示轮廓包围的区域越大

2.5轮廓周长计算

length = cv2.arcLength(contours[0], closed=True)  # 计算第一个轮廓的周长
print(length)
  • cv2.arcLength()用于计算轮廓的周长
  • closed=True表示轮廓是封闭的

2.6筛选特定面积的轮廓

a_list = []
for i in contours:if cv2.contourArea(i) > 10000:  # 筛选面积大于10000的轮廓a_list.append(i)
image_copy = phone.copy()
image_copy = cv2.drawContours(image_copy, a_list, -1, (0, 255, 0), 3)  # 用绿色绘制筛选后的轮廓
cv2.imshow('Contours_show_10000', image_copy)
cv2.waitKey(0)
  • 这部分实现了根据面积筛选轮廓的功能
  • 只保留面积大于 10000 的轮廓,并用绿色绘制,便于观察较大的物体轮廓

2.7查找最大面积的轮廓

# 按面积降序排序,取第一个(面积最大的轮廓)
sortcnt = sorted(contours, key=cv2.contourArea, reverse=True)[0]
image_contours = cv2.drawContours(phone.copy(), [sortcnt], -1, (0, 0, 255), 3)
cv2.imshow('image_contours', image_contours)
cv2.waitKey(0)
  • 使用sorted()函数和cv2.contourArea作为排序键,找到面积最大的轮廓
  • 这种方法常用于定位图像中最主要的物体

2.8绘制轮廓的外接圆

cnt = contours[6]  # 选择第7个轮廓(索引从0开始)
(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)
cv2.waitKey(0)
  • cv2.minEnclosingCircle()计算能包围轮廓的最小圆
  • 返回值包括圆心坐标 (x,y) 和半径 r
  • cv2.circle()用于绘制圆形,这里用绿色线条

2.9绘制轮廓的外接矩形

x, y, w, h = cv2.boundingRect(cnt)  # 计算最小外接矩形
phone_rectangle = cv2.rectangle(phone, (x, y), (x + w, y + h), (255, 0, 0), 2)  # 绘制矩形
cv2.imshow('phone_rectangle', phone_rectangle)
cv2.waitKey(0)
  • cv2.boundingRect()计算能包围轮廓的最小矩形(轴对齐矩形)
  • 返回值包括矩形左上角坐标 (x,y)、宽度 w 和高度 h
  • cv2.rectangle()用于绘制矩形,这里用蓝色线条

二、轮廓的近似

approx = cv2.approxPolyDP(curve, epsilon, closed)
参数说明:curve:输入轮廓。epsilon:近似精度,即两个轮廓之间最大的欧式距离。该参数越小,得到的近似结果越接近实际轮廓;反之,得到的近似结果会更加粗略。closed:布尔类型的参数,表示是否封闭轮廓。如果是 True,表示输入轮廓是封闭的,近似结果也会是封闭的;否则表示输入轮廓不是封闭的,近似结果也返回值:approx:近似结果,是一个ndarray数组,为1个近似后的轮廓,包含了被近似出来的轮廓上的点的坐标

图像读取与预处理

phone = cv2.imread('phone.png')  # 读取原图
phone_gray = cv2.cvtColor(phone,cv2.COLOR_BGR2GRAY)  # 转换为灰度图
ret,phone_thresh = cv2.threshold(phone_gray, 120, 255,cv2.THRESH_BINARY)  # 二值化处理
  • 将彩色图像转为灰度图,简化图像处理
  • 二值化处理:将灰度图转换为只有黑白两种颜色的图像,阈值设为 120,大于 120 的像素变为 255(白色),小于等于 120 的变为 0(黑色)

轮廓检测

contours=cv2.findContours(phone_thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)[-2]
  • 使用cv2.findContours函数检测轮廓
  • 参数cv2.RETR_TREE表示检测所有轮廓并建立完整的层次结构
  • 参数cv2.CHAIN_APPROX_NONE表示存储所有轮廓点
  • [-2]是为了兼容不同 OpenCV 版本,确保获取到轮廓列表

轮廓近似处理

# 设置近似精度,epsilon值越小,近似结果越接近原始轮廓
epsilon = 0.002 * cv2.arcLength(contours[0], True)        # 对轮廓进行近似
approx = cv2.approxPolyDP(contours[0], epsilon, True)   
  • cv2.arcLength计算轮廓周长,True表示轮廓是封闭的
  • epsilon是近似精度,这里设置为轮廓周长的 0.002 倍
  • cv2.approxPolyDP函数实现轮廓近似,将轮廓用更少的点来表示,保留主要形状

结果对比与显示

# 打印原始轮廓和近似轮廓的点数量
print(contours[0].shape)
print(approx.shape)# 绘制近似后的轮廓
phone_new = phone.copy()
image_contours = cv2.drawContours(phone_new, [approx], contourIdx=-1, color=(0,255,0), thickness=3)# 显示原图和处理后的图像
cv2.imshow('phone', phone)
cv2.waitKey(0)
cv2.imshow('image_contours', image_contours)
cv2.waitKey(0)
  • 通过打印形状可以看到,近似后的轮廓点数量明显减少
  • 用绿色线条绘制近似后的轮廓,并与原图进行对比显示
  • cv2.waitKey(0)表示等待用户按键后再继续执行

        通过调整epsilon的值,可以控制近似程度,值越大,轮廓简化越明显,保留的点越少;值越小,越接近原始轮廓。
 

三、模板匹配 

模板匹配是一种用于查找与模板图像(补丁)匹配(相似)的图像区域的技术

为了识别匹配区域,我们必须通过滑动来将模板图像与源图像进行比较

一次移动一个像素(从左到右,从上到下)。在每个位置,都会计算一个度量(度量计算公式),以便它表示该位置的匹配“好”或“坏”程度

 cv2.matchTemplate(image, templ, method, result=None, mask=None) 

image :待搜索图像

templ:模板图像

method:计算匹配程度的方法,可以有:

        TM_SQDIFF 平方差匹配法,该方法采用平方差进行匹配;匹配越好,值越小;匹配越差,值越大。

        TM_CCORR 相关匹配法,该方法采用乘积操作;数值越大表明匹配程度越好。

        TM_CCOEFF 相关系数匹配法,数值越大表明匹配程度越好。

        TM_SQDIFF_NORMED 归一化平方差匹配法,匹配越好,值越小;匹配越差,值越大。         TM_CCORR_NORMED 归一化相关匹配法,数值越大表明匹配程度越好。         TM_CCOEFF_NORMED 归一化相关系数匹配法,数值越大表明匹配程度越好。

图像读取与显示

kele = cv2.imread('kele.png')
template = cv2.imread('template.png')
cv2.imshow(winname='kele', mat=kele)
cv2.imshow(winname='template', mat=template)
cv2.waitKey(0)
  • cv2.imread:从本地加载图像,kele 存大图像、template 存模板小图像,默认按 BGR 色彩空间 读入(和日常 RGB 有区别,OpenCV 历史原因导致 )。
  • cv2.imshow:创建窗口显示图像,第一个参数是窗口名称(winname ),第二个是要显示的图像数据(mat )。
  • cv2.waitKey(0):暂停程序,等待用户按下任意键再继续执行,0 表示 “无限等待”,保证图像窗口能停留让我们看到内容。

获取模板尺寸与执行模板匹配

h, w = template.shape[:2]
res = cv2.matchTemplate(kele, template, cv2.TM_CCOEFF_NORMED)  
  • template.shape[:2]:获取模板图像的 高度(h)、宽度(w) ,shape 返回 (高,宽,通道数) ,[:2] 取前两个值,后续标记匹配区域会用到尺寸。
  • cv2.matchTemplate(...):执行模板匹配核心操作!把 template 当 “模板”,在 kele 里逐像素 / 逐区域滑动比较 。cv2.TM_CCOEFF_NORMED 是选的 归一化相关系数匹配法 ,结果存在 res 里:res 是个二维矩阵,每个元素值表示对应位置与模板的匹配程度(越接近 1 ,匹配越好 )。

解析匹配结果,标记目标区域

min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)  
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
kele_template = cv2.rectangle(kele, top_left, bottom_right, color=(0, 255, 0), thickness=2)  
  • cv2.minMaxLoc(res):从 res(匹配结果矩阵 )里找 最小值(min_val )、最大值(max_val ),以及它们对应的坐标(min_locmax_loc ) 。因为用了 TM_CCOEFF_NORMED ,值越大匹配越好,所以关注 max_loc(最佳匹配区域的左上角坐标 )。
  • bottom_right = (top_left[0] + w, top_left[1] + h):根据模板宽高,算出匹配区域 右下角坐标 ,这样就能确定一个矩形范围。
  • cv2.rectangle(...):在 kele 图像上画矩形!参数分别是:要画的图像(kele )、左上角坐标(top_left )、右下角坐标(bottom_right )、矩形颜色((0, 255, 0) ,即绿色,BGR 格式 )、线条粗细(thickness=2 ),结果存在 kele_template 里。

显示最终结果

cv2.imshow(winname='kele_template', mat=kele_template)
cv2.waitKey(0)
  • 用 cv2.imshow 显示标记了匹配区域的图像 kele_template ,再用 cv2.waitKey(0) 等待按键,方便我们查看匹配效果,程序最后才结束。

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Vue2+elementUi实现树形 横向 合并 table不规则表格

1、实现效果 共N行&#xff0c;但是每一列对应的单元格列数固定&#xff0c;行数不固定2、实现方式说明&#xff1a;使用的是vue2 elementUI表格组件 js实现<template><div class"table-container" ><el-table height"100%" :span-metho…

深度学习在计算机视觉中的应用:对象检测

引言 对象检测是计算机视觉领域中的一项基础任务&#xff0c;目标是在图像或视频帧中识别和定位感兴趣的对象。随着深度学习技术的发展&#xff0c;对象检测的准确性和效率都有了显著提升。本文将详细介绍如何使用深度学习进行对象检测&#xff0c;并提供一个实践案例。 环境准…

node.js 安装步骤

在Node.js中安装包通常通过npm(Node Package Manager)来完成,这是Node.js的包管理工具。以下是安装Node.js和通过npm安装包的基本步骤: 1. 安装Node.js 方法一:使用nvm(Node Version Manager) 推荐使用nvm来安装Node.js,因为它允许你安装多个Node.js版本,并轻松地在…

面试-故障案例解析

一、NFS故障&#xff0c;造成系统cpu使用率低而负载极高。故障概述: 公司使用NFS为web节点提供共享存储服务,某一天下午发现web节点CPU使用率低,而负载极高.登录web节点服务器排查发现后段NFS服务器故障. 影响范围: 网站看不到图片了。 处理流程: 通过ssh登录NFS服务…

医疗AI时代的生物医学Go编程:高性能计算与精准医疗的案例分析(一)

摘要: 随着高通量测序、医学影像和电子病历等生物医学数据的爆炸式增长,对高效、可靠、可扩展的计算工具需求日益迫切。Go语言凭借其原生并发模型、卓越的性能、简洁的语法和强大的标准库,在生物医学信息学领域展现出独特优势。本文以“生物医学Go编程探析”为主题,通过三个…

针对 “TCP 连接建立阶段” 的攻击

针对 “TCP 连接建立阶段” 的攻击一、定义二、共性防御思路三、攻击手段3.1、SYN 洪水攻击&#xff08;SYN Flood&#xff09;3.2、Land 攻击&#xff08;Land Attack&#xff09;一、定义 什么是针对 “TCP 连接建立阶段” 的攻击&#xff1f;核心特征是利用 TCP “三次握手…

聊一聊 单体分布式 和 微服务分布式

微服务 与 单体架构对比维度单体架构微服务架构​​架构本质​​一个单一的、功能齐全的应用程序一组​​小型、独立​​的服务集合​​开发​​团队工作在同一个代码库&#xff0c;易产生冲突。技术栈统一。每个服务可以由​​ 独立的小团队 ​​负责&#xff0c;允许使用​​…

【C++八股文】计算机网络篇

网络协议核心知识点详解 TCP头部结构 TCP头部包含多个关键字段&#xff0c;每个字段都有其特定作用&#xff1a; 16位源端口&#xff1a;标识发送方应用程序的端口号16位目的端口&#xff1a;标识接收方应用程序的端口号32位序号&#xff1a;保证数据包有序传输的唯一标识32…

小迪Web自用笔记7

游戏一般不走http https协议&#xff0c;一般的抓包工具抓不到。科来&#xff0c;这个工具是从网卡抓包。你一旦打怪数据就会多起来↓但不是很专业。可以抓到https。wep↑这个西东是全部协议都做流量包&#xff0c;你不知道他是从哪儿来的&#xff0c;他全都抓&#xff08;专业…

现代 Linux 发行版为何忽略Shell脚本的SUID位?

在现代Linux系统中&#xff0c;为Shell脚本设置 SUID&#xff08;Set User ID&#xff09; 权限位几乎是无效的。这个看似简单的现象背后&#xff0c;是Linux内核设计者们在安全与便利性之间做出的一个至关重要的历史性抉择。要彻底理解这一点&#xff0c;我们需要深入到内核层…

Qt节点编辑器设计与实现:动态编辑与任务流可视化(一)

文章目录一、项目概述二、整体架构&#xff1a;模型-视图分离的设计哲学1. 模型层&#xff1a;数据与业务逻辑的核心2. 视图层&#xff1a;图形渲染与用户交互3. 交互层&#xff1a;连接模型与视图的桥梁三、核心模块解析1. 样式管理系统&#xff1a;视觉表现的基石2. 图形数据…

MySQL常见报错分析及解决方案总结(4)---ERROR 1040(00000):Too many connections

报错信息&#xff1a;ERROR 1040(00000):Too many comnections异常效果&#xff1a;原因分析&#xff1a;“ERROR 1040 (00000): Too many connections” 是 MySQL 数据库最常见的连接数超限错误&#xff0c;本质是 “当前试图连接数据库的客户端数量&#xff0c;超过了 MySQL …

GRPO(组相对策略优化):大模型强化学习的高效进化

本文由「大千AI助手」原创发布&#xff0c;专注用真话讲AI&#xff0c;回归技术本质。拒绝神话或妖魔化。搜索「大千AI助手」关注我&#xff0c;一起撕掉过度包装&#xff0c;学习真实的AI技术&#xff01; ✨ 1. GRPO概述&#xff1a;重新定义大模型强化学习效率 GRPO&#x…

【Canvas与戳记】蓝底黄面十六角Premium Quality戳记

【成图】【代码】<!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>蓝底黄面十六角Premium Quality戳记 Draft1</title><style ty…

深度学习:洞察发展趋势,展望未来蓝图

在科技飞速发展的当下&#xff0c;深度学习作为人工智能领域的璀璨明星&#xff0c;正以前所未有的速度重塑着各个行业的格局。从日常使用的智能语音助手&#xff0c;到医疗领域精准的疾病诊断&#xff0c;再到自动驾驶汽车对复杂路况的实时感知与决策&#xff0c;深度学习无处…

基于Docker部署的Teable应用

简介Teable 是一款高性能多维表格本地化的解决方案&#xff0c;通过无代码方式快速构建业务管理系统&#xff0c;支持私有部署和精细权限管理。对于个人或者小团队使用&#xff0c;可以避免昂贵的集成软件带来的成本压力。特点Excel 式任意拖拽选区编辑支持双向关联&#xff0c…

Java项目实现【记录系统操作日志】功能

✨ 哈喽&#xff0c;屏幕前的每一位开发者朋友&#xff0c;你们好呀&#xff01;✨​ 当你点开这篇文章时&#xff0c;或许正对着 IDE 里闪烁的光标发呆&#xff0c;或许刚解决一个卡了三天的 bug&#xff0c;正端着咖啡松口气 —— 不管此刻的你在经历什么&#xff0c;都想先和…

响应式编程框架Reactor【4】

文章目录七、调度与线程模型7.1 概述7.2 Scheduler: Reactor 的线程调度器7.3 两大核心操作符&#xff1a;subscribeOn vs publishOn7.4 示例详解7.4.1 subscribeOn()的全局影响7.4.2 publishOn() 的局部切换7.4.3 多个publishOn切换7.4.4 线程切换时序图7.5 核心调度器7.5.1 B…

第21节:环境贴图与PBR材质升级——构建电影级真实感渲染

第21节&#xff1a;环境贴图与PBR材质升级——构建电影级真实感渲染 概述 基于物理的渲染&#xff08;Physically Based Rendering, PBR&#xff09;是当代计算机图形学中最重要的技术进步之一&#xff0c;它彻底改变了实时渲染的质量标准。在本节中&#xff0c;我们将深入探索…

【ROS2】ROS2 基础学习教程 、movelt学习

主要博主 参考资料&#xff1a; ROS系列&#xff1a; b站荔枝橙 b战哈萨克斯坦x 《ROS 2机器人开发从入门到实践》6.2.2 在RViz中显示机器人_哔哩哔哩_bilibili 动手学ROS2–鱼香肉丝 ​​​​​​​ 古月居ros2教程 北京华清智能科技 ros教程 moveit系列&#xff1a; 爱喝青…