模板匹配
模板匹配原理
定义:模板匹配就是在整个图像区域发现与给定字图像匹配的最小区域
条件:需要有一个模板图像T,一个待检测的图像——源图像 I
工作方法:在待检测图像I上,从左到右,从上向下计算模板图像与重叠字图像的匹配度,匹配程度越大,两者相同的可能性越大。
函数介绍:
cv2.matchTemplate(image, templ, method, result=None, mask=None)
- 用模板图像在输入图像(大图)上滑动,并在每一个位置对模板图像和与其对应的输入图像的子区域进行比较。
- OpenCV提供了6种不同的比较方法。
- 返回的结果是一个灰度图像,每一个像素值表示了此区域与模板的匹配程度。
cv2.minMaxLoc(src, mask=None)
- 来找到其中的最小值和最大值的位置了。
- 第一个值为矩形左上角的点(位置),(w,h)为moban模板矩形的宽和高。
- 这个矩形就是找到的模板区域了。
匹配方法介绍
TM_SQDIFF
(方差匹配法)
TM_SQDIFF_NORMED
(归一化方差匹配法)
TM_CCORR
(相关性匹配法)
TM_CCORR_NORMED
(归一化的相关性匹配法)
TM_CCOEFF
(相关系数匹配法)
- 约束
- 约束
TM_CCOEFF_NORMED
(归一化相关系数匹配法)
单对象模板匹配
import cv2
import numpy as np
from matplotlib import pyplot as plt
plt.close('all')
src = cv2.imread('messi5_s.png', 1)
if src is None:
print('Could not open or find the image')
exit(0)
print(src.shape)
img2 = src.copy()
template = cv2.imread('messi5_temp.png', 1)
if template is None:
print('Could not open or find the template')
exit(0)
print(template.shape)
h, w = template.shape[:2]
print("w = %d, h = %d" % (w, h))
methods = ['cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED', 'cv2.TM_CCORR', 'cv2.TM_CCORR_NORMED',
'cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED']
for meth in methods:
img = img2.copy()
# eval语句用来计算存储在字符串中的有效python表达式
method = eval(meth)
# 使用模板匹配
res = cv2.matchTemplate(img, template, method)
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(res)
# 使用不同方法的比较,对结果的解释不同
if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
topLeft = minLoc
else:
topLeft = maxLoc
bottomRight = (topLeft[0] + w, topLeft[1] + h)
cv2.rectangle(img, topLeft, bottomRight, (0, 0, 255), 5)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.subplot(121), plt.imshow(res, cmap='gray')
plt.title('Matching res'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img, cmap='gray')
plt.title('Deteced point'), plt.xticks([]), plt.yticks([])
plt.suptitle(meth)
plt.show()
效果
- 方差匹配法,归一化方差匹配法
- 相关性匹配法,归一化的相关性匹配法
- 相关系数匹配法,归一化相关系数匹配法
多对象模板匹配
使用阈值找出匹配完成的对象所在的位置
np.where()
:获取对象的具体位置
import cv2
import numpy as np
from matplotlib import pyplot as plt
plt.close('all')
src = cv2.imread('Match_T_1.png', 1)
if src is None:
print('Could not open or find the image')
exit(0)
print(src.shape)
cv2.imshow("ori", src)
imgGray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
template = cv2.imread('Match_T_2.png', 0)
if template is None:
print('Could not open or find the template')
exit(0)
print(template.shape)
h, w = template.shape[:2]
print("w = %d, h = %d" % (w, h))
res = cv2.matchTemplate(imgGray, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):
cv2.rectangle(src, pt, (pt[0] + w, pt[1] + h), (255, 0, 0), 2)
cv2.imshow('deteced points', src)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果
附录
cv2.matchTemplate()
函数说明
def matchTemplate(image, templ, method, result=None, mask=None): # real signature unknown; restored from __doc__
"""
matchTemplate(image, templ, method[, result[, mask]]) -> result
. @brief Compares a template against overlapped image regions.
.
. The function slides through image , compares the overlapped patches of size \f$w \times h\f$ against
. templ using the specified method and stores the comparison results in result . Here are the formulae
. for the available comparison methods ( \f$I\f$ denotes image, \f$T\f$ template, \f$R\f$ result ). The summation
. is done over template and/or the image patch: \f$x' = 0...w-1, y' = 0...h-1\f$
.
. After the function finishes the comparison, the best matches can be found as global minimums (when
. #TM_SQDIFF was used) or maximums (when #TM_CCORR or #TM_CCOEFF was used) using the
. #minMaxLoc function. In case of a color image, template summation in the numerator and each sum in
. the denominator is done over all of the channels and separate mean values are used for each channel.
. That is, the function can take a color template and a color image. The result will still be a
. single-channel image, which is easier to analyze.
.
. @param image Image where the search is running. It must be 8-bit or 32-bit floating-point.
. @param templ Searched template. It must be not greater than the source image and have the same
. data type.
. @param result Map of comparison results. It must be single-channel 32-bit floating-point. If image
. is \f$W \times H\f$ and templ is \f$w \times h\f$ , then result is \f$(W-w+1) \times (H-h+1)\f$ .
. @param method Parameter specifying the comparison method, see #TemplateMatchModes
. @param mask Mask of searched template. It must have the same datatype and size with templ. It is
. not set by default. Currently, only the #TM_SQDIFF and #TM_CCORR_NORMED methods are supported.
"""
pass
cv2.minMaxLoc()
函数说明
def minMaxLoc(src, mask=None): # real signature unknown; restored from __doc__
"""
minMaxLoc(src[, mask]) -> minVal, maxVal, minLoc, maxLoc
. @brief Finds the global minimum and maximum in an array.
.
. The function cv::minMaxLoc finds the minimum and maximum element values and their positions. The
. extremums are searched across the whole array or, if mask is not an empty array, in the specified
. array region.
.
. The function do not work with multi-channel arrays. If you need to find minimum or maximum
. elements across all the channels, use Mat::reshape first to reinterpret the array as
. single-channel. Or you may extract the particular channel using either extractImageCOI , or
. mixChannels , or split .
. @param src input single-channel array.
. @param minVal pointer to the returned minimum value; NULL is used if not required.
. @param maxVal pointer to the returned maximum value; NULL is used if not required.
. @param minLoc pointer to the returned minimum location (in 2D case); NULL is used if not required.
. @param maxLoc pointer to the returned maximum location (in 2D case); NULL is used if not required.
. @param mask optional mask used to select a sub-array.
. @sa max, min, compare, inRange, extractImageCOI, mixChannels, split, Mat::reshape
"""
pass
使用OpenCV提供的6种算法模板匹配算法种,哪一种的算法效果相对不是很理想呢?
答案:TM_CCORR
简答题
自己找一张或者使用课程提供的图片,进行模板的匹配。如果是自己找的照片,需要制作好模板哦。
import cv2
import numpy as np
from matplotlib import pyplot as plt
plt.close('all')
src = cv2.imread('cxk.jpg', 1)
if src is None:
print('Could not open or find the image')
exit(0)
print(src.shape)
cv2.imshow("ori", src)
imgGray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
template = cv2.imread('cxk_temp.png', 0)
if template is None:
print('Could not open or find the template')
exit(0)
print(template.shape)
h, w = template.shape[:2]
print("w = %d, h = %d" % (w, h))
res = cv2.matchTemplate(imgGray, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):
cv2.rectangle(src, pt, (pt[0] + w, pt[1] + h), (255, 0, 0), 2)
cv2.imwrite('match_temp_res.png', src)
cv2.imshow('deteced points', src)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果: