0

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/

https://docs.opencv.org/2.4/doc/tutorials/imgproc/histograms/template_matching/template_matching.html

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')
William Miller
  • 9,839
  • 3
  • 25
  • 46
chiff
  • 1
  • 1
  • How about showing the input images! Post to some free hosting service and put the URLs here. Do you get any messages? I suggest you start with a single resolution and get that working. Put imshow() commands after each step to make sure they are producing the expected behavior. Also print the shape of the image and the dtype to be sure they are as expected. – fmw42 Mar 29 '20 at 08:17
  • Hey, thanks for the suggestion. The source image [link](https://ibb.co/vxJkZhm) The template image [link](https://ibb.co/CWKxCD2) The output result with cv2.TM_CCORR [link](https://ibb.co/pb465rd) The output result with cv2.TM_CCORR_NORMED [link](https://ibb.co/4j1W8Hn) With the NORMED no bounding box gets drawn, because the value is too low? – chiff Mar 29 '20 at 14:27

0 Answers0