python数字图像处理基础(六)——模板匹配、直方图

目录

    • 模板匹配
      • 概念
      • 单对象模板匹配
      • 多对象模板匹配
    • 直方图
      • 1.查找直方图
      • 2.绘制直方图
      • 3.掩膜的应用

模板匹配

概念

模板匹配和卷积原理很像,模板在原图像上从原点开始滑动,计算模板与图像被模板覆盖的地方的差别程度,这个差别程度的计算方法在opencv里有6种,然后将每次计算的结果放入一个矩阵里,作为结果输出。假如原图是AxB大小,而模板是axb大小,则输出结果的矩阵是(A-a+1)x(B-b+1) (通过.shape查看验证)

匹配算法method
平方差匹配法:计算平方不同,计算出来的值越小,越相关cv2.TM_SQDIFF
归一化平方差匹配法:计算归一化平方不同,计算出来的值越接近0,越相关cv2.TM_SQDIFF_NORMED
相关匹配法:计算相关性,计算出来的值越大,越相关cv2.TM_CCORR
归一化相关匹配法:计算归一化相关性,计算出来的值越接近1,越相关cv2.TM_CCORR_NORMED
相关系数匹配法:计算相关系数,计算出来的值越大,越相关cv2.TM_CCOEFF
归一化相关系数匹配法:计算归一化相关系数,计算出来的值越接近1,越相关cv2.TM_CCOEFF_NORMED

通常来讲,随着从简单测量方法(平方差)到更复杂的测量方法(相关系数法),我们可以获得越来越准确的匹配。然而这同时也会以越来越大的计算量为代价。对于选取何种方法,针对不同的匹配情况进行对此分析比较,选取更适合自己应用场景同时兼顾速度和精度的最佳方案。一般使用归一化的。

cv2.minMaxLoc()函数会返回四个值——最小值及其位置、最大值及其位置(这里的位置是匹配框左上角顶点的坐标位置)

import cv2

img = cv2.imread('./image/img1.jpg', 0)
template = cv2.imread('./image/template.png', 0)
h, w = template.shape[:2]
# print(img.shape)
# print(template.shape)
# (225, 203)
# (82, 100)
res = cv2.matchTemplate(img, template, cv2.TM_SQDIFF)
# print(res.shape) --> (144, 104)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

理解:利用这个函数找最大值最小值,以及从六种中选择出的匹配算法,两者结合,得到最匹配的点的坐标。由于这个点是匹配框的左上顶点,我们再求得模板图像的长和宽,有左上顶点、长、宽,即可得到与模板匹配的图像

单对象模板匹配

import cv2
from matplotlib import pyplot as plt

img = cv2.imread('./image/img1.jpg', 0)

template = cv2.imread('./image/template.png', 0)
h, w = template.shape[:2] # 切片,取shape的前两个值代表模板长宽,不取第三个值(代表BGR)

# 六种匹配方法
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
            'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']

for meth in methods:
    img2 = img.copy()  # 不然原图会被覆盖
    # eval 语句用来计算存储在字符串中的有效 Python 表达式
    method = eval(meth)
    # 模板匹配
    res = cv2.matchTemplate(img, template, method)
    # 寻找最值
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
    # 使用不同的比较方法,对结果的解释不同

    # 如果是平方差匹配或归一化平方差匹配,取最小值
    if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
        top_left = min_loc
    else:
        top_left = max_loc
    bottom_right = (top_left[0] + w, top_left[1] + h)

    # 画矩形
    cv2.rectangle(img, top_left, bottom_right, 255, 2)

    # 展示
    plt.subplot(121), plt.imshow(res, cmap='gray')
    plt.title('Matching Result'), plt.xticks([]), plt.yticks([])  # 隐藏坐标轴
    plt.subplot(122), plt.imshow(img, cmap='gray')
    plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
    plt.suptitle(meth)
    plt.show()

注意到其中有一个匹配算法的结果匹配的不好

多对象模板匹配

import cv2
import numpy as np

img_rgb = cv2.imread('./image/img1.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('./image/template.png', 0)
h, w = template.shape[:2]

# 选择的匹配算法是相关系数法
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.4
# 取匹配程度大于%40的坐标
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):  # *号表示可选参数
    bottom_right = (pt[0] + w, pt[1] + h)
    # 画矩形
    cv2.rectangle(img_rgb, pt, bottom_right, (0, 0, 255), 2)
cv2.imshow("img", img_rgb)
cv2.waitKey(0)


