OpenCV 模板与多个对象匹配方法详解(继OpenCV 模板匹配方法详解)

文章目录

  • 前言
  • 1.导入库
  • 2.图片预处理
  • 3.输出模板图片的宽和高
  • 4.模板匹配
  • 5.获取匹配结果中所有符合阈值的点的坐标
    • 5.1 threshold = 0.9:
    • 5.2 loc = np.where(res >= threshold):
  • 6.遍历所有匹配点
    • 6.1 loc 的结构回顾
    • 6.2 loc[::-1] 的作用
      • 6.2.1 为什么需要反转?
    • 6.3 zip(*loc[::-1]) 的作用
  • 7.画出模板匹配矩形框
    • 7.1 功能
    • 7.2 参数详解
    • 7.3 关键细节
    • 7.4 常见问题
  • 8.运行结果
  • 9. 总结

前言

上文《OpenCV 模板匹配方法详解》我们详细介绍了模板匹配这一方法,本文我们来介绍一下模板与多个对象匹配的方法。

其中有很多的函数需要我们来详细介绍,接下来我们直接看代码讲解:

1.导入库

import cv2
import numpy as np
  • 导入opencv库和numpy库

2.图片预处理

img_rgb = cv2.imread("image.jpg")
img_gray = cv2.cvtColor(img_rgb,cv2.COLOR_BGR2GRAY)
template = cv2.imread("tem.jpg",0)
  • 导入图片,并转化为灰度图
  • 导入的图片如下图所示,左图为匹配图片,右图为模板图片

在这里插入图片描述


3.输出模板图片的宽和高

h,w = template.shape[:2]
  • template.shape:假设 template 是一个 NumPy 数组(通常是图像数据),.shape 属性会返回数组的维度信息。
  • 对于图像:通常返回 (高度, 宽度, 通道数),如果是灰度图则只有 (高度, 宽度)
  • [:2]:切片操作,取前两个元素
  • 例如对于彩色图像 (480, 640, 3),取前两个值得到 (480, 640)
  • h, w = …:元组解包
  • 将前两个值分别赋值给变量 h (height/高度) 和 w (width/宽度)

所以这行代码的作用是:获取模板图像的高度和宽度,分别存入变量 h 和 w 中。


4.模板匹配

# 使用模板匹配方法 cv2.matchTemplate 进行模板匹配
res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)

功能:

  • 模板匹配:在 img_gray(灰度图像)中滑动 template(模板图像),计算每个位置的 相似度,并返回一个 相似度矩阵 res。
  • 匹配方法:cv2.TM_CCOEFF_NORMED 是 归一化相关系数匹配,取值范围 [-1, 1],越接近 1 表示匹配度越高。

返回值 res:

  • res 是一个 二维浮点型数组,大小 = (img_h - template_h + 1, img_w - template_w +1)(因为模板不能超出原图边界)
  • 每个 res[y, x] 表示模板在 (x, y) 处的匹配得分。

5.获取匹配结果中所有符合阈值的点的坐标

# 设定匹配阈值
threshold = 0.9
# 获取匹配结果中所有符合阈值的点的坐标
loc = np.where(res >= threshold) #(符合条件的行,符合条件的列)

5.1 threshold = 0.9:

功能:

  • 设定一个 匹配阈值,只有 res 中 ≥ 0.9 的点才被认为是有效匹配。

调整建议:

  • 阈值越高(如 0.95),匹配越严格,漏检率可能增加。
  • 阈值越低(如 0.8),匹配越宽松,但可能误检。

5.2 loc = np.where(res >= threshold):

