Как моя программа работает в цикле while:
- Снимок экрана с областью перед динозавром
- Циклическое переключение объектов Я хочу обнаруживать и обнаруживать с помощью cs2.matchTemplate
- Когда обнаруженная координата x объекта находится в пределах порогового значения расстояния, динозавр прыгает
Это основной скрипт:< /strong>
def main_script():
# Local variables
loop_time = 0.00001
fps_list = []
action_threshold = 280
dodge_objects = {
'big_cacti_day': GameObject(find_img('big_cacti_day.png')),
'big_cacti_night': GameObject(find_img('big_cacti_night.png')),
'bird_day': GameObject(find_img('bird_day.png')),
'bird_night': GameObject(find_img('bird_night.png')),
'small_cacti_day': GameObject(find_img('small_cacti_day.png')),
'small_cacti_night': GameObject(find_img('small_cacti_night.png')),
}
# Start the game
jump(actions)
# Game loop
with mss.mss() as sct:
monitor = {"top": 600, "left": 250, "width": 550, "height": 150}
while 1:
# FPS print for testing
print_fps(fps_list, loop_time)
loop_time = time.time()
# Update game screen
img = numpy.array(sct.grab(monitor))
game_screen = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
for key in dodge_objects:
dodge_object = dodge_objects[key]
if dodge_object.match(game_screen):
dodge_object_left_x = dodge_object.location[0][0]
cv2.rectangle(game_screen, dodge_object.location[0], dodge_object.location[1], (0,0,255), 2)
# Action
if dodge_object_left_x < action_threshold:
print(key, 'x:', dodge_object_left_x, 'y:', dodge_object_left_y)
jump(actions)
# Show recorded region
cv2.imshow('screen', game_screen)
if cv2.waitKey(1) == ord('q'):
break
Это класс GameObject
import cv2
class GameObject:
location = None
def __init__(self, path):
img = cv2.imread(path, 0)
self.img = img
self.width = img.shape[1]
self.height = img.shape[0]
def match(self, screen):
res = cv2.matchTemplate(screen, self.img, cv2.TM_CCOEFF_NORMED)
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(res)
startLoc = maxLoc
endLoc = (startLoc[0] + self.width, startLoc[1] + self.height)
if maxVal > 0.8:
self.location = (startLoc, endLoc)
return True
else:
self.location = None
return False
- Я пробовал использовать различные библиотеки захвата экрана, такие как dxcam, win32api, pyautogui, PIL, кажется, лучшая производительность — это то, что дает библиотека mss .
- Я пробовал обрезать интересующую область с помощью mss, который выделяет небольшую область 550x150 перед Дино, это улучшило производительность, но все еще недостаточно
- Я пробовал обрезать изображения объектов, чтобы уменьшить их до минимально возможного размера:



[img]https:// i.sstatic.net/mj7fGcDs.png[/img]

