I'm trying to do multi scale template matching for some signature segmatation, and I'm stuck because I want to get the "accuracy" rating of the best match it returns.
The results return correctly when I use cv2.TM_CCOEFF
and cv2.TM_CCORR
, but once I try cv2.TM_CCOEFF_NORMED
and cv2.TM_CCORR_NORMED
it doesn't match properly anymore. The max value of the cv2.TM_CCOEFF
returns a very large value(sum of all the dot products?) which I do not know how to quantify into a performance rating.
I've went through quite a few online tutorials
https://www.pyimagesearch.com/2015/01/26/multi-scale-template-matching-using-python-opencv/
about the template matching, but I can't figure out why it doesn't work. My hunch is that the scale affects the results but I'm not sure.
Could someone tell me how to make NORMED methods work for multiple scales or how to quantify the maxValue into a score?
My code is below:
import os
import fitz
import numpy as np
import cv2
import matplotlib.pyplot as plt
from skimage import measure, morphology
from skimage.color import label2rgb
from skimage.measure import regionprops
from PIL import Image
working_dir="/testdocs2sift"
files=os.listdir(f".{working_dir}")
imgs=[]
#reading image
img1 = cv2.imread(f'.{working_dir}/9_finaloutput.png', 0)
img1.shape
# img1.threshold
# gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
# image 2
img2 = cv2.imread(f'.{working_dir}/trumpsig.png', 0)
plt.imshow(img2)
# template matching test 1
import cv2
import numpy as np
import imutils
# # Read the main image
# img_rgb = cv2.imread('mainimage.jpg').
img_gray = cv2.imread(f'.{working_dir}/5_finaloutput.png', 0)
# img_gray = cv2.adaptiveThreshold(img_gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,11,5)
img_gray= cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)[1]
# img_gray=cv2.normalize(img_gray, None, alpha=-1, beta=1, norm_type=cv2.NORM_MINMAX)
fig1, ax1 = plt.subplots(figsize=(15,15))
# template2
ax1.imshow(img_gray)
ax1.set_axis_off()
ax1.title.set_text('img_gray')
template = cv2.imread(f'.{working_dir}/obamasig2.png', 0)
# template = cv2.threshold(template, 180, 255, cv2.THRESH_BINARY_INV)[1]
template = cv2.adaptiveThreshold(template,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,7,11)
# template=cv2.normalize(template, None, alpha=-1, beta=1, norm_type=cv2.NORM_MINMAX)
fig2, ax2 = plt.subplots(figsize=(15,15))
# template2
ax2.imshow(template)
ax2.set_axis_off()
ax2.title.set_text('template')
(tH, tW) = template.shape[:2]
print(f"template shape is {template.shape}")
# Read the template
print(f"img shape is {img_gray.shape}")
# Store width and height of template in w and h
w, h = template.shape[::-1]
found = None
count=0
bestpercent=0
# bestresult=[]
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']
for scale in np.linspace(0.1, 2.0, 20)[::-1]:
count+=1
try:
# resize the image according to the scale, and keep track
# of the ratio of the resizing
resized = imutils.resize(img_gray, width = int(img_gray.shape[1] * scale))
print(f"resized shape is {resized.shape}")
r = img_gray.shape[1] / float(resized.shape[1])
# print(f"ratio is {r}")
result = cv2.matchTemplate(resized, template, cv2.TM_CCORR)
print(f"result shape is {result.shape}")
# print(f"result is {result}")
(minVal, maxVal, minLoc, maxLoc) = cv2.minMaxLoc(result)
print(minVal, maxVal, minLoc, maxLoc)
# if we have found a new maximum correlation value, then update the found variable
if found is None or maxVal > found[0]:
found = (maxVal, maxLoc, r)
print(f"found is {found}")
bestresult=result
print(f"This is a better match at maxVal is {maxVal}, maxLoc is {maxLoc}, ratio is {r}")
else:
print("This is NOT a better match")
percentage=maxVal*r/(template.shape[0]*template.shape[1])
if percentage>bestpercent:
bestpercent=percentage
except:
print("didnt work")
# unpack the found varaible and compute the (x, y) coordinates
# of the bounding box based on the resized ratio
print(f"Best value, best location, and ratio is {found}")
print(f"best percent is {bestpercent}")
print(f"found is {found}")
(bestVal, bestLoc, bestr) = found
print(f"found2 is {found}")
(startX, startY) = (int(bestLoc[0] * bestr), int(bestLoc[1] * bestr))
(endX, endY) = (int((bestLoc[0] + tW) * bestr), int((bestLoc[1] + tH) * bestr))
# print(f"maxLoc is {bestLoc}, r is {bestr}")
# print(f"startx starty is {(startX, startY)}, endx end y is {(endX, endY)}")
# draw a bounding box around the detected result and display the image
cv2.rectangle(img_gray, (startX, startY), (endX, endY), (255, 255, 0), 2)
# Show the final image with the matched area.
fig10, ax10 = plt.subplots(figsize=(15,15))
ax10.imshow(cv2.bitwise_not(img_gray), cmap='Greys_r')
ax10.set_axis_off()
ax10.title.set_text('final')