Should there be used a different method for object detection when used cv2.Canny?

62 views Asked by At

I'm trying to implement the usage of cv2.Canny(), but no matter which approach and method I'm using I'm not getting the object detected. So here I'm raising a question about whether there could be object detection with the cv2.Canny Here's the code that I have:

import time
import Options.settings as set
import time
import pyautogui as pt
from time import sleep
import cv2
import mss
import numpy

x = 0

offset = set.offset
create_logs = set.create_logs

#template and dimensions
template = cv2.imread("m2.png")
template_gray = cv2.cvtColor(template, cv2.COLOR_BGRA2GRAY)
template_canny = cv2.Canny(template_gray, 79, 100)
template_w, template_h = template_canny.shape[::-1]

with mss.mss() as sct:
    # Part of the screen to capture
    monitor = {"top": 523, "left": 1600, "width": 230, "height": 359}

    while True:
        last_time = time.time()
        
        # Get raw pixels from the screen, save it to a Numpy array
        img = numpy.array(sct.grab(monitor))

        # Display the picture
        cv2.imshow("Normal", img)

        # Display the picture in grayscale
        img_gray = cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY)
        img_canny = cv2.Canny(img_gray, 100, 115)

        res = cv2.matchTemplate(
            image = img_canny,
            templ = template_canny, 
            method= cv2.TM_CCOEFF_NORMED
        )

        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

        #threshold
        if max_val >= 0.6:
            x = x + 1
            print(f'{x} is used')

            img = cv2.rectangle(
                img = img,
                pt1 = max_loc,
                pt2 = (
                    max_loc[0] + template_w, # = pt2 x 
                    max_loc[1] + template_h # = pt2 y
                ),
                color = (0,255,0),
                thickness = 3 #fill the rectangle
            )
        # Display the picture
        cv2.imshow("Normal", img)



        #print("fps: {}".format(1 / (time.time() - last_time)))

        # Press "q" to quit
        if cv2.waitKey(25) & 0xFF == ord("q"):
            cv2.destroyAllWindows()
            break

Here's the original code, but because it wasn't detecting object as accurate as supposed and wasn't working with some of the cv2 methods like "TM_CCORR_NORMED" I was recommended to try cv2.Canny.

import time
import Options.settings as set
import time
import pyautogui as pt
from time import sleep
import cv2
import mss
import numpy

x = 0

offset = set.offset
create_logs = set.create_logs

#template and dimensions
template = cv2.imread("m1.png")
template_gray = cv2.cvtColor(template, cv2.COLOR_BGRA2GRAY)
template_w, template_h = template_gray.shape[::-1]

with mss.mss() as sct:
    # Part of the screen to capture
    monitor = {"top": 523, "left": 1600, "width": 230, "height": 359}

    while True:
        last_time = time.time()
        
        # Get raw pixels from the screen, save it to a Numpy array
        img = numpy.array(sct.grab(monitor))

        # Display the picture
        cv2.imshow("Normal", img)

        # Display the picture in grayscale
        img_gray = cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY)

        res = cv2.matchTemplate(
            image = img_gray,
            templ = template_gray, 
            method= cv2.TM_SQDIFF_NORMED
        )

        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

        #threshold
        if max_val >= 0.55:
            x = x + 1
            print(f'{x} is used')

            img = cv2.rectangle(
                img = img,
                pt1 = max_loc,
                pt2 = (
                    max_loc[0] + template_w, # = pt2 x 
                    max_loc[1] + template_h # = pt2 y
                ),
                color = (0,255,0),
                thickness = 3 #fill the rectangle
            )
        # Display the picture
        cv2.imshow("Normal", img)



        #print("fps: {}".format(1 / (time.time() - last_time)))

        # Press "q" to quit
        if cv2.waitKey(25) & 0xFF == ord("q"):
            cv2.destroyAllWindows()
            break

EDIT:

Images:

enter image description here

enter image description here

enter image description here

Here's the m2.png https://ibb.co/Xb5tCPZ

1

There are 1 answers

2
Markus On

EDIT: Your code works fine on my machine even with screen capturing. I only had to change the monitor region of interest that is grabbed from the screen. Perhaps you forgot to adjust that?

import cv2
import mss
import numpy


# template and dimensions
template = cv2.imread("m2.png")
template_gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
template_canny = cv2.Canny(template_gray, 79, 100)
template_w, template_h = template_canny.shape[::-1]

with mss.mss() as sct:
    # Part of the screen to capture
    monitor = {"top": 10, "left": 10, "width": 1200, "height": 800}

    while True:
        # get raw pixels from the screen, save it to a Numpy array
        img = numpy.array(sct.grab(monitor))

        # Display the picture
        cv2.imshow("Normal", img)

        # Display the picture in grayscale
        img_gray = cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY)
        img_canny = cv2.Canny(img_gray, 100, 115)

        res = cv2.matchTemplate(
            image=img_canny,
            templ=template_canny,
            method=cv2.TM_CCOEFF_NORMED
        )

        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

        # threshold
        if max_val >= 0.6:
            img = cv2.rectangle(
                img=img,
                pt1=max_loc,
                pt2=(
                    max_loc[0] + template_w,  # = pt2 x
                    max_loc[1] + template_h  # = pt2 y
                ),
                color=(0, 255, 0),
                thickness=3  # fill the rectangle
            )
        # Display the picture
        cv2.imshow("Normal", img)

        # Press "q" to quit
        if cv2.waitKey(25) & 0xFF == ord("q"):
            break

cv2.destroyAllWindows()

Output:

enter image description here