图像预处理-模板匹配

        就是用模板图目标图像中不断的滑动比较,通过某种比较方法来判断是否匹配成功,找到模板图所在的位置。

- 不会边缘填充

- 类似于卷积,滑动比较,挨个比较象素。

- 返回结果res大小是:目标图大小-模板图大小+1(H-h+1,W-w+1)

一.匹配方法

res=cv2.matchTemplate(image, templ, method)

- image:原图像,这是一个灰度图像或彩色图像(在这种情况下,匹配将在每个通道上独立进行)。

- templ:模板图像,也是灰度图像或与原图像相同通道数的彩色图像。

- method:匹配方法,可以是以下之一:

  - cv2.TM_CCOEFF

  - cv2.TM_CCOEFF_NORMED

  - cv2.TM_CCORR

  - cv2.TM_CCORR_NORMED

  - cv2.TM_SQDIFF

  - cv2.TM_SQDIFF_NORMED

  - 返回值res,每个元素表示原图像中相应位置与模板图像匹配的相似度,而每个元素的位置其实就是对应匹配位置左上角元素位置。匹配方法不同,返回矩阵的值的含义也会有所区别。以下是几种常用的匹配方法及其返回值含义:

1. cv2.TM_SQDIFF 或 cv2.TM_SQDIFF_NORMED

   返回值越接近0,表示匹配程度越好。最小值对应的最佳匹配位置。

2. cv2.TM_CCORR 或 cv2.TM_CCORR_NORMED

   返回值越大,表示匹配程度越好。最大值对应的最佳匹配位置。

3. cv2.TM_CCOEFF 或 cv2.TM_CCOEFF_NORMED

   返回值越大,表示匹配程度越好。最大值对应的最佳匹配位置。

1.1 平方差匹配(cv2.TM_SQDIFF)

        以模板图与目标图所对应的像素值使用平方差公式来计算,其结果越小,代表匹配程度越高。如图:

1.2 归一化平方差匹配(cv2.TM_SQDIFF_NORMED)

与平方差匹配类似,只不过需要将值统一到0到1,计算结果越小,代表匹配程度越高。如图:

1.3 相关匹配(cv2.TM_CCORR)

使用对应像素的乘积进行匹配,乘积的结果越大其匹配程度越高。如图:

1.4 归一化相关匹配(cv2.TM_CCORR_NORMED)

与相关匹配类似,只不过是将其值统一到0到1之间,值越大,代表匹配程度越高。如图:

1.5 相关系数匹配(cv2.TM_CCOEFF)

        先计算模板目标图像均值,然后通过每个像素与均值之间的差的乘积求和来表示其匹配程度,1表示完美的匹配,-1表示最差的匹配。如图:

1.6 归一化相关系数匹配(cv2.TM_CCOEFF_NORMED)

将相关系数匹配的结果统一到0到1之间,值越接近1代表匹配程度越高。如图:

二.绘制轮廓

设定一个匹配阈值来筛选出多个匹配程度高的区域,找出数组中所有大于0.8的元素索引:

loc=np.where(array > 0.8)

获取轮廓点

zip(*loc)

- *loc 是解包操作,将 loc 中的多个数组拆开,作为单独的参数传递给 zip

- zip 将这些数组按元素一一配对,生成一个迭代器,每个元素是一个元组,表示一个坐标点

import cv2 as cv
import numpy as np# 导入目标图
img = cv.imread('../images/game.png')
# 导入模板图
temp = cv.imread('../images/temp.png')# 使用归一化相关系数匹配拿到所有匹配结果的数组
res = cv.matchTemplate(img, temp, cv.TM_CCORR_NORMED)
# 用布尔索引查找满足实际要求的匹配结果
loc = np.where(res >= 0.8)
print(loc)# 循环获取匹配结果并绘制矩形框
for pt in zip(*loc):# 因为where函数是对数组操作,先返回行索引再返回列索引,返回的坐标是(y,x)形式,所以需要反转pt = pt[::-1]# 绘制矩形框,已经知道loc中坐标是匹配区域左上角的坐标,右下角的坐标用模板图的尺寸加上左上角坐标即可cv.rectangle(img, pt, (pt[0]  + temp.shape[1], pt[1] + temp.shape[0]), (0, 0, 255), 2)cv.imshow('result', img)
cv.imshow('temp', temp)
cv.waitKey(0)
cv.destroyAllWindows()

(array([ 61, 61, 61, 61, 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 68, 68, 68, 68, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 139, 139, 139, 139, 139, 139, 139,

...

139, 140, 154, 155, 156, 157, 171, 172, 173, 174, 70, 71, 72, 87, 88, 89, 104, 105, 106, 121, 122, 123, 138, 139, 140, 155, 156, 171, 172, 173, 71, 88, 105, 122, 138, 139, 155, 156, 172, 173, 32, 30, 31, 32, 30, 31, 32, 30, 31]))

        这里有一个注意点,那就是将原图灰度化后,是不能使用(b,g,r)三通道颜色赋值的,而黑色很难看出来,所以使用白色(255,255,255)绘制矩形。

