I try to find the best way to detect images with the rotation. Without rotation cv2.matchTemplate works pretty fine, but I found no function for rotated images.
I need the position and angle of the template images in the big picture. Any idea is welcome, I hope the example makes it clear.
thanks for help and support.
template image:
big picture:
Here is a simplistic approach in Python/OpenCV to get the rotation angle, centroid and width and height of the rotated bounding box of the image.
The approach is to get (and filter contours on area), then draw them white filled on a black background to merge the contours. Then get the convex hull of the merged contour and compute the rotated rectangle from the contour of the convex hull. That returns the rotation angle, centroid and rotated bounding box dimensions.
Read the input
Convert to grayscale
Threshold and invert so that the heart and number are white on black background
Find the external contours from the thresholded image and filter on area.
While filtering draw the contours as a mask image as white filled on black background
Get all the points of the white pixels and then compute the convex hull from those points
Get the (largest and only) contour from the convex hull
Compute the rotated rectangle from this contour
Print the width x height, center, and rotation angle
Draw the rotated rectangle outline as green on a copy of the input
Show the various computed images
#!/bin/python3.12
import cv2
import numpy as np
# read the input image as grayscale
img = cv2.imread('ace_image.png')
# convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# threshold image and invert
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)[1]
# Find external contours
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
minArea=100
mask = np.zeros_like(thresh)
for c in contours:
area=cv2.contourArea(c)
if area > minArea:
cv2.drawContours(mask,[c],0,(255),-1)
# draw white filled contour on black background for combined bounding box
points = np.column_stack(np.where(mask.transpose() > 0))
hull = cv2.convexHull(points)
# draw convex hull in white filled on black
hull_img = np.zeros_like(thresh)
cv2.fillPoly(hull_img, [hull], 255)
# get rotated rectangle for combined bounding box
contours = cv2.findContours(hull_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
c = max(contours, key=cv2.contourArea)
rotrect = cv2.minAreaRect(c)
(center), (width,height), angle = rotrect
print('width x height:', width, "x", height)
print('center', center)
print('angle', angle)
box = cv2.boxPoints(rotrect)
boxpts = np.int32(box)
# draw rotated rectangle on copy of image
rotrect_img = img.copy()
cv2.drawContours(rotrect_img,[boxpts],0,(0,255,0),2)
# write results images
cv2.imwrite('ace_image_combined_contour.jpg', mask)
cv2.imwrite('ace_image_convexhull.jpg', hull_img)
cv2.imwrite('ace_image_rotated_rectangle.jpg', rotrect_img)
# show results
cv2.imshow('combined contours', mask)
cv2.imshow('convex hull', hull_img)
cv2.imshow('rotated rectangle', rotrect_img)
cv2.waitKey(0)
Combined Contour Image:
ConvexHull Image:
Rotated Rectangle On Copy Of Image:
Text Output:
width x height: 23.33452033996582 x 45.96194076538086
center (129.5, 95.0)
angle 45.0