M
M
MiheiSV2021-02-22 22:37:02
numpy
MiheiSV, 2021-02-22 22:37:02

How to compare arrays in NumPy or do without them?

Good day, wise users of Habr.
I recently came across a video about automating fishing in MMO Albion Online / https://www.youtube.com/watch?v=92XnJ3s0vX8 / also, there is an article on Habré about it. Since I play this game, I decided to write my own script that detects red nicknames (enemies) at the edges of the screen and presses the R button, using the OpenCV and PyAutoGUI libraries, this is such a game area as a gang, but we will not go into details.
Source -

spoiler
import time
import cv2
import mss
import numpy as np
import pyautogui

template = cv2.imread("red_nick.png", cv2.IMREAD_GRAYSCALE)
w, h = template.shape[::-1]

with mss.mss() as sct:
    monitor = {"top": 0, "left": 0, "width": 400, "height": 250}

    while "Screen capturing":
        last_time = time.time()
        img = np.array(sct.grab(monitor))
        empty_img = np.array(sct.grab(monitor))
        print("fps: {}".format(1 / (time.time() - last_time)))
        gray_frame = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        res = cv2.matchTemplate(gray_frame, template, cv2.TM_CCOEFF_NORMED)
        loc = np.where(res >= 0.999)
        for i in zip(*loc[::-1]):
            cv2.rectangle(img, i, (i[0] + w, i[1] + h), (0, 255, 255), 10)
        #cv2.imshow("Frame", img)
        #cv2.imshow("Frame2", empty_img)
        if cv2.waitKey(1) == 27:
            cv2.destroyAllWindows()
            break
        if (img != empty_img).any():
            pyautogui.press(keys='r')
            cv2.imshow("Frame", img)
            cv2.waitKey()
            break

The problem is in several things at once, let's start in order:
1) I took the code from the article on Habré as a basis, because I don't know much myself now, so the code may be crooked in some places.
2) The second problem in these lines of code -
if (img != empty_img).any():
            pyautogui.press(keys='r')
            break

Firstly, it was done on the knee, so that at least it would not give an error at startup.
Secondly, it was conceived in such a way that a screenshot of the screen was written to the img variable (repeatedly, so that it would be like a video), and the same screenshot, but without changes, would be written to empty_img. That is, when using OpenCV to find a red nickname on img, we select it and compare img with empty_img to find out if there is a difference between them (is there a red nickname in the screenshot). And then, if we found it, we pressed the R button, if not, we continued the cycle. But this does not work as intended, because sometimes the code may simply not have time to write two identical screenshots to these two variables, which prevents it from correctly executing. I tried to solve this problem by replacing
empty_img = np.array(sct.grab(monitor))
with
empty_img = img,
which, logically, should have helped, but another problem arose - after executing the lines
for i in zip(*loc[::-1]):
cv2.rectangle(img, i, (i[0] + w, i[1] + h), (0, 255, 255), 10)

these two variables become the same. Why, I never understood.
Source -
spoiler
import time
import cv2
import mss
import numpy as np
import pyautogui

template = cv2.imread("red_nick.png", cv2.IMREAD_GRAYSCALE)
w, h = template.shape[::-1]

with mss.mss() as sct:
    monitor = {"top": 0, "left": 0, "width": 400, "height": 250}

    while "Screen capturing":
        last_time = time.time()
        img = np.array(sct.grab(monitor))
        empty_img = np.array(sct.grab(monitor))
        print("fps: {}".format(1 / (time.time() - last_time)))
        gray_frame = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        res = cv2.matchTemplate(gray_frame, template, cv2.TM_CCOEFF_NORMED)
        loc = np.where(res >= 0.999)
        for i in zip(*loc[::-1]):
            cv2.rectangle(img, i, (i[0] + w, i[1] + h), (0, 255, 255), 10)
        #cv2.imshow("Frame", img)
        #cv2.imshow("Frame2", empty_img)
        if cv2.waitKey(1) == 27:
            cv2.destroyAllWindows()
            break
        if (img != empty_img).any():
            pyautogui.press(keys='r')
            cv2.imshow("Frame", img)
            cv2.waitKey()
            break

I ask you, friends, to help me either fix this version of the solution to this problem, or come up with a better solution that works without problems (or with them :D). Thanks in advance to everyone who responds!

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question