Template Matching

Tonee Bayhon
3 min readFeb 1, 2021

First, let’s see our source image:

from skimage.io import imread, imshow
from skimage.color import rgb2gray
carrier = imread('aircraft_carrier.jpg')
carrier_gray = rgb2gray(carrier)
imshow(carrier_gray);

Then, we define our template. For this image we just choose one of the planes:

template = carrier_gray[648:744,775:838]
imshow(template);

Then using match_template to prepare for template matching

from skimage.feature import match_template
result = match_template(carrier_gray, template)
imshow(result, cmap='viridis');

Looking for our original template in the source photo:

import numpy as np
import matplotlib.pyplot as plt
x, y = np.unravel_index(np.argmax(result), result.shape)

imshow(carrier_gray)
template_width, template_height = template.shape
rect = plt.Rectangle((y, x), template_height, template_width, color='y',
fc='none')
plt.gca().add_patch(rect);

Let’s lower the threshold to accommodate more matches:

from skimage.feature import peak_local_max
imshow(carrier_gray)
template_width, template_height = template.shape
for x, y in peak_local_max(result, threshold_abs=0.8):
rect = plt.Rectangle((y, x), template_height, template_width, color='y',
fc='none')
plt.gca().add_patch(rect);

With a threshold of 0.8, we only got two matches from the source image. What happens if we lower our threshold further?

imshow(carrier_gray)
template_width, template_height = template.shape
for x, y in peak_local_max(result, threshold_abs=0.1):
rect = plt.Rectangle((y, x), template_height, template_width, color='y',
fc='none')
plt.gca().add_patch(rect);

It seems that with too low of a threshold, we obtain unnecessary matches in our source image. Intuitively, we can say that for only a few pixels, the algorithm would already consider the selected image as a match. But we want something more meaning from our image, so we find the middle ground for these thresholds:

imshow(carrier_gray)
template_width, template_height = template.shape
for x, y in peak_local_max(result, threshold_abs=0.4):
rect = plt.Rectangle((y, x), template_height, template_width, color='y',
fc='none')
plt.gca().add_patch(rect);

It seems that with even a low threshold of 0.4, we are not getting all the planes. We can assume that all the rest of the planes would just be random matches.

  1. So, will we still be able to detect the airplanes if you enlarge the template?

Template matching basically tries to locate which pixel order matches with the template to a certain degree. If we were to enlarge the template, it would disrupt this order. Simply put, as much as human vision doesn’t discriminate between scales when negligible, but the machine interprets in numbers thus this array of numbers must be followed as well.

2. How about if we flip the template image?

At the onset, we can see that the matches of the image are close to those of whose orientation is similar to its own. Thus, if we flip the template image, following the same argument as the previous question, we won’t get the same matches. Although, we we do have plane on an opposite orientation in our source image, we can definitely get some matches.

3. Finally, will we still be able to detect the airplanes if we change the contrast of the image?

I believe that at a certain threshold, because the image will match certain values from the template, it will still be able to detect the airplanes. Again, with the caveat of having a lower threshold for the same result vs. the original one.

--

--