detect and count the number of star symbol in opencv-python
Question:
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
page.png
Answers:
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:
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:
Number of matches: 3
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
page.png
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:
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:
Number of matches: 3