模板匹配 是一种查找图像中与面片(模板)相似的区域的技术。 补丁是具有特定特征的小图像。模板匹配的目标是在图像中找到补丁/模板。 要找到它,用户必须提供两个输入图像: 源图像 –在中查找模板的图像,以及 模板图像(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) |
模板匹配的限制:
- 图案引用必须保留参考图案图像(模板)的方向
- 因此,它不适用于模板的旋转或缩放版本,因为对象w.r.t.模板的形状/大小/剪切等变化将给出错误匹配。
- 该方法在计算中大型图像的模式相关图像时效率低下,因为该过程耗时。
为了避免模板和原始图像大小不同所造成的问题,我们可以使用 多路定标 。在这种情况下,仅仅因为模板的尺寸与图像中要匹配的区域的尺寸不匹配,并不意味着无法应用模板匹配。
模板匹配中的多尺度机制
多重缩放的过程如下:
- 以多个比例循环输入图像(即使输入图像逐渐变小)。
- 使用cv2应用模板匹配。matchTemplate并跟踪相关系数最大的匹配(以及相关系数最大区域的x、y坐标)。
- 在所有尺度上循环之后,取相关系数最大的区域作为“匹配”区域。
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