1

I need to count the occurrence of the stars at the right bottom corner in the image, I read this article Template Matching and used the following code to find the stars but My code doesn't work for detecting the stars in the image.

What changes should I make in the code?

import cv2 as cv import numpy as np from matplotlib import pyplot as plt img_rgb = cv.imread('page.png') img_gray = cv.cvtColor(img_rgb, cv.COLOR_BGR2GRAY) template = cv.imread('star_temp.png', 0) w, h = template.shape[::-1] res = cv.matchTemplate(img_gray, template, cv.TM_CCOEFF_NORMED) threshold = 0.8 loc = np.where(res >= threshold) print(res) for pt in zip(*loc[::-1]): cv.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2) cv.imwrite('res.png', img_rgb) 

star_temp.png

enter image description here

page.png

enter image description here

1
  • 2
    In template matching, the template must be the same size and orientation as the symbols you are trying to match. If that is the case, adjust your threshold and use non-maxima suppression to avoid too many matches of the same symbol. Please search Google and/or this forum for many examples of template matching in Python and OpenCV. For example, see pyimagesearch.com/2021/03/29/…. I suggest using TM_SQDIFF or TM_CORR_NORMED, not TM_COEFF_anything Commented Nov 23, 2022 at 5:51

1 Answer 1

3

It's because your template is bigger than the actual star on the image. Template matching is not scale invariant, so you need to be careful and match an almost same-size image. I cropped this from your target image:

1

This is the full working snippet:

import cv2 # image path path = "D://opencvImages//" # Reading images in default mode: targetImage = cv2.imread(path + "d6tu1.png") templateImage = cv2.imread(path + "starTemplate.png") # Deep copy for results: targetImageCopy = targetImage.copy() # Convert RGB to grayscale: grayscaleImage = cv2.cvtColor(targetImage, cv2.COLOR_BGR2GRAY) grayscaleTemplate = cv2.cvtColor(templateImage, cv2.COLOR_BGR2GRAY) # Perform template match: matchResult = cv2.matchTemplate(grayscaleImage, grayscaleTemplate, cv2.TM_CCOEFF_NORMED) # Set matching minimum score: threshold = 0.9 loc = np.where( matchResult >= threshold) # Look for possible matches: matchesCounter = 0 w, h = grayscaleTemplate.shape[::-1] for pt in zip(*loc[::-1]): cv2.rectangle(targetImageCopy, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2) # increase number of matches: matchesCounter +=1 cv2.imshow("Matches", targetImageCopy) cv2.waitKey(0) print("Number of matches: "+str(matchesCounter)) 

You end up with this result:

enter image description here

Number of matches: 3 
Sign up to request clarification or add additional context in comments.

2 Comments

thanks for your reply, it works. but the image will be taken from the camera on mobile so it should be a size variant, do you have suggestions to deal with it?
please edit your question to show a representative picture. that revelation will make the task significantly more complex.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.