Home » Tutorial: Template Matching Using OpenCV in Python

Tutorial: Template Matching Using OpenCV in Python

Java SE 11 Programmer I [1Z0-815] Practice Tests
1 Year Subscription
Java SE 11 Programmer II [1Z0-816] Practice Tests
Java SE 11 Developer (Upgrade) [1Z0-817]
Spring Framework Basics Video Course
Oracle Java Certification

Template Matching is a technique in image processing to find a smaller image (template) within a larger image. OpenCV provides robust functionality to perform template matching using different methods.

What You’ll Learn

1. Introduction to Template Matching

Template Matching involves sliding the template image over the larger image and comparing regions using a similarity metric. OpenCV’s cv2.matchTemplate() is the core function for this task.

Syntax

result = cv2.matchTemplate(image, template, method)
  • image: The larger source image.
  • template: The smaller template image.
  • method: Matching method (e.g., cv2.TM_CCOEFF, cv2.TM_SQDIFF).

2. Basic Template Matching

Example: Single Template Matching

import cv2

# Load the main image and template
image = cv2.imread("source.jpg")
template = cv2.imread("template.jpg")

# Perform template matching
result = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)

# Get the location of the best match
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)

# Draw a rectangle around the matched region
h, w, _ = template.shape
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
cv2.rectangle(image, top_left, bottom_right, (0, 255, 0), 2)

# Display the result
cv2.imshow("Matched Image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

3. Visualizing Matching Results

The result of cv2.matchTemplate is a grayscale image representing similarity. Peaks (or troughs) indicate potential matches.

Example: Display Matching Results

import cv2
import matplotlib.pyplot as plt

# Load the main image and template
image = cv2.imread("source.jpg", cv2.IMREAD_GRAYSCALE)
template = cv2.imread("template.jpg", cv2.IMREAD_GRAYSCALE)

# Perform template matching
result = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)

# Display the result
plt.imshow(result, cmap="gray")
plt.title("Matching Result")
plt.colorbar()
plt.show()

4. Matching Using Different Methods

OpenCV supports multiple matching methods:

  1. cv2.TM_CCOEFF: Correlation coefficient (higher is better).
  2. cv2.TM_CCOEFF_NORMED: Normalized correlation coefficient.
  3. cv2.TM_CCORR: Cross-correlation.
  4. cv2.TM_CCORR_NORMED: Normalized cross-correlation.
  5. cv2.TM_SQDIFF: Squared difference (lower is better).
  6. cv2.TM_SQDIFF_NORMED: Normalized squared difference.

Example: Compare Matching Methods

import cv2
import matplotlib.pyplot as plt

# Load the main image and template
image = cv2.imread("source.jpg", cv2.IMREAD_GRAYSCALE)
template = cv2.imread("template.jpg", cv2.IMREAD_GRAYSCALE)

methods = [
    cv2.TM_CCOEFF, cv2.TM_CCOEFF_NORMED,
    cv2.TM_CCORR, cv2.TM_CCORR_NORMED,
    cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED
]

for method in methods:
    result = cv2.matchTemplate(image, template, method)
    plt.imshow(result, cmap="gray")
    plt.title(f"Method: {method}")
    plt.colorbar()
    plt.show()

5. Handling Multiple Matches

Example: Find All Matches Above a Threshold

import cv2
import numpy as np

# Load the main image and template
image = cv2.imread("source.jpg")
template = cv2.imread("template.jpg")

# Perform template matching
result = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)

# Define a threshold
threshold = 0.8
locations = np.where(result >= threshold)

# Draw rectangles around all matches
h, w, _ = template.shape
for pt in zip(*locations[::-1]):
    bottom_right = (pt[0] + w, pt[1] + h)
    cv2.rectangle(image, pt, bottom_right, (0, 255, 0), 2)

# Display the result
cv2.imshow("Detected Matches", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

6. Practical Examples

6.1 Template Matching in Real-Time Video

import cv2

# Load the template
template = cv2.imread("template.jpg", cv2.IMREAD_GRAYSCALE)
h, w = template.shape

# Open the video capture
video = cv2.VideoCapture(0)

while True:
    ret, frame = video.read()
    if not ret:
        break

    # Convert frame to grayscale
    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Perform template matching
    result = cv2.matchTemplate(gray_frame, template, cv2.TM_CCOEFF_NORMED)

    # Get the best match
    _, max_val, _, max_loc = cv2.minMaxLoc(result)

    # Draw a rectangle if match is above a threshold
    if max_val > 0.8:
        top_left = max_loc
        bottom_right = (top_left[0] + w, top_left[1] + h)
        cv2.rectangle(frame, top_left, bottom_right, (0, 255, 0), 2)

    # Display the frame
    cv2.imshow("Video Template Matching", frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

video.release()
cv2.destroyAllWindows()

6.2 Template Matching with Mask

You can use a mask to ignore specific regions in the template during matching.

import cv2

# Load images
image = cv2.imread("source.jpg")
template = cv2.imread("template.jpg")
mask = cv2.imread("mask.jpg", cv2.IMREAD_GRAYSCALE)

# Perform template matching with a mask
result = cv2.matchTemplate(image, template, cv2.TM_CCORR_NORMED, mask=mask)

# Find the best match
_, _, _, max_loc = cv2.minMaxLoc(result)
h, w, _ = template.shape
cv2.rectangle(image, max_loc, (max_loc[0] + w, max_loc[1] + h), (0, 255, 0), 2)

# Display the result
cv2.imshow("Matched Image with Mask", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

6.3 Match Template Across Scaled Versions

For images where the template might appear at different scales, you can resize the template dynamically.

import cv2

# Load the images
image = cv2.imread("source.jpg", cv2.IMREAD_GRAYSCALE)
template = cv2.imread("template.jpg", cv2.IMREAD_GRAYSCALE)

best_match = None
best_value = -1
h, w = template.shape

for scale in np.linspace(0.5, 1.5, 10):  # Scale from 50% to 150%
    resized_template = cv2.resize(template, (int(w * scale), int(h * scale)))
    result = cv2.matchTemplate(image, resized_template, cv2.TM_CCOEFF_NORMED)
    _, max_val, _, max_loc = cv2.minMaxLoc(result)

    if max_val > best_value:
        best_value = max_val
        best_match = (max_loc, resized_template.shape)

if best_match:
    top_left = best_match[0]
    h, w = best_match[1]
    bottom_right = (top_left[0] + w, top_left[1] + h)
    cv2.rectangle(image, top_left, bottom_right, (0, 255, 0), 2)

cv2.imshow("Best Match", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

7. Summary

Key Functions

  • cv2.matchTemplate(): Perform template matching.
  • cv2.minMaxLoc(): Find the best or worst match locations.
  • np.where(): Find multiple matches above a threshold.

Best Practices

  1. Normalize images and templates for better results.
  2. Use different matching methods for specific tasks.
  3. Handle scaling and rotation for templates that might appear in different forms.

By mastering these techniques, you can effectively locate and identify patterns in images using OpenCV’s template matching capabilities!

 

You may also like

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More