功能:

  • 查找所有匹配度 ≥ threshold 的坐标,返回它们的 行列索引。
  • loc 是一个 元组,包含两个数组:
  •  loc[0]:所有匹配点的 Y 坐标(行索引)
    
  •  loc[1]:所有匹配点的 X 坐标(列索引
    

示例
假设 res 如下:

res = [[0.1, 0.3, 0.7],[0.8, 0.95, 0.6],  # (1,1) = 0.95 ≥ 0.9[0.4, 0.9, 0.2]    # (2,1) = 0.9 ≥ 0.9
]

执行 loc = np.where(res >= 0.9) 后:

loc = (array([1, 2]), array([1, 1]))  # 匹配点:(Y=1,X=1), (Y=2,X=1)

注意:loc 是一个元组,格式为 (y_coords, x_coords),所以先返回的是Y值,再返回的是X值!!!


6.遍历所有匹配点

for pt in zip(*loc[::-1]):

这段代码 for pt in zip(*loc[::-1]): 是 模板匹配后处理 的关键部分,用于遍历所有匹配到的目标位置,并调整坐标顺序以适应 OpenCV 的绘图要求。下面详细解析它的作用:

6.1 loc 的结构回顾

在之前的代码中:

loc = np.where(res >= threshold)
  • loc 是一个元组,格式为 (y_coords, x_coords),所以先返回的是Y值,再返回的是X值

6.2 loc[::-1] 的作用

loc[::-1] 的作用loc[::-1] 对元组进行 反向切片,将 (y_coords, x_coords) 变成 (x_coords, y_coords)。
例如:

loc = (array([1, 2]), array([3, 4]))
loc[::-1] = (array([3, 4]), array([1, 2]))  
# 现在顺序是 (x, y)

6.2.1 为什么需要反转?

  • OpenCV 的坐标系统使用 (x, y)(列在前,行在后),而 np.where() 返回的是 (y, x),因此需要交换顺序。

6.3 zip(*loc[::-1]) 的作用

  • *loc[::-1] 解包 元组,相当于
zip(array([3, 4]), array([1, 2]))
  • zip() 将两个数组按元素配对,生成可迭代的 (x, y) 坐标对
for pt in zip(*loc[::-1]):print(pt)  # 输出:(3, 1), (4, 2)

最终效果:
遍历所有匹配点,每次循环的 pt 是一个 (x, y) 坐标元组,可以直接用于 OpenCV 绘图函数(如 cv2.rectangle())。


7.画出模板匹配矩形框

cv2.rectangle(img_rgb,pt,(pt[0] + w,pt[1] + h),(0,0,255),1)

这段代码 cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 1) 是 OpenCV 中用于在图像上绘制矩形的函数,具体含义如下:


7.1 功能

在图像 img_rgb 上,以 pt 为左上角起点,绘制一个 宽度为 w、高度为 h 的红色矩形框,边框粗细为 1 像素


7.2 参数详解

参数含义示例
img_rgb要绘制矩形的目标图像(RGB 格式)从 cv2.imread()读取的图像
pt矩形的 左上角坐标 (x, y)(50, 100) 表示从图像的第 50 列、第 100 行开始
(pt[0] + w, pt[1] + h)矩形的 右下角坐标如果 pt=(50,100),w=30,h=20,则右下角是 (80, 120)
(0, 0, 255)矩形颜色(BGR 格式)(0,0,255)表示纯红色
1矩形边框的粗细(像素)1 表示 1 像素宽,-1表示填充矩形

7.3 关键细节

  1. 坐标顺序

    • OpenCV 使用 (x, y) 坐标,其中:
      • x 是水平方向(列索引,从左到右递增)
      • y 是垂直方向(行索引,从上到下递增)
  2. 颜色格式

    • (0, 0, 255)BGR 格式(不是 RGB),所以这里表示红色。
    • 常见颜色示例:
      • 红色:(0, 0, 255)
      • 绿色:(0, 255, 0)
      • 蓝色:(255, 0, 0)
  3. 矩形尺寸

    • w 和 h通常是模板图像的宽度和高度(通过 template.shape[:2] 获取)。
    • 如果 w 或 h 超出图像边界,OpenCV 会报错。

7.4 常见问题

  1. 为什么矩形颜色不对?

    • 检查颜色是否是 BGR 格式,例如红色应为 (0, 0, 255),而非 RGB 的 (255, 0, 0)。
  2. 如何调整矩形样式?

    • 修改参数:
      • 边框粗细:2 表示更粗的边框,-1 表示填充矩形。
      • 颜色:(255, 0, 0) 是蓝色,(0, 255, 0) 是绿色。