直方图

  • 什么是直方图?你可以将直方图视为图形或绘图,从而为你提供有关图像强度分布的总体思路。它是X轴上的像素值(范围从0到255,并非总是)和Y轴上图像中相应像素数量的绘图。

  • 一些直方图相关的术语

    BINS:上面的直方图显示每个像素值的像素数量,即从0到255。也就是说,你需要256个值来显示上述的直方图。但是请考虑,如果您不需要分别查找所有像素值的像素数量,但是像素值的间隔中的像素数量是多少?例如,你需要找到位于10到15之间,然后是16到31,…,240到255之间的像素值。你只需要16个值来表示直方图。这就是OpenCV教程中关于直方图的例子。

    因此,你所做的只是将整个直方图拆分成16个子部分,每个子部分的值是其中所有像素数的总和。这个子部分被称为“BIN”。在第一种情况下,BINS中的每组的像素数目都是256,而在第二种情况下,它仅为16个。在OpenCV中,BINS由术语hitSize表示。

    DIMS:这是我们收集数据的参数数量。在这种情况下,我们只收集强度值的数量,所以这里是1.

    RANGE:这是你要测量的强度值的范围。通常,它是[0,256],即所有强度值。

1.查找直方图

1)OpenCV中的直方图计算

我们使用cv2.calcHist()函数来查找直方图。让我们熟悉这个函数及其参数:

Cv2.calcHist(image,channels,mask,hitSize,range[,hist[,accumulate]])

  • image(图像):它是类型为uint8或者float32的源图像。应该用方括号给出,即“[img]”.
  • .Channels(通道):它也是被放在方括号内。它是我们计算直方图的通道的索引。例如,如果输入是灰度图像,则其值为[0].对于彩色图像,可以分别通过[0],[1]或者[2]计算蓝色、绿色或者红色通道的直方图 。
  • Mask(掩膜):要查找完整图像的直方图,它会显示为“无”。但是,如果你想找到特定区域的图像直方图,你必须为此创建一个蒙版图像并将其作为蒙版
  • histSize:这代表我们的BIN数量。需要用方括号给出。对于全尺寸,我们传入[256].
  • Range(范围):通常情况下,它是[0,256].

img = cv2.imread('1.jpg', 0)
hist = cv2.calcHist([img], [0], None, [256], [0, 256])
#hist是一个256*1的数组,每个值对应于图像中具有相应像素值的像素数
print(hist)

2)Numpy中的直方图计算

img = cv2.imread('1.jpg', 0)

hist, bins = np.histogram(img.ravel(), 256, [0, 256])

print("hist", hist)

print("bins", bins)

hist与我们之前计算的相同。但是bins将有257个元素因为Numpy计算bins为0-0.99,1-1.99,2-2.99等。为了表示这一点,他们还在bins的末尾加上256.但我们不需要高达256,255就够了。OpenCV函数比np.histogram()要快(大约40倍)。所以坚持使用OpenCV函数。

2.绘制直方图

两种方法:

Ø Shortway:使用matplotlib绘图函数

Ø Long way:使用OpenCV绘图函数

1)使用Matplotlib(主要)

Matplotlib带有一个直方图绘制函数:matplot.pyplot.hist()

它直接找到直方图并绘制它.不需要使用calcHist()或者np.histogram()函数来查找直方图。

`import cv2`
`from matplotlib import pyplot as plt`
`img = cv2.imread('home.jpg',0)`
`plt.hist(img.ravel(),256,[0,256]); plt.show()`

或者你可以使用matplotlib的正常绘制方式,这对BGR绘制是有利的.为此,你首先需要查找直方图数据。

`import cv2`
`from matplotlib import pyplot as plt`

`img = cv2.imread('8.jpg')`
`color = ('b', 'g', 'r')`
`for i, col in enumerate(color): # 枚举`
    `histr = cv2.calcHist([img], [i], None, [256], [0, 256])`
    `plt.plot(histr, color=col)`
    `plt.xlim([0, 256])`
`plt.show()`

2)使用OpenCV

用OpenCV的话,你可以将直方图的值与其二进制一起调整为x,y坐标,以便你可以使用cv2.line()或cv2.polyline()函数绘制它以生成与上面相同的图像。这已经在OpenCV-Python2官方demo中可用。

3.掩膜的应用

我们使用cv2.calcHist()来查找完整图像的直方图。如果你想查找图像中某些区域的直方图,该怎么办?只需在想查找直方图的区域创建一个带白色的蒙版图像,否则就是黑色。然后将它作为掩膜。

例子:

img = cv2.imread('2.jpg')`

#创建一个掩膜`

mask = np.zeros(img.shape[:2], dtype='uint8')`
mask[100:300, 100:400] = 255`
masked_img = cv2.bitwise_and(img, img, mask=mask)`

#计算有掩膜和没有掩膜时的直方图`

#只需改变第三个参数`

hist_full = cv2.calcHist([img], [0], None, [256], [0, 256])`
hist_mask = cv2.calcHist([img], [0], mask, [256], [0, 256])`

