python opencv how do i matchtemplate for same shapes with different colors and brightness

Question:

im using matchtemplate to detect 2×2 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)

enter image description here

template

enter image description here

image

enter image description here

result

Asked By: wookidookik123

||

Answers:

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

^– 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)

result

Answered By: Claudio
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.