Помогите оптимизировать функцию в коде

Пробую написать бота, который будет самостоятельно ловить шарик в игре https://play.arkanoid.online/?lang=en

Однако

cv2.matchTemplate(frame, template, cv2.TM_CCOEFF_NORMED)

исполняется около 0.2 секунд и платформа не успевает передвигаться за шариком. Может кто-то подскажет, как можно увеличить эффективность?

с - запуск кода x - выход

import cv2
import keyboard
from threading import Thread
import time
import win32api
import dxcam


camera = dxcam.create(output_idx=0, output_color="GRAY")
camera.start()


while True:
    if keyboard.is_pressed("c"):
        flag = True
        break


def exit_check():
    global flag
    while flag:
        if keyboard.is_pressed("x"):
            flag = False
            camera.stop()
            break


def locate_ball_coordinates():
    global flag
    while flag:
        try:
            frame = camera.get_latest_frame()
            
            template = cv2.imread('ball.bmp', 0)
            start = time.time()
            result = cv2.matchTemplate(frame, template, cv2.TM_CCOEFF_NORMED)
            print(time.time() - start)
            min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
            ball_center_x, _ = max_loc

            win32api.SetCursorPos((ball_center_x+16, 1000))
            print(ball_center_x)
        except Exception:
            pass


thread1 = Thread(target=exit_check)
thread1.start()

thread2 = Thread(target=locate_ball_coordinates)
thread2.start()

thread1.join()
thread2.join()

Ответы (1 шт):

Автор решения: gord1402
  1. Уберём загрузку изображения мяча в каждом кадре
  2. Уберём лишний поток
  3. Размер региона можно уменьшить до размера нижней половины поля
  4. Добавим предсказание положения мяча в следующем кадре
from threading import Thread

import cv2
import dxcam
import keyboard
import win32api

while not keyboard.is_pressed("c"):
   pass

# Заменить region на свой
camera = dxcam.create(output_idx=0, output_color="GRAY", region=(495, 468, 1424, 1023))
camera.start()

flag = True


def locate_ball_coordinates():
   global flag
   # Заменить название на своё
   template = cv2.imread('img_2.png', 0)
   old_cord = -1
   while flag:
       if keyboard.is_pressed("x"):
           flag = False
           camera.stop()
           break
       try:
           frame = camera.get_latest_frame()

           result = cv2.matchTemplate(frame, template, cv2.TM_CCOEFF_NORMED)
           min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
           ball_center_x, _ = max_loc
           ball_center_x_corrected = ball_center_x

           if old_cord != -1:
               ball_center_x_corrected += ball_center_x - old_cord

           win32api.SetCursorPos((ball_center_x_corrected + 16 + 495, 1000))
           old_cord = ball_center_x
       except Exception:
           pass


thread2 = Thread(target=locate_ball_coordinates)
thread2.start()

thread2.join()

→ Ссылка