Python Tutorial | Template matching using OpenCV

This tutorial is mainly focused on the application of OpenCV. In this tutorial, we will learn to detect the area or region in the source image using the features of the template image. we will be using the OpenCV Python library in which our main focus will be on functions like “cv2.matchTemplate”, “cv2.resize”, etc. At last, we will get our result with the area focusing on the source image that matches the similar template image.

Using OpenCV Perform Template Matching

Let’s get started…

First of all, let’s import some important Python libraries that will be required for our problem.

import os
import numpy as np
import cv2
import imutils
from matplotlib import pyplot as plt

We will start with by importing two images
1. Template Image / Patch Image
2. Main Image / Source Image

main_img_path = os.getcwd() + '/' + 'main_image.jpg'
template_path = os.getcwd() + '/' + 'template_image.jpg'

The source image is in RGB format. However, the code for reading image files then converting it to a grayscale image is

main_img = cv2.imread(main_img_path)
gray_img = cv2.cvtColor(main_img,cv2.COLOR_BGR2GRAY)

The resulting image is now in grayscale. (Two Dimensional)

Similarly, another way to get a grayscale image is to pass the second parameter as 0 while reading the image using OpenCV:

template = cv2.imread(template_path,0)

Next we will store the height and width of the template image in ht_t and wd_t. And declare the NoneType variable.

ht_t, wd_t = template.shape
found = None

The basic idea here is to slide the template image over source image the same as in conv2d and find the region with the highest correlation.

(Besides, those who are into Convolutional Neural Network can check out depth information on conv2d.)

let’s dive in more depth!!

So, that we can have a clear understanding…


For instance, The code for a matching template with a similar image is

# Template matching
result = cv2.matchTemplate(gray_img,template,cv2.TM_CCOEFF_NORMED) 
  
# Specify a threshold 
threshold = 0.8
  
# Store the coordinates of matched area in a numpy array 
loc = np.where( result >= threshold)

After performing the matching operation, simply using threshold (or accuracy) and comparing it with the result will give the region identical.


However, our main focus is to make our operation more robust. Why?

Because this is insufficient as it performs poorly for the augmented image like rotated or change in shape/size/shear.

But, we can use a simple magic trick i.e. Multiscaling matching.

  1. Scale down the source image to make the input image smaller and smaller using “loop”.
  2. Secondly using OpenCV for edge detection
  3. Thirdly apply template matching and keep track of the match with the highest correlation.
  4. At last after looping over all scales get the region with the highest correlation.

Below is our Python program for template matching using the OpenCV library:

for scale in np.linspace(0.02,0.5,20)[::-1]:
    resized = cv2.resize(gray_img, dsize = (0,0), fx = scale, fy = scale)
    r = gray_img.shape[1] / float(resized.shape[1])       ## ratio of image resizing
   
    ## ensuring resized image is not smaller than the template image 
    if resized.shape[0] < ht_t or resized.shape[1] < wd_t:
            break
    edged = cv2.Canny(resized, 50, 200)       ### edge detection 
    result = cv2.matchTemplate(edged, template, cv2.TM_CCOEFF)
    (minVal, maxVal, minLoc, maxLoc) = cv2.minMaxLoc(result)

    if found is None or maxVal > found[0]:
        found = (maxVal, maxLoc, r)
print(found)
(_, maxLoc, r) = found
(startX, startY) = (int(maxLoc[0] * r), int(maxLoc[1] * r))
(endX, endY) = (int((maxLoc[0] + wd_t) * r), int((maxLoc[1] + ht_t) * r))
cv2.rectangle(main_img, (startX, startY), (endX, endY), (255, 0, 0), 2)
cv2.imshow("Template",template)
cv2.imshow("Image", main_img)

 

Leave a Reply