使用自定义内核/图像过滤器在二维数组中查找特定模式

Use a custom kernel / image filter to find a specific pattern in a 2d array

给定一张图片 im,

>>> np.random.seed(0)
>>> im = np.random.randint(0, 100, (10,5))
>>> im
array([[44, 47, 64, 67, 67],
       [ 9, 83, 21, 36, 87],
       [70, 88, 88, 12, 58],
       [65, 39, 87, 46, 88],
       [81, 37, 25, 77, 72],
       [ 9, 20, 80, 69, 79],
       [47, 64, 82, 99, 88],
       [49, 29, 19, 19, 14],
       [39, 32, 65,  9, 57],
       [32, 31, 74, 23, 35]])

找到此图像的特定片段的最佳方法是什么,例如

>>> im[6:9, 2:5]
array([[82, 99, 88],
       [19, 19, 14],
       [65,  9, 57]])

如果特定组合不存在(可能是由于噪声),我想有一个相似性度量,它搜索具有相似分布的片段并告诉我 im 的每个像素,如何好的协议是。例如像

array([[0.03726647, 0.14738364, 0.04331007, 0.02704363, 0.0648282 ],
       [0.02993497, 0.04446428, 0.0772978 , 0.1805197 , 0.08999   ],
       [0.12261269, 0.18046972, 0.01985607, 0.19396181, 0.13062801],
       [0.03418192, 0.07163043, 0.15013723, 0.12156613, 0.06500945],
       [0.00768509, 0.12685481, 0.19178985, 0.13055806, 0.12701177],
       [0.19905991, 0.11637007, 0.08287372, 0.0949395 , 0.12470202],
       [0.06760152, 0.13495046, 0.06344035, 0.1556691 , 0.18991421],
       [0.13250537, 0.00271433, 0.12456922, 0.97      , 0.194389  ],
       [0.17563869, 0.10192488, 0.01114294, 0.09023184, 0.00399753],
       [0.08834218, 0.19591735, 0.07188889, 0.09617871, 0.13773224]])

示例代码是python。 我认为应该有一个将内核与 im 相关联的解决方案。但是,这会有一个问题,即具有相同值但缩放的段将给出更清晰的响应。

模板匹配将是实现它的方法之一。当然deeplearning/ML也可以用于更复杂的匹配

大多数图像处理库都支持某种匹配函数,该函数比较一组 2 张图像 - 参考图像和要匹配的图像。在 OpenCV 中,它 returns 一个可以用来确定匹配的分数。匹配方法使用各种支持scale and/or rotation invariant匹配的函数。当心您计划使用的方法中的许可限制。

如果图像可能并不总是准确的,您可以使用标准差 (StdDev) 来允许允许的偏差并将它们分类到桶中。根据要匹配的图像条件,也可以使用直方图匹配(照明、颜色可能很重要,除非您使用特定通道)。使用直方图将避免完全匹配模板。

模板匹配参考:

感谢 banerjk 的出色回答 - template matching 正是解决方案!

一些备份方法

考虑到我的correlating-with-a-kernel想法,有一些进展: 当将图像与模板相关联时(即我在问题中所说的目标片段),相关图像中最强烈的点(相对于平均强度)与模板位置匹配的可能性很高(参见 im 和示例中的 m)。好像我不是第一个提出这个想法的人,从第 39 页的 lecture notes 中可以看出。

然而,这并不总是正确的。这种方法或多或少只是检测模板中最大值处的权重。在这个例子中,im2 被构造成这样,它欺骗了这个概念。

如果事先在图像上应用一些过滤器(例如中值),也许它会变得更可靠。

我只是想在这里提一下,因为它在某些情况下可能有优势(与 template_matching 的 Wikipedia-implementation 相比,它应该具有更高的性能)。

例子

import numpy as np
from scipy import ndimage

np.random.seed(0)
im = np.random.randint(0, 100, (10,5))
t = im[6:9, 2:5]
print('t', t, sep='\n')

m = ndimage.correlate(im, t) / ndimage.correlate(im, np.ones(t.shape))
m /= np.amax(m)

print('im', im, sep='\n')
print('m', m, sep='\n')

print("this can be 'tricked', however")

im2 = im.copy()
im2[6:9, :3] = 0
im2[6,1] = 1

m2 = ndimage.correlate(im2, t) / ndimage.correlate(im2, np.ones(t.shape))
m2 /= np.amax(m2)

print('im2', im2, sep='\n')
print('m2', m2, sep='\n')

输出

t
[[82 99 88]
 [19 19 14]
 [65  9 57]]
im
[[44 47 64 67 67]
 [ 9 83 21 36 87]
 [70 88 88 12 58]
 [65 39 87 46 88]
 [81 37 25 77 72]
 [ 9 20 80 69 79]
 [47 64 82 99 88]
 [49 29 19 19 14]
 [39 32 65  9 57]
 [32 31 74 23 35]]
m
[[0.73776208 0.62161208 0.74504705 0.71202601 0.66743979]
 [0.70809611 0.70617161 0.70284942 0.80653741 0.67067733]
 [0.55047727 0.61675268 0.5937487  0.70579195 0.74351706]
 [0.7303857  0.77147963 0.74809273 0.59136392 0.61324214]
 [0.70041161 0.7717032  0.69220064 0.72463532 0.6957257 ]
 [0.89696894 0.69741108 0.64136612 0.64154719 0.68621613]
 [0.48509474 0.60700037 0.65812918 0.68441118 0.68835903]
 [0.73802038 0.83224745 0.87301124 1.         0.92272565]
 [0.72708573 0.64909142 0.54540817 0.60859883 0.52663327]
 [0.72061572 0.70357846 0.61626289 0.71932261 0.75028955]]
this can be 'tricked', however
im2
[[44 47 64 67 67]
 [ 9 83 21 36 87]
 [70 88 88 12 58]
 [65 39 87 46 88]
 [81 37 25 77 72]
 [ 9 20 80 69 79]
 [ 0  1  0 99 88]
 [ 0  0  0 19 14]
 [ 0  0  0  9 57]
 [32 31 74 23 35]]
m2
[[0.53981867 0.45483201 0.54514907 0.52098765 0.48836403]
 [0.51811216 0.51670401 0.51427317 0.59014141 0.49073293]
 [0.40278285 0.4512764  0.43444444 0.51642621 0.54402958]
 [0.5344214  0.56448972 0.54737758 0.43269951 0.44870774]
 [0.51248943 0.56465331 0.50648148 0.53021386 0.50906076]
 [0.78923691 0.56633529 0.51641414 0.44336403 0.50210263]
 [0.88137788 0.89779614 0.63552189 0.55070797 0.50367059]
 [0.88888889 1.         0.75544508 0.75694003 0.67515605]
 [0.43965976 0.48492221 0.37490287 0.48511085 0.38533625]
 [0.30754918 0.32478065 0.27066895 0.46685032 0.548985  ]]

也许有人可以对讲义的背景做出贡献。

更新: 在第一页J. P. Lewis, “Fast Normalized Cross-Correlation”, Industrial Light and Magic.中讨论。