计算机视觉——基于OpenCV和Python进行模板匹配

模板匹配?

模板匹配是它允许在一幅较大的图像中寻找是否存在一个较小的、预定义的模板图像。这项技术的应用非常广泛,包括但不限于图像识别、目标跟踪和场景理解等。

目标和原理

模板匹配的主要目标是在一幅大图像中定位一个或多个与模板图像相匹配的区域。这个过程就像是用一个“放大镜”在大图像上移动,不断比较模板图像与大图像中相应位置的相似度。通过计算模板图像和大图像中各个位置的像素差异,可以找到与模板图像最为相似的区域。

比较方法

在执行模板匹配时,有多种比较方法可供选择,这些方法决定了如何计算模板图像与大图像之间的相似度。以下是一些常用的比较方法:

  1. 相关性(Correlation): 这种方法通过计算模板图像和大图像中相应区域的像素值的乘积和来评估相似度。当乘积和最大时,表示两个图像在该位置的匹配度最高。

  2. 差异(Difference): 与相关性相反,差异方法通过计算模板图像和大图像中相应区域的像素值差的绝对值或平方值来评估相似度。在这种方法中,差异值最小的地方表示匹配度最高。

  3. 归一化交叉相关(Normalized Cross-Correlation): 这是一种更为健壮的比较方法,它通过将模板图像和大图像的像素值与各自的平均值进行比较来计算相似度。这种方法对于光照变化和图像对比度的变化具有更好的适应性。

  4. 平方差(Squared Difference): 这种方法计算模板图像和大图像中相应区域的像素值差的平方和。平方差越小,表示匹配度越高。

  5. 相关系数(Correlation Coefficient): 这是一种基于统计学的方法,它通过计算模板图像和大图像之间的相关系数来评估它们的相似度。相关系数的值介于-1和1之间,值越接近1,表示匹配度越高。

使用OpenCV进行模板匹配

OpenCV提供了cv2.matchTemplate()函数,用于执行模板匹配。

该函数接受以下参数:

  • image – 要在其中搜索模板的较大图像。
  • template – 在搜索的模板图像。
  • method – 要使用的比较方法。有多种可用的比较方法。

然后,函数返回一个包含比较结果的矩阵。矩阵中的每个元素都将具有一个值,指示模板图像与较大图像区域的匹配程度。

# 导入必要的包
import cv2# 加载主图像和模板图像
image = cv2.imread("examples/1.jpg")
template = cv2.imread("examples/template1.jpg")# 制作图像的副本
image_copy = image.copy()# 将图像转换为灰度图像
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
template_gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)# 获取模板图像的宽度和高度
template_h, template_w = template.shape[:1]# 使用归一化交叉相关方法执行模板匹配
result = cv2.matchTemplate(image_gray, template_gray, cv2.TM_CCOEFF_NORMED)# 找到结果矩阵中最佳匹配的位置
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)# 在最佳匹配周围绘制矩形
top_left = max_loc
bottom_right = (top_left[0] + template_w, top_left[1] + template_h)
cv2.rectangle(image_copy, top_left, bottom_right, (0, 255, 0), 2)# 显示图像
cv2.imshow("Image", image)
cv2.imshow("Template", template)
cv2.imshow("Matched Template", image_copy)
cv2.waitKey(0)

在这里插入图片描述
在这里插入图片描述

多模板匹配与OpenCV

如果想要在一张图像中检测同一对象的多个实例怎么办?在这种情况下,需要对代码进行一些修改。在之前的代码中,只获取了最佳匹配的位置。可以修改代码,以便获取所有高于某个阈值的匹配位置。

import cv2
import numpy as np# 设置模板匹配和非极大值抑制阈值
thresh = 0.98
nms_thresh = 0.6# 加载主图像和模板图像
image = cv2.imread("examples/2.jpg")
template = cv2.imread("examples/template2.jpg")# 制作图像的副本
image_copy = image.copy()# 将图像转换为灰度图像
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
template_gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)# 获取模板图像的宽度和高度
template_h, template_w = template.shape[:1]# 使用归一化交叉相关方法执行模板匹配
result = cv2.matchTemplate(image_gray, template_gray, cv2.TM_CCOEFF_NORMED)# 获取高于阈值的匹配位置的坐标
y_coords, x_coords = np.where(result >= thresh)print("找到的匹配数量:", len(x_coords))# 循环遍历坐标并在匹配周围绘制矩形
for x, y in zip(x_coords, y_coords):cv2.rectangle(image_copy, (x, y), (x + template_w, y + template_h), (0, 255, 0), 2)# 显示图像
cv2.imshow("Template", template)
cv2.imshow("Multi-Template Matching", image_copy)
cv2.waitKey(0)

在这里插入图片描述
在这里插入图片描述