8.运行结果

在这里插入图片描述

9. 总结

到这里本篇博客就结束啦,感谢大家的阅读!最近一直在坚持每天写博客,当作是一个叙说心得的地方,在这个过程中自己通过不断的回顾之前所学习的内容,发现很多细节地方之前都没有注意到,通过再一次的回顾,增添了很多收获,这真的就是“温故而知新”这句话现实化了。最后,希望大家能一直朝着自己理想的方向努力。越努力,越幸运!!!

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

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

相关文章

产品经理学习过程

一:扫盲篇(初始产品经理) 阶段1:了解产品经理 了解产品经理是做什么的、产品经理的分类、产品经理在实际工作中都会接触什么样的岗位、以及产品经理在实际工作中具体要做什么事情。 二:准备篇 阶段2:工…

【消息队列RocketMQ】一、RocketMQ入门核心概念与架构解析

在当今互联网技术飞速发展的时代,分布式系统的架构设计愈发复杂。消息队列作为分布式系统中重要的组件,在解耦应用、异步处理、削峰填谷等方面发挥着关键作用。RocketMQ 作为一款高性能、高可靠的分布式消息中间件,被广泛应用于各类互联网场景…

从“链主”到“全链”:供应链数字化转型的底层逻辑

1. 制造业与供应链数字化转型的必然性 1.1. 核心概念与战略重要性 制造业的数字化转型,是利用新一代数字技术(如工业互联网、人工智能、大数据、云计算、边缘计算等)对制造业的整体价值链进行根本性重塑的过程。这不仅涉及技术的应用&#…

x-ui重新申请ssl证书失败

由于某些需要我们重新申请ssl证书,x-ui自动化脚本不能强制更新,根据x-ui仓库源码: https://github.com/vaxilu/x-ui/blob/main/x-ui.sh 在申请ssl证书的地方稍作修改,得到,运行下面的脚本就可以重新申请ssl证书&#…

Java NIO Java 虚拟线程(微线程)与 Go 协程的运行原理不同 为何Go 能在低配机器上承接10万 Websocket 协议连接