plt.subplot(221), plt.imshow(img, 'gray'), plt.title("origianl")`
plt.subplot(222), plt.imshow(mask, 'gray'), plt.title('mask')`
plt.subplot(223), plt.imshow(masked_img, 'gray'), plt.title('masked_img')`
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask), plt.title('hist')`

plt.xlim([0, 256])`

plt.show()`

解释代码:

  • mask = np.zeros(img.shape[:2], dtype=‘uint8’)

    用法:zeros(shape, dtype=float, order=‘C’)

    返回:返回来一个给定形状和类型的用0填充的数组;

    参数:shape:形状

    ​ dtype:数据类型,可选参数,默认np.float64

    ​ order:可选参数,c代表与c语言类似,行优先;F代表列优先

  • plt.title(‘hist’)

    将该figure对象的表头名命名为hist

  • plt.subplot(221)

    subplot()函数则用来实现,在一个大图中,出现多个小的子图。

    处理哪个figure,则选择哪个figure,再进行画图。

    221表示是一个两行两列布局的图,且现在画的是右上角的小图

    同理,236表示画的2行3列布局的最右下角的图

  • hist_full = cv2.calcHist([img], [0], None, [256], [0, 256])

    plt.plot(hist_full)

    hist_full是一个shape为(256,1)的数组,表示0-255每个像素值对应的像素个数,下标即为相应的像素值

    plt.plot()一般需要输入x,y,若只输入一个参数,那么默认x为range(n),n为y的长度,在这里即表示图像x轴为0-255像素点灰度值,y轴为对应灰度值的像素点数量

    一个plt.plot()代表该图像中的一条图线

  • plt.imshow()

    负责对图像进行处理,并显示其格式,但是不能显示。

  • plt.show()

    显示图像

  • plt.xlim([0,256])

    x轴上的值的取值范围为0-256


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

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

相关文章

基于WEKWS模型的语音唤醒关键词识别

一、模型描述 1.1 论文解读 本文所使用的模型网络结构继承自论文《Compact Feedforward Sequential Memory Networks for Small-footprint Keyword Spotting》,文中研究了将低秩矩阵分解与传统FSMN相结合的紧凑型前馈顺序记忆网络(cFSMN)用…

中北数据结构2023真题

雪雾: 设计一个算法&#xff0c;将一个节点值为自然数的单列表拆分成两个单列表&#xff0c;原表中值为偶数的节点保留&#xff0c;而值为奇数的节点&#xff0c;按他们在原表的相对次序组成一个新的单列表 #include <stdio.h> #include <stdlib.h>typedef struct…

一文教你V3+TS(保姆级教程)

TS 与 JS 的区别 基础类型 ts 的常用类型 ts 的常用基础类型分为两种&#xff1a; js 已有类型 原始类型&#xff1a;number/string/boolean/null/undefined/symbol 对象类型&#xff1a;object&#xff08;包括&#xff0c;数组、对象、函数等对象&#xff09; 每次编写前…

oracle11g的闪回技术-闪回表-时间戳

--数据库闪回表 --1创建表&#xff08;登录模式system&#xff09; CREATE table dept2 as select * from dept;--此语句如果加上where条件可用于工作中数据的临时备份 select * from dept2;--查询新建表信息 --进入sql>set time on 通过时间点闪回 记录弹出的时间点&#…

软件测试|使用Python生成PDF文件

简介 PDF&#xff08;Portable Document Format&#xff09;是一种常用的文档格式&#xff0c;具有跨平台兼容性、保真性、安全性和交互性等特点。我们日常生活工作中的合同、报告、论文等通常都采用PDF格式&#xff0c;以确保文档在不同的操作系统&#xff08;例如 Windows、…

腾讯云轻量化应用服务器_轻量化应用服务器_轻量化私有云

腾讯云轻量应用服务器开箱即用、运维简单的轻量级云服务器&#xff0c;CPU内存带宽配置高并且价格特别便宜&#xff0c;大带宽&#xff0c;但是限制月流量&#xff0c;轻量2核2G3M带宽62元一年、2核2G4M优惠价118元一年&#xff0c;540元三年、2核4G5M带宽218元一年&#xff0c…

【不用找素材】ECS 游戏Demo制作教程(1) 1.15

一、项目设置 版本&#xff1a;2022.2.0f1 &#xff08;版本太低的话会安装不了ECS插件&#xff09; 模板选择3D URP 进来后移除URP&#xff08;因为并不是真的需要&#xff0c;但也不是完全不需要&#xff09; Name: com.unity.entities.graphics Version: 1.0.0-exp.8 点击…

推荐 10 个基于 Stable Diffusion 的 AI 绘画网站

在当今快速发展的人工智能领域&#xff0c;AI 绘画已经成为一个不可忽视的趋势。特别是基于 Stable Diffusion 技术的 AI 绘画工具&#xff0c;以其强大的图像生成能力和丰富的创意潜力吸引了众多艺术家和设计师的目光。对于那些热爱艺术创作&#xff0c;但又缺乏专业绘画技巧的…

