OpenCV Template Matching for Object Detection
SkillMediaCount occurrences of a template object in an image using OpenCV template matching with non-maximum suppression.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the OpenCV Template Matching for Object Detection skill
What this skill tells your AI
The instructions your AI receives, as published by cxcscmu/skilllearnbench in skills/b1-one-shot-claude-opus-4-6/video-object-counting/opencv-template-matching/SKILL.md and read by ahel’s review.
Overview
OpenCV is a computer vision library that enables template matching - finding occurrences of a template image within a larger source image. This is useful for counting objects in screenshots or video frames.
Installation
pip install opencv-python numpy
Key Concepts
Template Matching
Template matching works by sliding a smaller template image across a larger image and computing a similarity score at each position. Objects are detected where the score exceeds a threshold.
Matching Methods
cv2.TM_CCOEFF: Correlation coefficient (recommended for most cases)cv2.TM_CCORR: Cross correlationcv2.TM_SQDIFF: Sum of squared differences
Usage Examples
Convert RGB Image to Grayscale
import cv2
# Read image in color
image = cv2.imread('image.png')
# Convert to grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Save grayscale image (overwrites original)
cv2.imwrite('image.png', gray)
Basic Template Matching
import cv2
import numpy as np
def count_objects(image_path, template_path, threshold=0.8):
"""Count occurrences of template in image"""
# Read images in grayscale
image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
template = cv2.imread(template_path, cv2.IMREAD_GRAYSCALE)
# Perform template matching
result = cv2.matchTemplate(image, template, cv2.TM_CCOEFF)
# Find locations where correlation exceeds threshold
locations = np.where(result >= threshold)
# Count unique objects (accounting for nearby detections)
count = len(locations[0])
return count, locations
Advanced: Non-Maximum Suppression
Template matching often produces overlapping detections. Use non-maximum suppression to remove duplicates:
import cv2
import numpy as np
def count_objects_nms(image_path, template_path, threshold=0.8, min_distance=10):
"""Count objects using non-maximum suppression"""
image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
template = cv2.imread(template_path, cv2.IMREAD_GRAYSCALE)
result = cv2.matchTemplate(image, template, cv2.TM_CCOEFF)
# Get all locations above threshold with their scores
locations = np.where(result >= threshold)
scores = result[locations]
# Convert to list of (x, y, score) tuples
detections = list(zip(locations[1], locations[0], scores))
# Sort by score descending
detections.sort(key=lambda x: x[2], reverse=True)
# Apply non-maximum suppression
kept = []
for x, y, score in detections:
# Check if too close to already kept detection
too_close = False
for kx, ky in kept:
if abs(x - kx) < min_distance and abs(y - ky) < min_distance:
too_close = True
break
if not too_close:
kept.append((x, y))
return len(kept), kept
Full Object Counting Pipeline
import cv2
import os
def process_frame_and_count(frame_path, template_path, threshold=0.8):
"""
Complete pipeline: read image, convert to grayscale,
count objects, and return count
"""
# Read image in color first
image = cv2.imread(frame_path)
# Convert to grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Overwrite original file with grayscale version
cv2.imwrite(frame_path, gray)
# Read template in grayscale
template = cv2.imread(template_path, cv2.IMREAD_GRAYSCALE)
# Perform template matching
result = cv2.matchTemplate(gray, template, cv2.TM_CCOEFF)
# Count detections above threshold
count = np.sum(result >= threshold)
return count
Tips
- Threshold Selection: Start with 0.7-0.8 for strict matching, go lower if missing objects
- Template Size: Larger templates are faster but less flexible. Use templates that match object size in frames
- Grayscale: Converting to grayscale makes matching more robust to color variations
- Normalization: For noisy results, normalize the result map before thresholding
- Multi-scale: Consider extracting at different scales if object sizes vary
Common Issues
- No detections: Lower threshold or verify template is similar to objects in image
- Too many detections: Apply non-maximum suppression to filter nearby matches
- Memory issues: Process large images in chunks or reduce resolution
Signals
- GitHub stars
- 83
- Forks
- 5
- Last commit
- Jul 2026
Advanced
- Catalog kind
- skill
- Gateway key
opencv-template-matching- Source
- github.com/cxcscmu/skilllearnbench