在Python中使用OpenCV进行模板匹配

模板匹配 是一种查找图像中与面片(模板)相似的区域的技术。 补丁是具有特定特征的小图像。模板匹配的目标是在图像中找到补丁/模板。 要找到它,用户必须提供两个输入图像: 源图像 –在中查找模板的图像,以及 模板图像(T) –要在源图像中找到的图像。

null
  • 它基本上是一种在较大图像中搜索和查找模板图像位置的方法。
  • 这里的想法是找到与我们提供的模板匹配的图像的相同区域,给出一个阈值
    • 阈值取决于我们想要在源图像中检测模板的精度。
    • 例如,如果我们正在应用人脸识别,并且我们想要检测一个人的眼睛,我们可以提供一个眼睛的随机图像作为模板,并搜索源(一个人的脸)。
    • 在这种情况下,由于“眼睛”在人与人之间的差异很大,即使我们将阈值设置为50%(0.5),眼睛也会被检测到。
    • 如果要搜索几乎相同的模板,则应将阈值设置为高。(t>=0.8)

模板匹配是如何工作的?

  • 模板图像只是在输入图像上滑动(如二维卷积)
  • 比较了模板图像下输入图像的模板和补丁。
  • 将所得结果与阈值进行了比较。
  • 如果结果大于阈值,则该部分将标记为检测到。
  • 在函数cv2中。matchTemplate(img_gray,template,cv2.TM_Cceff_Normad)第一个参数是主图像,第二个参数是要匹配的模板,第三个参数是用于匹配的方法。

python

# Python program to illustrate
# template matching
import cv2
import numpy as np
# Read the main image
img_rgb = cv2.imread( 'mainimage.jpg' ).
# Convert it to grayscale
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
# Read the template
template = cv2.imread( 'template' , 0 )
# Store width and height of template in w and h
w, h = template.shape[:: - 1 ]
# Perform match operations.
res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
# Specify a threshold
threshold = 0.8
# Store the coordinates of matched area in a numpy array
loc = np.where( res > = threshold)
# Draw a rectangle around the matched region.
for pt in zip ( * loc[:: - 1 ]):
cv2.rectangle(img_rgb, pt, (pt[ 0 ] + w, pt[ 1 ] + h), ( 0 , 255 , 255 ), 2 )
# Show the final image with the matched area.
cv2.imshow( 'Detected' ,img_rgb)


模板匹配的限制:

  1. 图案引用必须保留参考图案图像(模板)的方向
  2. 因此,它不适用于模板的旋转或缩放版本,因为对象w.r.t.模板的形状/大小/剪切等变化将给出错误匹配。
  3. 该方法在计算中大型图像的模式相关图像时效率低下,因为该过程耗时。

为了避免模板和原始图像大小不同所造成的问题,我们可以使用 多路定标 。在这种情况下,仅仅因为模板的尺寸与图像中要匹配的区域的尺寸不匹配,并不意味着无法应用模板匹配。

模板匹配中的多尺度机制

多重缩放的过程如下:

  1. 以多个比例循环输入图像(即使输入图像逐渐变小)。
  2. 使用cv2应用模板匹配。matchTemplate并跟踪相关系数最大的匹配(以及相关系数最大区域的x、y坐标)。
  3. 在所有尺度上循环之后,取相关系数最大的区域作为“匹配”区域。

python

# Python program to illustrate
# multiscaling in template matching
import cv2
import numpy as np
# Read the main image
img_rgb = cv2.imread( 'mainimage.jpg' )
# Convert to grayscale
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
# Read the template
template = cv2.imread( 'template' , 0 )
# Store width and height of template in w and h
w, h = template.shape[:: - 1 ]
found = None
for scale in np.linspace( 0.2 , 1.0 , 20 )[:: - 1 ]:
# resize the image according to the scale, and keep track
# of the ratio of the resizing
resized = imutils.resize(img_gray, width = int (img_gray.shape[ 1 ] * scale))
r = img_gray.shape[ 1 ] / float (resized.shape[ 1 ])
# if the resized image is smaller than the template, then break
# from the loop
# detect edges in the resized, grayscale image and apply template
# matching to find the template in the image edged
# = cv2.Canny(resized, 50, 200) result = cv2.matchTemplate(edged, template,
# cv2.TM_CCOEFF) (_, maxVal, _, maxLoc) = cv2.minMaxLoc(result)
# if we have found a new maximum correlation value, then update
# the found variable if found is None or maxVal > found[0]:
if resized.shape[ 0 ] < h or resized.shape[ 1 ] < w:
break
found = (maxVal, maxLoc, r)
# unpack the found variable and compute the (x, y) coordinates
# of the bounding box based on the resized ratio
(_, maxLoc, r) = found
(startX, startY) = ( int (maxLoc[ 0 ] * r), int (maxLoc[ 1 ] * r))
(endX, endY) = ( int ((maxLoc[ 0 ] + tW) * r), int ((maxLoc[ 1 ] + tH) * r))
# draw a bounding box around the detected result and display the image
cv2.rectangle(image, (startX, startY), (endX, endY), ( 0 , 0 , 255 ), 2 )
cv2.imshow( "Image" , image)
cv2.waitKey( 0 )


以上代码的逐步解释:

  • 在将模板的宽度和高度存储在w和r中之后,我们初始化一个变量,该变量用于跟踪图像的区域和比例,并与最佳匹配。从这里开始,我们使用np在图像的多个尺度上循环。linspace函数。此函数接受三个参数:起始值、结束值和中间相等的块片数。在本例中,我们将从图像原始大小的100%开始,并以20%大小相等的块的方式向下扩展到原始大小的20%。
  • 然后,我们根据当前的比例调整图像大小,并计算旧宽度与新宽度的比率——正如您稍后将看到的,跟踪这个比率很重要。我们进行检查以确保输入图像大于模板匹配。如果模板更大,那么我们的cv2。matchTemplate调用将抛出一个错误,因此如果是这种情况,我们就中断循环。
  • 此时,我们可以将模板匹配应用于调整大小的图像:
    • cv2。minMaxLoc函数获取相关结果并返回一个4元组,其中分别包括最小相关值、最大相关值、最小值的(x,y)-坐标和最大值的(x,y)-坐标。我们只对最大值和(x,y)-坐标感兴趣,所以我们保留最大值,放弃最小值。
  • 然后,我们检查图像中在每次迭代时匹配的区域。从那里,我们更新我们发现的变量find,以跟踪到目前为止发现的最大相关值,最大值的(x,y)-坐标,以及原始图像宽度与当前调整大小的图像宽度的比率。
  • 在我们遍历了图像的所有尺度之后,我们将找到的变量解包,然后计算边界框的起点和终点(x,y)-坐标。特别注意将边界框的坐标乘以比率,以确保坐标与输入图像的原始尺寸匹配。
  • 最后,我们绘制边界框并将其显示在屏幕上。

本文由 普拉蒂玛·乌帕迪亚 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 写极客。组织 或者把你的文章寄到contribute@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。 如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享