什么是Java NIO? Java NIO(New Input/Output) 是Java 1.4(2002年)引入的一种非阻塞、面向缓冲区的输入输出框架,旨在提升Java在高性能和高并发场景下的I/O处理能力。它相比传统的 Java IO(java…

go环境安装mac

下载go安装包:https://golang.google.cn/dl/ 找到对应自己环境的版本下载。 注意有二进制的包,也有图形界面安装的包。图形界面直接傻瓜式点就行了。 二进制的按照下面操作: 1、下载二进制包。 2、将下载的二进制包解压至 /usr/local目录…

LVGL源码(9):学会控件的使用(自定义弹窗)

LVGL版本:8.3 LVGL的控件各式各样,每种控件都有自己的一些特性,当我们想要使用一个LVGL控件时,我们首先可以通过官网去了解控件的一些基本特性,官网链接如下: LVGL Basics — LVGL documentation&#xf…

《软件设计师》复习笔记(1)——考试介绍【新】

目录 一、考试介绍 证书价值 考试要求 二、【新】计算机与软件工程知识 三、软件设计 一、考试介绍 >考试科目>考题形式>考试时长>合格标准计算机与软件工程知识75道单选题(每题1分,总分75分)2023年11月改革机试后&#…

MCU中的BSS和data都占用SRAM空间吗?

在MCU中,BSS段和data段都占用SRAM空间,但它们的存储方式和用途有所不同。‌ BSS段 BSS段(Block Started by Symbol)用于存储未初始化的全局变量和静态变量。这些变量在程序启动时会被清零,因此它们不占用Flash空间&a…

Ubuntu 22.04 更换 Nvidia 显卡后启动无法进入桌面问题的解决

原显卡为 R7 240, 更换为 3060Ti 后, 开机进桌面时卡在了黑屏界面, 键盘有反应, 但是无法进入 shell. 解决方案为 https://askubuntu.com/questions/1538108/cant-install-rtx-4060-ti-on-ubuntu-22-04-lts 启动后在开机菜单中(如果没有开机菜单, 需要按shift键), 进入recove…

Python爬虫-爬取猫眼演出数据

前言 本文是该专栏的第53篇,后面会持续分享python爬虫干货知识,记得关注。 猫眼平台除了有影院信息之外,它还涵盖了演出信息,比如说“演唱会,音乐节,话剧音乐剧,脱口秀,音乐会,戏曲艺术,相声”等等各种演出相关信息。 而本文,笔者将以猫眼平台为例,基于Python爬虫…

人工智能-机器学习(线性回归,逻辑回归,聚类)

人工智能概述 人工智能分为:符号学习,机器学习。 机器学习是实现人工智能的一种方法,深度学习是实现机器学习的一种技术。 机器学习:使用算法来解析数据,从中学习,然后对真实世界中是事务进行决策和预测。如垃圾邮件检…

FPGA学习(五)——DDS信号发生器设计

FPGA学习(五)——DDS信号发生器设计 目录 FPGA学习(五)——DDS信号发生器设计一、FPGA开发中常用IP核——ROM/RAM/FIFO1、ROM简介2、ROM文件的设置(1)直接编辑法(2)用C语言等软件生成初始化文件 3、ROM IP核配置调用 二、DDS信号发…

【Vue】从 MVC 到 MVVM:前端架构演变与 Vue 的实践之路

个人博客:haichenyi.com。感谢关注 一. 目录 一–目录二–架构模式的演变背景​三–MVC:经典的分层起点​四–MVP:面向接口的解耦尝试​五–MVVM:数据驱动的终极形态​​六–Vue:MVVM 的现代化实践​​​ 二. 架构模…

【算法】快速排序、归并排序(非递归版)

目录 一、快速排序&#xff08;非递归&#xff09; 1.原理 2.实现 2.1 stack 2.2 partition(array,left,right) 2.3 pivot - 1 > left 二、归并排序&#xff08;非递归&#xff09; 1.原理 2.实现 2.1 gap 2.1.1 i 2*gap 2.1.2 gap * 2 2.1.3 gap < array.…

CasualLanguage Model和Seq2Seq模型的区别

**问题1&#xff1a;**Causal Language Modeling 和 Conditional Generation 、Sequence Classification 的区别是什么&#xff1f; 因果语言模型(Causal Language Model)&#xff1a; 预测给定文本序列中的下一个字符&#xff0c;一般用于文本生成、补全句子等&#xff0c;模型…

【计算机视觉】三维视觉项目 - Colmap二维图像重建三维场景

COLMAP 3D重建 项目概述项目功能项目运行方式1. 环境准备2. 编译 COLMAP3. 数据准备4. 运行 COLMAP 常见问题及解决方法1. **编译问题**2. **运行问题**3. **数据问题** 项目实战建议项目参考文献 项目概述 COLMAP 是一个开源的三维重建软件&#xff0c;专注于 Structure-from…

状态管理最佳实践:Bloc架构实践

状态管理最佳实践&#xff1a;Bloc架构实践 引言 Bloc (Business Logic Component) 是Flutter中一种强大的状态管理解决方案&#xff0c;它基于响应式编程思想&#xff0c;通过分离业务逻辑和UI表现层来实现清晰的代码架构。本文将深入探讨Bloc的核心概念、实现原理和最佳实践…

Python多任务编程:进程全面详解与实战指南

1. 进程基础概念 1.1 什么是进程&#xff1f; 进程(Process)是指正在执行的程序&#xff0c;是程序执行过程中的一次指令、数据集等的集合。简单来说&#xff0c;进程就是程序的一次执行过程&#xff0c;它是一个动态的概念。 想象你打开电脑上的音乐播放器听歌&#xff0c;…

Linux 网络基础(二) (传输协议层:UDP、TCP)

目录 一、传输层的意义 二、端口号 1、五元组标识一个通信 2、端口号范围划分 3、知名端口号&#xff08;Well-Know Port Number&#xff09; &#xff08;1&#xff09;查看端口号 4、绑定端口号数目问题 5、pidof & netstat 命令 &#xff08;1&#xff09;ne…