Похоже, что использование цикла Python и cv2.matchTemplate являются двумя основными компонентами, которые замедляют мой скрипт - с закомментированным разделом цикла for я получаю ~ 27 кадров в секунду
Если есть есть ли еще методы, которые я могу реализовать для повышения производительности моего кода, и мне бы хотелось о них услышать.
РЕДАКТИРОВАТЬ:
Я использовал профилировщик, чтобы оценить время, затраченное на мой код , я исключил cv2.waitKey, как советовали, вот как я это сделал:
- в начале main_script()
pr.enable()
start_time = time.perf_counter()
- в цикле while:
elapsed_time = current_time - start_time
if elapsed_time > 60:
break
- по прошествии 60 секунд я получаю результаты
ps = pstats.Stats(pr).sort_stats(pstats.SortKey.TIME)
ps.print_stats()
- вот первые ~30 строк результатов профилирования
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
1114 34.266 0.031 34.288 0.031 C:\Users\kubas\Desktop\100 day python coding\myenv\Lib\site-packages\mss\windows.py:203(_grab_impl)
6684 16.933 0.003 16.933 0.003 {matchTemplate}
152 7.638 0.050 7.638 0.050 {built-in method time.sleep}
1114 0.277 0.000 0.285 0.000 {built-in method numpy.array}
1114 0.245 0.000 0.245 0.000 {imshow}
6684 0.205 0.000 0.205 0.000 {minMaxLoc}
1114 0.144 0.000 0.144 0.000 {cvtColor}
75 0.067 0.001 0.067 0.001 {built-in method builtins.print}
6684 0.032 0.000 17.170 0.003 c:\Users\kubas\Desktop\100 day python coding\test\test\game_object.py:14(match)
1114 0.013 0.000 0.021 0.000 C:\Users\kubas\Desktop\100 day python coding\myenv\Lib\site-packages\mss\screenshot.py:24(__init__)
1114 0.012 0.000 34.305 0.031 C:\Users\kubas\Desktop\100 day python coding\myenv\Lib\site-packages\mss\base.py:69(grab)
76 0.010 0.000 0.011 0.000 C:\Users\kubas\Desktop\100 day python coding\myenv\Lib\site-packages\pyautogui\_pyautogui_win.py:250(_keyDown)
1114 0.006 0.000 0.008 0.000 C:\Users\kubas\Desktop\100 day python coding\myenv\Lib\site-packages\mss\screenshot.py:41(__array_interface__)
76 0.006 0.000 0.006 0.000 C:\Users\kubas\Desktop\100 day python coding\myenv\Lib\site-packages\pyautogui\_pyautogui_win.py:295(_keyUp)
2382 0.004 0.000 0.004 0.000 {built-in method __new__ of type object at 0x00007FFB757B13D0}
1370 0.003 0.000 0.003 0.000 {built-in method builtins.isinstance}
197 0.002 0.000 0.002 0.000 {rectangle}
152 0.002 0.000 0.002 0.000 C:\Users\kubas\Desktop\100 day python coding\myenv\Lib\site-packages\pyautogui\_pyautogui_win.py:335(_position)
1114 0.002 0.000 0.002 0.000 C:\Users\kubas\Desktop\100 day python coding\myenv\Lib\site-packages\mss\screenshot.py:68(height)
1114 0.002 0.000 0.002 0.000 {method '__exit__' of '_thread.lock' objects}
6 0.001 0.000 0.001 0.000 {imread}
1116 0.001 0.000 0.001 0.000 {built-in method time.perf_counter}
76 0.001 0.000 0.019 0.000 C:\Users\kubas\Desktop\100 day python coding\myenv\Lib\site-packages\pyautogui\__init__.py:1581(press)
12 0.001 0.000 0.001 0.000 {built-in method nt._getfinalpathname}
152 0.001 0.000 0.001 0.000 C:\Users\kubas\Desktop\100 day python coding\myenv\Lib\site-packages\pyautogui\__init__.py:526(isShiftCharacter)
1 0.001 0.001 0.001 0.001 C:\Users\kubas\AppData\Local\Programs\Python\Python312\Lib\ctypes\__init__.py:49(create_string_buffer)
152 0.001 0.000 0.003 0.000 C:\Users\kubas\Desktop\100 day python coding\myenv\Lib\site-packages\pyautogui\__init__.py:752(position)
76 0.001 0.000 7.661 0.101 C:\Users\kubas\Desktop\100 day python coding\myenv\Lib\site-packages\pyautogui\__init__.py:591(wrapper)
1114 0.001 0.000 0.001 0.000 C:\Users\kubas\Desktop\100 day python coding\myenv\Lib\site-packages\mss\screenshot.py:113(width)
76 0.000 0.000 7.661 0.101 c:\Users\kubas\Desktop\100 day python coding\test\test\main.py:8(jump)
152 0.000 0.000 0.004 0.000 C:\Users\kubas\Desktop\100 day python coding\myenv\Lib\site-packages\pyautogui\__init__.py:1732(failSafeCheck)
76 0.000 0.000 7.638 0.100 C:\Users\kubas\Desktop\100 day python coding\myenv\Lib\site-packages\pyautogui\__init__.py:631(_handlePause)
EDIT -> полный код main.py после введения профилирования:
import os, cv2, mss, numpy, pyautogui, numpy as np, time
from game_object import GameObject
import cProfile, pstats
def find_img(name):
return os.path.join(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'img_game'), name)
def jump():
pyautogui.press('space')
def main_script():
pr = cProfile.Profile()
pr.enable()
start_time = time.perf_counter()
# Local variables
loop_time = 0.00001
fps_list = []
action_threshold = 280
dodge_objects = {
'big_cacti_day': GameObject(find_img('big_cacti_day.png')),
'big_cacti_night': GameObject(find_img('big_cacti_night.png')),
'bird_day': GameObject(find_img('bird_day.png')),
'bird_night': GameObject(find_img('bird_night.png')),
'small_cacti_day': GameObject(find_img('small_cacti_day.png')),
'small_cacti_night': GameObject(find_img('small_cacti_night.png')),
}
# Start the game
jump()
# Game loop
with mss.mss() as sct:
monitor = {"top": 600, "left": 250, "width": 550, "height": 150}
while 1:
current_time = time.perf_counter()
elapsed_time = current_time - start_time
if elapsed_time > 60:
break
# Update game screen
img = numpy.array(sct.grab(monitor))
game_screen = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Detection
for key in dodge_objects:
dodge_object = dodge_objects[key]
if dodge_object.match(game_screen):
dodge_object_left_x = dodge_object.location[0][0]
cv2.rectangle(game_screen, dodge_object.location[0], dodge_object.location[1], (0,0,255), 2)
# Action
if dodge_object_left_x < action_threshold:
print(key, 'x:', dodge_object_left_x)
jump()
# Show recorded region - deleted waitkey
cv2.imshow('screen', img)
pr.disable()
ps = pstats.Stats(pr).sort_stats(pstats.SortKey.TIME)
ps.print_stats()
if __name__ == '__main__':
main_script()
Подробнее здесь: https://stackoverflow.com/questions/785 ... en-with-op