目录
一、模板匹配
模板匹配原理
1、单模板之间的匹配
(1)读取并显示待匹配的图片和模板图片
(2)模板匹配并绘制匹配位置的外接矩形
(3)显示最终的效果
2、模板与多个对象匹配,仅匹配当前的模板
(1)读取并显示待匹配的图片和模板灰度图片
(2) 模板匹配
(3)设置阈值
3、匹配相同模板的全角度
(1)读取并显示待匹配的图片和模板灰度图片,旋转模板得到所有的能匹配到的模板。
(2)模板匹配并绘制外接矩形
二、打包与np.where()函数
1、np.where()函数
(1) 作为条件选择器(类似三元表达式)
(2) 作为条件索引获取器(省略 x 和 y)
2、打包与解包
(1)打包
(2)解包
3、反转列表
三、图像的旋转
1、使用numpy方法实现旋转
(1)顺时针旋转90度
(2)逆时针旋转90度
2、使用opencv的方法实现图像旋转
(1)顺时针旋转90度
(2)逆时针旋转90度
(3)旋转180度
一、模板匹配
模板匹配是一种用于查找与模板图像(补丁)匹配(相似)的图像区域的技术。
为了识别匹配区域,我们必须通过滑动来将模板图像与源图像进行比较:
一次移动一个像素(从左到右,从上到下)。在每个位置,都会计算一个度量(度量计算公式),以便它表示该位置的匹配“好”或“坏”程度
模板匹配原理
匹配原理:模板从图片的左上角逐一进行匹配,针对每一个匹配位置(位置坐标是模板左上角坐标),都会根据matchTemplate()函数设置的计算方法得到一个对应的得分值,不同的匹配方法数值大小的效果是不同的,找到最优的匹配结果返回。
函数API:
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 归一化相关系数匹配法,数值越大表明匹配程度越好。
返回匹配结果的矩阵,其中每个元素表示该位置与模板的匹配程度
如果想了解matchTemplate的method的具体计算方法和matchTemplate的基础知识,可以前往OpenCv的官网查看更详细的知识OpenCV: Template Matching。
1、单模板之间的匹配
可乐模板匹配代码
(1)读取并显示待匹配的图片和模板图片
kele = cv2.imread('kele.png')
template = cv2.imread('template.png')
cv2.imshow('kele',kele)
cv2.imshow('template',template)
cv2.waitKey(0)
(2)模板匹配并绘制匹配位置的外接矩形
cv2.minMaxLoc()可以获取矩阵中的最小值和最大值,以及最小值的索引号和最大值的索引号
h, w = template.shape[:2] #获取模板图片的高和宽res = cv2.matchTemplate(kele, template, cv2.TM_CCOEFF_NORMED) #返回匹配结果的矩阵,其中每个元素表示该位置与模板的匹配程度
# cv2.minMaxLoc可以获取矩阵中的最小值和最大值,以及最小值的索引号和最大值的索引号
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, (0, 255, 0), 2) # 绘制矩形
(3)显示最终的效果
cv2.imshow('kele_template', kele_template)
cv2.waitKey(0)
2、模板与多个对象匹配,仅匹配当前的模板
模板:
待匹配对象:
(1)读取并显示待匹配的图片和模板灰度图片
import cv2
import numpy as np
#(这里用到了两种方法来将彩色图片转化为灰度图)img_rgb=cv2.imread('../data/tuall.jpg')
img_gray=cv2.cvtColor(img_rgb,cv2.COLOR_BGRA2GRAY)
tuone=cv2.imread('../data/tuone.jpg',0)
(2) 模板匹配
h,w=tuone.shape[:2]
# 使用模板匹配方法进行模板匹配
res=cv2.matchTemplate(img_gray,tuone,cv2.TM_CCOEFF_NORMED)
(3)设置阈值
np.where()函数:过滤出符合条件的数值。
阈值设置原理:
在进行多对象匹配时,常常要设置阈值保证能够完全框选到对象,当阈值设置为0.9时,所有满足大于0.9的外接矩形都会被绘制出来,如果这个阈值数据设置的更小,那么符合条件的位置就越多,表现在图上的特征就是有更多的框,框的线更粗。
反转:
loc的数据,下面表示的是行和列,但是在opencv中行时用y表示,列时用x表示,所以按照x,y表示的话,下面给出的数据是,(y,x),绘制矩形时应该是x和y,所以这里要做反转。
# 设置匹配阈值
threshold=0.9
#获取匹配结果中所有符合阈值的点的坐标
loc=np.where(res>=threshold) #如果得分大于阈值,返回大于阈值的索引for pt in zip(*loc[::-1]): #反转打包#在原图上绘制矩形框cv2.rectangle(img_rgb,pt,(pt[0]+w,pt[1]+h),(0,255,0),1)cv2.imshow('1',img_rgb)
cv2.waitKey(0)
3、匹配相同模板的全角度
待匹配的图像上有很多个可以匹配上的图,但是匹配的模板需要旋转才能匹配上
将图片上的所有的图像模板都匹配上
(1)读取并显示待匹配的图片和模板灰度图片,旋转模板得到所有的能匹配到的模板。
import cv2
import numpy as npimg_rgb=cv2.imread('../data/tuall.jpg')
img_gray=cv2.cvtColor(img_rgb,cv2.COLOR_BGRA2GRAY)tuone=cv2.imread('../data/tuone.jpg',0)
tuone1=cv2.rotate(tuone,cv2.ROTATE_90_CLOCKWISE) #顺时针旋转90度
tuone2=cv2.rotate(tuone,cv2.ROTATE_90_COUNTERCLOCKWISE) #逆时针旋转90度
tuone3=cv2.rotate(tuone,cv2.ROTATE_180) #旋转180度
tuones=[tuone,tuone1,tuone2,tuone3]
(2)模板匹配并绘制外接矩形
h,w=tuone.shape[:2]
# 使用模板匹配方法进行模板匹配
for tu in tuones:res=cv2.matchTemplate(img_gray,tu,cv2.TM_CCOEFF_NORMED)# 设置匹配阈值threshold=0.9#获取匹配结果中所有符合阈值的点的坐标loc=np.where(res>=threshold)for pt in zip(*loc[::-1]):#在原图上绘制矩形框cv2.rectangle(img_rgb,pt,(pt[0]+w,pt[1]+h),(0,0,255),1)cv2.imshow('1',img_rgb)
cv2.waitKey(0)
二、打包与np.where()函数
1、np.where()函数
(1) 作为条件选择器(类似三元表达式)
语法
np.where(condition, x=None, y=None)
condition
:布尔数组或表达式,用于指定条件。x, y
(可选):当条件为True
时返回x
对应位置的元素,为False
时返回y
对应位置的元素。- 返回值:形状与
condition
相同的数组,元素来自x
或y
。
示例:
import numpy as npa = np.array([1, 2, 3, 4, 5])
# 将大于 3 的元素替换为 10,否则保持原值
result = np.where(a > 3, 10, a)
print(result) # 输出: [ 1 2 3 10 10]# 更复杂的条件(结合逻辑运算)
b = np.array([10, 20, 30, 40])
condition = (a > 2) & (b < 35) # 同时满足两个条件
result = np.where(condition, a * 2, b // 2)
print(result) # 输出: [ 2 4 6 20](仅前3个元素满足条件,最后一个不满足,取 b//2=20)
(2) 作为条件索引获取器(省略 x 和 y)
语法
np.where(condition)
- 作用:返回满足条件
condition
的元素的索引(以元组形式表示,每个元素对应数组的一个维度)。 - 返回值:元组
(ind1, ind2, ..., indn)
,其中indi
是第i
维满足条件的索引数组。
示例:
a = np.array([1, 2, 3, 4, 4, 5])
# 获取值为 4 的元素的索引
indices = np.where(a == 4)
print(indices) # 输出: (array([3, 4]),)(一维数组,索引为 3 和 4)# 二维数组示例
b = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
condition = b > 5
indices = np.where(condition)
print(indices) # 输出: (array([1, 2, 2]), array([2, 0, 1, 2])),对应行和列的索引
2、打包与解包
(1)打包
a=[1,2,3]
b=[4,5,6]# 使用zip将他们按位置进行配对
zipped=zip(a,b)
print(list(zipped))
# 输出:[(1,4),(2,5),(3,6)]
(2)解包
zip(*iterables)将多个可迭代对象(列表、元组)进行解压操作
# 假设我们已经有了一个打包好的zip对象
zipped=zip(a,b)# #使用*运算符解包,得到转置的结果
unzipped=zip(*zipped)
loc = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]# 1. loc[::-1]:反转列表
reversed_loc = loc[::-1]
print(reversed_loc) # 输出: [[7, 8, 9], [4, 5, 6], [1, 2, 3]]# 2. *reversed_loc:解包列表
# 此时相当于 zip([7, 8, 9], [4, 5, 6], [1, 2, 3])# 3. zip(*reversed_loc):使用 zip 函数进行打包
zipped = zip(*reversed_loc)
for pt in zipped:print(pt)
# 输出:
# (7, 4, 1)
# (8, 5, 2)
# (9, 6, 3)
3、反转列表
假设 loc = [(1, 2), (3, 4), (5, 6)]
(3 个坐标点):
- 反转列表:
loc[::-1] = [(5, 6), (3, 4), (1, 2)]
三、图像的旋转
1、使用numpy方法实现旋转
读取图片并重设图片大小
import cv2
import numpy as npimg=cv2.imread("../data/kele.png")
img=cv2.resize(img,dsize=None,fx=0.5,fy=0.5)cv2.imshow('yuantu',img)
(1)顺时针旋转90度
# 旋转90度,k=-1,表示顺时针旋转90度
rotated_image1=np.rot90(img,k=-1)
cv2.imshow('totated_image1',rotated_image1)
(2)逆时针旋转90度
# 旋转90度,k=1,表示逆时针旋转90度
rotated_image2=np.rot90(img,k=1)
cv2.imshow('retated_image',rotated_image2)
cv2.waitKey(0)
cv2.destroyAllWindows()
2、使用opencv的方法实现图像旋转
(1)顺时针旋转90度
rotated_image=cv2.rotate(img,cv2.ROTATE_90_CLOCKWISE) #顺时针旋转90
cv2.imshow('shun90',img)
(2)逆时针旋转90度
rotated_image1=cv2.rotate(img,cv2.ROTATE_90_COUNTERCLOCKWISE) #逆时针旋转90度
cv2.imshow('ni90',rotated_image1)
(3)旋转180度
rotated_image2=cv2.rotate(img,cv2.ROTATE_180) #旋转180度
cv2.imshow('180',rotated_image2)
cv2.waitKey(0)