三、MySQL实例初始化、设置、服务启动关闭、环境变量配置、客户端登入(一篇足以从白走到黑)

目录 1、选择安装的电脑类型、设置端口号 2、选择mysql账号密码加密规则 3、设置root账户密码 4、设置mysql服务名和服务启动策略 5、执行设置&#xff08;初始化mysql实例&#xff09; 6、完成设置 7、MySQL数据库服务的启动和停止 方式一&#xff1a;图形化方式 方式…

《Python数据分析技术栈》第01章 03 Python基础(Python Basics)

03 Python基础&#xff08;Python Basics&#xff09; 《Python数据分析技术栈》第01章 03 Python基础&#xff08;Python Basics&#xff09; In this section, we get familiar with the syntax of Python, commenting, conditional statements, loops, and functions. 在…

LRU Cache

文章目录 1. 什么是LRU Cache2. LRU Cache的实现3. LRU Cache的OJ题目分析AC代码 1. 什么是LRU Cache LRU是Least Recently Used的缩写&#xff0c;意思是最近最少使用&#xff0c;它是一种Cache替换算法。 什么是Cache&#xff1f; 狭义的Cache指的是位于CPU和主存间的快速RAM…

linux 更新镜像源

打开终端&#xff0c;备份一下旧的 源 文件&#xff0c;以防万一 cd /etc/apt/ ls sudo cp sources.list sources.list.bak ls然后打开清华大学开源软件镜像站 搜索一下你的linux发行版本&#xff0c;我这里是ubuntu发行版本 点击这个上面图中的问号 查看一下自己的版本号&a…

【控制篇 / 分流】(7.4) ❀ 03. 对国内和国际IP网段访问进行分流 ❀ FortiGate 防火墙

【简介】公司有两条宽带用来上网&#xff0c;一条电信&#xff0c;一条IPLS国际专线&#xff0c;由于IPLS仅有2M&#xff0c;且价格昂贵&#xff0c;领导要求&#xff0c;访问国内IP走电信&#xff0c;国际IP走IPLS&#xff0c;那么应该怎么做&#xff1f; 国内IP地址组 我们已…

KubeSphere 开源社区 2023 年度回顾与致谢

2023 年结束了&#xff0c;让我们再一次一起回顾一下 KubeSphere 开源社区在过去一年的变化。更重要的是&#xff0c;本篇文章将会对 2023 年所有参与过 KubeSphere 社区贡献的成员致以最诚挚的感谢&#xff0c;快来看看有没有你&#xff01; 开源项目发展情况 2023 年&#…

黑马 Javaweb - MySQL 精华篇

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 知…

查询数据库表字段具有某些特征的表

目录 引言举例总结 引言 当我们把一个项目做完以后&#xff0c;客户要求我们把系统中所有的电话&#xff0c;证件号等进行加密处理时&#xff0c;我们难道要一个表一表去查看那些字段是电话和证件号码吗&#xff1f; 这种办法有点费劲&#xff0c;下面我们来探索如何找到想要的…

mybatis分页、延迟加载、立即加载、一级缓存、二级缓存

mybatis分页、延迟加载、立即加载、一级缓存、二级缓存 分页延迟加载和立即加载缓存一级缓存二级缓存 分页 分类&#xff1a; 使用Limit&#xff0c;来进行分页&#xff1b;物理分页使用RowBounds集合来保存分页需要数据&#xff0c;来进行分页;逻辑分页&#xff1b;本质是全…

Air780E开发板开发环境搭建

开发板原理图 开发软件 下载网站 https://luatos.com/luatools/download/last 使用教程 烧录教程 - LuatOS 文档 开发流程 首先下载最新版本的Luatools 然后新建一个Luatools文件夹&#xff0c;将下载的exe文件放入其中后&#xff0c;再打开exe文件&#xff08;会生成目…

《WebKit 技术内幕》之四(2): 资源加载和网络栈

2.Chromium 多进程资源加载 2,1 多进程 资源的实际加载在各个WebKit移植中有不同的实现。Chromium采用的多进程的资源加载机制。 ResourceHandle 类之下的部分是不同移植对获取资源的不同实现&#xff0c;Chromium 中是 多进程资源加载 。主要是多个Renderer进程和Browser进程…

SystemVerilog验证测试平台

2.2定宽数组 相比于 Verilog1995中的一维定宽数组, System verilog提供了更加多样的数组类型,功能上也大大增强。 2.2.1定宽数组的声明和初始化 Verilog要求在声明中必须给出数组的上下界。因为几乎所有数组都使用0作为索引下界,所以 System verilog允许只给出数组宽度的便捷声…