非极大值抑制在多模板匹配中的应用

非极大值抑制(Non-Maximum Suppression,简称NMS)是目标检测算法中的一个重要步骤,特别是在处理涉及多个模板的情况时,它有助于消除冗余的重叠边界框。OpenCV提供了一个名为cv2.dnn.NMSBoxes()的函数,可以用来执行非极大值抑制。

创建一个边界框列表,使用匹配的坐标,这些匹配的分数高于设定的阈值:

# 创建边界框列表
boxes = np.array([[x, y, x + template_w, y + template_h]for (x, y) in zip(x_coords, y_coords)])

接下来,对这些边界框应用非极大值抑制:

# 应用非极大值抑制到边界框
indices = cv2.dnn.NMSBoxes(boxes, result[y_coords, x_coords], thresh, nms_thresh)

cv2.dnn.NMSBoxes()函数接受边界框、分数、阈值和非极大值抑制阈值作为参数。

分数是由模板匹配函数返回的值。只需要获取高于阈值的匹配分数。在上面的代码中,可以通过result[y_coords, x_coords]表达式来做到这一点。

thresh参数在这里不是很重要,因为我们已经过滤掉了低于阈值的匹配。

nms_thresh参数是非极大值抑制阈值。我们已经将其设置为0.6。

函数返回经过非极大值抑制后仍然存在的边界框的索引。例如,回到之前的例子中,这里有8个边界框:

[[347 134 420 206][348 134 421 206][433 134 506 206][347 219 420 291][348 219 421 291][433 219 506 291][348 220 421 292][433 220 506 292]]

应用非极大值抑制后,得到这个索引列表:

[2 5 1 4]

因此,索引2、5、1和4指的是经过非极大值抑制后仍然存在的边界框。可以使用这些索引来保留那些经过非极大值抑制后仍然存在的边界框。

for i in indices:(x, y, w, h) = boxes[i][0], boxes[i][1], boxes[i][2], boxes[i][3]cv2.rectangle(image, (x, y), (w, h), (0, 255, 0), 2)

然后在主图像上绘制边界框。结果将与之前的相似,但如果仔细观察,会发现边界框的厚度不同。这是因为使用非极大值抑制去除了重复的边界框。

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

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

相关文章

最小生成树算法的实现c++

最小生成树算法的实现c 题目链接:1584. 连接所有点的最小费用 - 力扣(LeetCode) 主要思路:使用krusal算法,将边的权值进行排序(从小到大排序),每次将权值最小且未加入到连通分量中…

Cesium中实现镜头光晕

镜头光晕 镜头光晕 (Lens Flares) 是模拟相机镜头内的折射光线的效果,主要作用就是让太阳光/其他光源更加真实,和为您的场景多增添一些气氛。 Cesium 中实现 其实 Cesium 里面也是有实现一个镜头光晕效果的,添加方式如下,只是效…

Python教学入门:数字类型与字符串

字符串元素组成的序列 字符串元素组成的序列指的是字符串中的每个字符按照一定的顺序排列形成的序列。在 Python 中,字符串是由字符组成的有序序列(Sequence),每个字符在字符串中有其固定的位置(索引)&…

Android RecyclerView的LayoutManager配置

