im using matchtemplate to detect 2x2 sqaures on dark background. with my code, it detects most of the squares without any problem but it fails detecting when the color of the squares are dark and blackish. i tried normalize in opencv but it didnt work well.. also tried using mask but it didnt work either (maybe i used the mask feature wrong?) since i lack of understanding image preprocessing and opencv. i believe theres so many things im missing but i just cant figure out what im missing. i would really appreciate it if someone could help me out
import cv2
import numpy as np
import time
import win32gui, win32ui, win32con
def imagesearch(per):
img = cv2.imread('target.png', cv2.IMREAD_GRAYSCALE)
img1 = cv2.imread('target.png')
template = cv2.imread('./map/monster.png', cv2.IMREAD_GRAYSCALE)
w, h = template.shape[::-1]
meth = [cv2.TM_CCOEFF, cv2.TM_CCOEFF_NORMED, cv2.TM_CCORR, cv2.TM_CCORR_NORMED, cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]
res = cv2.matchTemplate(img, template, meth[3])
threshold = per
loc = np.where(res>=threshold)
if loc[0].any():
for pt in zip(*loc[::-1]):
cv2.rectangle(img1, pt, (pt[0] w, pt[1] h), (0,0,255), 1)
cv2.imshow("dst", img1)
cv2.waitKey(0)
cv2.destroyAllWindows()
imagesearch(0.8)
template
image
result
CodePudding user response:
The problem you are facing is that part of the squares you want to detect does not follow the rule "lighter than background" and are "darker than background". The solution to this problem is to use template image with reversed colors:
^-- inversed template
import cv2
import numpy as np
import time
def imagesearch(per):
img = cv2.imread('openCV_squareDetection.png', cv2.IMREAD_GRAYSCALE)
img1 = cv2.imread('openCV_squareDetection.png')
template_inversed = cv2.imread('openCV_squareDetection_template_inversed.png', cv2.IMREAD_GRAYSCALE)
template = cv2.imread('openCV_squareDetection_template.png', cv2.IMREAD_GRAYSCALE)
w, h = template.shape[::-1]
meth = [cv2.TM_CCOEFF, cv2.TM_CCOEFF_NORMED, cv2.TM_CCORR, cv2.TM_CCORR_NORMED, cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]
res = cv2.matchTemplate(img, template , meth[1])
res_inversed = cv2.matchTemplate(img, template_inversed, meth[1])
threshold = per
loc = np.where(res >=threshold)
loc_inversed = np.where(res_inversed>=threshold)
if loc[ 0].any():
for pt in zip(*loc[::-1]):
cv2.rectangle(img1, pt, (pt[0] w, pt[1] h), (0,0,255), 1)
if loc_inversed[0].any():
for pt in zip(*loc_inversed[::-1]):
cv2.rectangle(img1, pt, (pt[0] w, pt[1] h), (0,0,255), 1)
cv2.imshow("dst", img1)
cv2.waitKey(0)
cv2.destroyAllWindows()
imagesearch(0.95)