图片识别
模板匹配
基础语法
cv2.matchTemplate(img:imgArray, template_img:imgArray, method:int) -> Array
# 所有模版匹配用到的flag
list_flag(TM_)
六种匹配模式
内置的method(匹配方法)分为6种,每种都有不同的适用场景
# cv2.TM_x
methods = {
"TM_SQDIFF":0,
"TM_SQDIFF_NORMED":1,
"TM_CCORR":2,
"TM_CCORR_NORMED":3,
"TM_CCOEFF":4,
"TM_CCOEFF_NORMED":5,
}
cv2.TM_SQDIFF | 0 - 平方差匹配法:
该方法使用平方差进行匹配,因此最佳的匹配结果在结果为0处,值越大匹配结果越差。
计算平方不同,计算出来的值越小,越相关
计算模板与目标图像的方差,由于是像素值差值的平方的和,所以值越小匹配程度越高;
结果获取
# 平方差匹配法 值越小越相关
method = cv2.TM_SQDIFF
res = cv2.matchTemplate(img_target, img_template, method)
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(res)
cv2.TM_SQDIFF_NORMED | 1:
- 该方法使用归一化的平方差进行匹配,最佳匹配也在结果为0处。
- 计算归一化相关性 ,计算出来的值越接近1,越相关
- 范化的cv::TM_SQDIFF,取值为0-1之间,完美匹配返回值为0
cv2.TM_CCORR | 2 - 相关性匹配方法:
相关性匹配方法,该方法使用源图像与模板图像的卷积结果进行匹配,因此,最佳匹配位置在值最大处,值越小匹配结果越差。
计算相关性,计算出来的值越大,越相关
使用dot product计算匹配度(不清楚怎么计算dot product,没看过代码),越高匹配度就好;
结果获取
# 相关性匹配方法,值越大越相关
method = cv2.TM_CCORR
res = cv2.matchTemplate(img_target, img_template, method)
cv2.TM_CCORR_NORMED | 3:
- 计算归一化相关性,计算出来的值越大,越相关
- 范化的cv::TM_CCORR,0-1之间
- 归一化的相关性匹配方法,与相关性匹配方法类似,最佳匹配位置也是在值最大处。
cv2.TM_CCOEFF | 4 - 相关系数匹配法
- 相关性匹配方法,该方法使用源图像与模板图像的卷积结果进行匹配,因此,最佳匹配位置在值最大处,值越小匹配结果越差。
- 计算相关系数,计算出来的值越大,越相关
- 采用模板与目标图像像素与各自图像的平均值计算dot product,正值越大匹配度越高,负值越大图像的区别越大,但如果图像没有明显的特征(即图像中的像素值与平均值接近)则返回值越接近0
cv2.TM_CCOEFF_NORMED | 5:
计算归一化相关系数,计算出来的值越接近1,越相关,既越大
范化的cv::TM_CCOEFF,-1 ~ 1之间
归一化的相关性匹配方法,与相关性匹配方法类似,最佳匹配位置也是在值最大处。归一化的相关性匹配方法,与相关性匹配方法类似,最佳匹配位置也是在值最大处。
结果提取:
# 相关系数匹配法
method = cv2.TM_CCOEFF_NORMED
res = cv2.matchTemplate(img_target, img_template, method)
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(res)
print(maxVal, maxLoc)
注意:
cv2
内置的匹配模式尽量采用带归一化的方式,结果可靠性最高
- 使用场景
- 首先应尽量使用归一化的方法进行匹配
- 有明确目标模板的情况下,选用
TM_CCORR_NORMED | 5
方法效果可能较好, - 没有明确目标模板的情况下,可以选用
from typing import *
Img = NewType('cv2.imread', list)
TM_FLAG = NewType("cv2.TM_CCOEFF|cv2.TM_CCOEFF_NORMED|cv2.TM_CCORR|cv2.TM_CCORR_NORMED|cv2.TM_SQDIFF|cv2.TM_SQDIFF_NORMED", int)
Region = NewType('(startX, startY, endX, endY)', Tuple[int])
def img_match(img_target:Img, img_template:Img, method:TM_FLAG=1, region:Optional[Region]=None, sim:float=0.8) -> bool:
res = cv2.matchTemplate(img_target, img_template, method)
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(res)
max_res:bool = maxVal > sim
min_res:bool = (1 - minVal) > sim
match method:
case 0 | "TM_SQDIFF" :
if minVal == 0 or maxVal == 0:return True
return min_res
case 1 | "TM_SQDIFF_NORMED":
return max_res
case 2 | "TM_CCORR":
return max_res
case 3 | "TM_CCORR_NORMED":
return max_res
case 4 | "TM_CCOEFF":
return max_res
case 5 | "TM_CCOEFF_NORMED":
return max_res
case _:
return False