RecyclerView的item布局方式依赖于其配置的布局管理器。不同的布局管理器可以实现不同的界面效果。 LayoutManager介绍 RecyclerView可以通过setLayoutManager设置布局管理器,该方法的源码如下: /*** Set the {link LayoutManager} that this RecyclerV…

java网络编程 BufferedReader的readLine方法读不到数据且一直阻塞

最近在整理Java IO相关内容,会遇到一些以前没有注意的问题,特此记录,以供自查和交流。 需求: 基于Java的BIO API,实现简单的客户端和服务端通信模型,客户端使用BufferedReader的readLine方法读取System.i…

ASPICE 追溯性实践分享

01前言 接着之前的分享,遗留的追溯性ASPICE 认证实践及个人理解分享-CSDN博客文章浏览阅读961次,点赞22次,收藏17次。ASPICE是Automotive 和SPICE的组合,全英文为(Automotive Software ProcessImprovement and Determ…

C++修炼之路之继承<二>

目录 一:子类的六大默认成员函数 二:继承与友元 三:继承与静态成员 四:复杂的继承关系菱形继承菱形虚拟继承 1.单继承 2.多继承 3.菱形继承;一种特殊的多继承 4.菱形虚拟继承 5.虚拟继承解决数据冗余和二…

小程序 前端如何用wx.request获取 access_token接口调用凭据

在微信小程序中,获取access_token通常是通过wx.request方法来实现的。以下是一个简单的示例代码: 1.获取小程序的appID 与 secret(小程序密钥) 登录之后,请点击左侧的"开发管理"==>点击"开发设置" 就可以找到 2. 在javascript 中的代码: // 定…

性能优化工具

CPU 优化的各类工具 network netperf 服务端&#xff1a; $ netserver Starting netserver with host IN(6)ADDR_ANY port 12865 and family AF_UNSPEC$ cat netperf.sh #!/bin/bash count$1 for ((i1;i<count;i)) doecho "Instance:$i-------"# 下方命令可以…

算法刷题记录2

4.图 4.1.被围绕的区域 思路&#xff1a;图中只有与边界上联通的O才不算是被X包围。因此本题就是从边界上的O开始递归&#xff0c;找与边界O联通的O&#xff0c;并标记为#&#xff08;代表已遍历&#xff09;&#xff0c;最后图中剩下的O就是&#xff1a;被X包围的O。图中所有…

温湿度传感器(DHT11)以及光照强度传感器(BH1750)的使用

前言 对于一些单片机类的环境检测或者智能家居小项目中&#xff0c;温湿度传感器&#xff08;DHT11&#xff09;以及光照强度传感器&#xff08;BH1750&#xff09;往往是必不可少的两个外设&#xff0c;下面我们来剖析这两个外设的原理&#xff0c;以及使用。 1. 温湿度传感…

嵌入式4-18

做一个简单数据库终端操作系统 #include <myhead.h> int main(int argc, const char *argv[]) {int id;char name[16];float score;sqlite3 *pNULL;if(sqlite3_open("./my.db",&p)!SQLITE_OK){printf("sqlite3_open error\n");return -1;} …

python中中英文打印对齐解决方案

在python中&#xff0c;有时候会出现中英文混合输出的情形&#xff0c;但是由于中文默认是全角格式&#xff08;一个中文字符占用两个字符宽度&#xff09;&#xff0c;这会对python原生的print函数带来一些障碍。尤其是用户用print对齐输出的时候&#xff0c;这种差异会导致文…

顺序表链表经典算法题

1.链表反转 typedef struct ListNode listnode; struct ListNode* reverseList(struct ListNode* head) {if(head NULL){return head;}listnode* p1 NULL;listnode* p2 head;listnode* p3 head->next;while(p2){p2->next p1;p1 p2;p2 p3;if(p3)p3 p3->next;}…

ASP.NET MVC企业级程序设计 (商品管理:小计,总计,删除,排序)

目录 效果图 实现过程 1创建数据库 2创建项目文件 3创建控制器&#xff0c;右键添加&#xff0c;控制器 ​编辑 注意这里要写Home​编辑 创建成功 数据模型创建过程之前作品有具体过程​编辑 4创建DAL 5创建BLL 6创建视图&#xff0c;右键添加视图 ​编辑 7HomeCont…

ST-GCN模型详解(+openpose)

ST-GCN模型详解&#xff08;openpose&#xff09; 一、什么是ST-GCN呢 基于骨架的动作识别&#xff08;Skeleton-Based Action Recognition&#xff09;主要任务是从一系列时间连续的骨骼关键点&#xff08;2D/3D&#xff09;中识别出正在执行的动作。因为牵涉到骨骼框架这种…

智慧公厕解决方案易集成好使用的智能硬件

在现代城市建设中&#xff0c;智慧公厕的需求日益增长。为了提供更好的用户体验和更高效的管理&#xff0c;易集成、好使用的智能硬件成为智慧公厕解决方案的关键组成部分。 1. 蹲位有人无人感应器&#xff1a;是用于检测厕位有人无人的设备&#xff0c;根据现场不同的安装条件…

Flask前端页面文本框展示后端变量,路由函数内外两类

一、外&#xff01;路由函数外的前后端数据传输 Flask后端 ↓ 首先导入包&#xff0c;需要使用 后端&#xff1a;flask_socketio来进行路由外的数据传输&#xff0c; from flask_socketio import SocketIO, emit 前端&#xff1a;还有HTML头文件的设置。 <!DOCTYPE …

DevOps是什么?

DevOps是一系列实践、工具和文化理念的组合&#xff0c;旨在自动化并整合软件开发和信息技术运维团队之间的流程。以下是DevOps的几个关键点&#xff1a; 沟通与协作&#xff1a;DevOps强调开发和运维团队之间的沟通与合作&#xff0c;通过改善这两个部门间的协作关系&#xff…

使用clickhouse-backup备份和恢复数据

作者&#xff1a;俊达 介绍 clickhouse-backup是altinity提供的一个clickhouse数据库备份和恢复的工具&#xff0c;开源项目地址&#xff1a;https://github.com/Altinity/clickhouse-backup 功能上能满足日常数据库备份恢复的需求&#xff1a; 支持单表/全库备份支持备份上…