我正试图通过沿图像移动模板来匹配二值图像(只有黑白)。并返回模板和图像之间的最小距离,以及出现该最小距离的相应位置。例如:
图像:0 1 0
0 0 1
0 1 1
模板:
^{pr2}$
此模板与位置(1,1)处的图像最匹配,距离将为0。到目前为止,事情并不是太困难,我已经得到了一些代码,可以做到这一点。在def match_template(img, template):
mindist = float('inf')
idx = (-1,-1)
for y in xrange(img.shape[1]-template.shape[1]+1):
for x in xrange(img.shape[0]-template.shape[0]+1):
#calculate Euclidean distance
dist = np.sqrt(np.sum(np.square(template - img[x:x+template.shape[0],y:y+template.shape[1]])))
if dist < mindist:
mindist = dist
idx = (x,y)
return [mindist, idx]
但是对于我需要的大小的图像(图像在500 x 200像素之间,模板在250 x 100之间),这已经花费了大约4.5秒,这太慢了。我知道使用矩阵乘法可以更快地完成同样的事情(在matlab中,我相信可以使用im2col和repmat来完成)。有人能解释一下怎么用python/numpy来做吗?在
顺便说一句,我知道有一个opencvmatchtemplate函数可以完全满足我的需要,但是由于我以后可能需要稍微修改代码,所以我更喜欢一个我完全理解并可以修改的解决方案。在
谢谢!在
编辑:如果有人能解释一下opencv是如何在不到0.2秒的时间内做到这一点的,那也太棒了。我看了一下源代码,但是这些东西对我来说总是很复杂。在
编辑2:赛顿代码import numpy as np
cimport numpy as np
DTYPE = np.int
ctypedef np.int_t DTYPE_t
def match_template(np.ndarray img, np.ndarray template):
cdef float mindist = float('inf')
cdef int x_coord = -1
cdef int y_coord = -1
cdef float dist
cdef unsigned int x, y
cdef int img_width = img.shape[0]
cdef int img_height = img.shape[1]
cdef int template_width = template.shape[0]
cdef int template_height = template.shape[1]
cdef int range_x = img_width-template_width+1
cdef int range_y = img_height-template_height+1
for y from 0 <= y < range_y:
for x from 0 <= x < range_x:
dist = np.sqrt(np.sum(np.square(template - img[ x:(x+template_width), y:(y+template_height) ]))) #calculate euclidean distance
if dist < mindist:
mindist = dist
x_coord = x
y_coord = y
return [mindist, (x_coord,y_coord)]
img = np.asarray(img, dtype=DTYPE)
template = np.asarray(template, dtype=DTYPE)
match_template(img, template)