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.
- Scale down the source image to make the input image smaller and smaller using “loop”.
- Secondly using OpenCV for edge detection
- Thirdly apply template matching and keep track of the match with the highest correlation.
- 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 / float(resized.shape) ## ratio of image resizing ## ensuring resized image is not smaller than the template image if resized.shape < ht_t or resized.shape < 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: found = (maxVal, maxLoc, r) print(found) (_, maxLoc, r) = found (startX, startY) = (int(maxLoc * r), int(maxLoc * r)) (endX, endY) = (int((maxLoc + wd_t) * r), int((maxLoc + ht_t) * r)) cv2.rectangle(main_img, (startX, startY), (endX, endY), (255, 0, 0), 2) cv2.imshow("Template",template) cv2.imshow("Image", main_img)