2

I have a numpy array of size 2000*4000 with binary values in it. I have a template that I would like to match with my source array. Currently I'm running a sliding window over the source array. Although this method works fine, it's very time consuming. I'm guessing a native implementation would be much faster. Also can it match multiple occurrences of the template?

Something like

x = [[0 0 1 1 1 1 1 0 0]
     [0 0 1 1 0 0 0 0 0]
     [0 0 1 1 0 0 0 0 0]
     [0 0 1 1 0 0 0 0 0]]

template = [[1 1 1 1]
            [1 0 0 0]
            [1 0 0 0]]

cords = np.matchtemplate(x, template)

And printing the cords should ideally give a list of tuples which has the diagonal coordinates of the matching segment.

print(cords)

[[(0, 3), (6, 2)]]
Akas Antony
  • 739
  • 1
  • 8
  • 19
  • Just an idea: what about running cross-correlation with your template as a 2D kernel to find candidate locations (i.e. good match between `x` and `template`), then only check the neighbourhoods around the candidate positions? Cross-correlation can be done pretty efficiently... – MPA Feb 06 '18 at 10:23

2 Answers2

3

A solution which uses OpenCV:

import cv2

result = cv2.matchTemplate(
    x.astype(np.float32),
    template.astype(np.float32),
    cv2.TM_SQDIFF)

positions = np.argwhere(result == 0.0)

This gives (0, 3) for your example.

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
1

As @MPA suggested, this will provide with a list of candidates:

from scipy import signal

match = np.sum(template)
tst = signal.convolve2d(x, template[::-1, ::-1], mode='valid') == match
candidates = np.argwhere(tst)

This gives (0, 2) and (0, 3) for your example.


For binary matrices, one can do as @Paul suggests:

from scipy import signal

match = np.sum(template)
tst = signal.convolve2d(x, (2 * template - 1)[::-1, ::-1], mode='valid') == match
positions = np.argwhere(tst)

This gives (0, 3) for your example.

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
  • 1
    You could use `2*template - 1`; that way you would get actual hits instead of candidates. Btw. `argwhere` gives the coordinanate tuples directly. – Paul Panzer Feb 06 '18 at 10:57