import cv2 as cv
import numpy as np# 导入目标图并灰度化
img = cv.imread('../images/game.png', cv.IMREAD_GRAYSCALE)
# 导入模板图并灰度化
temp = cv.imread('../images/temp.png', cv.IMREAD_GRAYSCALE)# 使用归一化相关系数匹配拿到所有匹配结果的数组
res = cv.matchTemplate(img, temp, cv.TM_CCORR_NORMED)
# 用布尔索引查找满足实际要求的匹配结果
loc = np.where(res >= 0.8)# 循环获取匹配结果并绘制矩形框
for pt in zip(*loc):# 因为where函数是对数组操作,先返回行索引再返回列索引,返回的坐标是(y,x)形式,所以需要反转pt = pt[::-1]# 绘制矩形框,这里使用了原来的红色框,实际显示为黑色cv.rectangle(img, pt, (pt[0] + temp.shape[1], pt[1] + temp.shape[0]), (0, 0, 255), 2)cv.imshow('result', img)
cv.imshow('temp', temp)
cv.waitKey(0)
cv.destroyAllWindows()

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【算法笔记】动态规划基础(一):dp思想、基础线性dp

目录 前言动态规划的精髓什么叫“状态”动态规划的概念动态规划的三要素动态规划的框架无后效性dfs -> 记忆化搜索 -> dp暴力写法记忆化搜索写法记忆化搜索优化了什么?怎么转化成dp?dp写法 dp其实也是图论首先先说结论:状态DAG是怎样的…

网络原理————HTTP

1,HTTP简介 我们上一期谈到了网络编程尤其是TCP和UDP,使用网络套接字来实现网络编程,上一期忘记说了,我们使用TCP的时候,我们用了线程池,这样就可以处理很多客户端而不会阻塞,那么如果客户端一…

rust编程学习(三):8大容器类型

1简介 rust标准库std::collections也提供了像C STL库中的容器&#xff0c;分为4种通用的容器&#xff0c;8种类型&#xff0c;如下表所示。 线性容器类型&#xff1a; 名称简介Vec<T>内存空间连续&#xff0c;可变长度的数组&#xff0c;类似于C中Vector<T>容器…

Javase 基础入门 —— 02 基本数据类型

本系列为笔者学习Javase的课堂笔记&#xff0c;视频资源为B站黑马程序员出品的《黑马程序员JavaAI智能辅助编程全套视频教程&#xff0c;java零基础入门到大牛一套通关》&#xff0c;章节分布参考视频教程&#xff0c;为同样学习Javase系列课程的同学们提供参考。 01 注释 单…

【 React 】重点知识总结 快速上手指南

react 是 facebook 出的一款针对视图层的库。react 使用的是单向数据流的机制 React 官方中文文档 基础 api 和语法 jsx 语法 就是在 js 中插入 html 片段 在 React 中所有的组件都是 function 组件定义 function 定义组件 就是使用 function 定义组件 任何一个 function …

C++:继承

目录 一&#xff1a;继承的概念 1.1 继承的定义 1.2 继承方式 1.3 可见性区别 公有方式 私有方式 保护方式 1.4 一般规则 二、继承中的隐藏规则 三、基类和派生类间的转换 四、派生类的默认成员函数 实现一个不能被继承的类 继承与友元 五、继承与静态成员 六、多…

十二种存储器综合对比——《器件手册--存储器》

存储器 名称 特点 用途 EEPROM 可电擦除可编程只读存储器&#xff0c;支持按字节擦除和写入操作&#xff0c;具有非易失性&#xff0c;断电后数据不丢失。 常用于存储少量需要频繁更新的数据&#xff0c;如设备配置参数、用户设置等。 NOR FLASH 支持按字节随机访问&…

C语言高频面试题——malloc 和 calloc区别

在 C 语言中&#xff0c;malloc 和 calloc 都是用于动态内存分配的函数&#xff0c;但它们在 内存初始化、参数形式 和 使用场景 上有显著区别。以下是详细的对比分析&#xff1a; 1. 函数原型 malloc void* malloc(size_t size);功能&#xff1a;分配 未初始化 的连续内存块…

Qt -对象树

博客主页&#xff1a;【夜泉_ly】 本文专栏&#xff1a;【暂无】 欢迎点赞&#x1f44d;收藏⭐关注❤️ 目录 前言构造QObject::QObjectQObjectPrivate::setParent_helper 析构提醒 #mermaid-svg-FTUpJmKG24FY3dZY {font-family:"trebuchet ms",verdana,arial,sans-s…

JavaScript与TypeScript

TypeScript 和 JavaScript 都是用于构建 Web 应用的编程语言&#xff0c;但它们有着不同的设计目标和特性。 一、JavaScript 1. 定义与特点 动态脚本语言&#xff1a;由 Brendan Eich 在 1995 年创建&#xff0c;最初用于浏览器端的交互逻辑。弱类型/动态类型&#xff1a;变量…

教育行业网络安全:守护学校终端安全,筑牢教育行业网络安全防线!

教育行业面临的终端安全问题日益突出&#xff0c;主要源于教育信息化进程的加速、终端设备多样化以及网络环境的开放性。 以下是教育行业终端安全面临的主要挑战&#xff1a; 1、设备类型复杂化 问题&#xff1a;教育机构使用的终端设备包括PC、服务器等&#xff0c;操作系统…

Linux常见指令介绍中(入门级)

1. man 在Linux中&#xff0c;man命令是用于查看命令手册页的工具&#xff0c;它可以帮助用户了解各种命令、函数、系统调用等的详细使用方法和相关信息。 用法&#xff1a;在终端中输入man加上要查询的命令或工具名称&#xff0c;例如man ls&#xff0c;就会显示ls命令的手册…