Как ускорить обнаружения объекта или кода в целом?
Я попытался сделать что-то типа авто-наводчика для шутера на основе yolov4. И всё вроде бы получилось, он более-менее работает как задумано, но 3 кадра в секунду (с моими характеристиками компьютера), с учётом поворачивающейся камеры и двигающимися противниками, это слишком мало, что-бы успеть навестись, из-за чего камера просто мотается в разные стороны завидев противника. вот код:
import mss
import mss.tools
import cv2 as cv
import time
import pyautogui as pg
import numpy as np
x1, x2, x3, x4 = 0, 0, 0, 0
Conf_threshold = 0.4
NMS_threshold = 0.4
COLORS = [(0, 255, 0), (0, 0, 255), (255, 0, 0),
(255, 255, 0), (255, 0, 255), (0, 255, 255)]
class_name = []
with open('CSv3.names', 'r') as f:
class_name = [cname.strip() for cname in f.readlines()]
net = cv.dnn.readNet('CSv3_6000.weights', 'CSv3.cfg')
net.setPreferableBackend(cv.dnn.DNN_BACKEND_CUDA)
net.setPreferableTarget(cv.dnn.DNN_TARGET_CUDA_FP16)
model = cv.dnn_DetectionModel(net)
model.setInputParams(size=(416, 416), scale=1/255, swapRB=True)
with mss.mss() as sct:
monitor = {"top": 0, "left": 0, "width": 1920, "height": 1080}
output = "sct-{top}x{left}_{width}x{height}.png".format(**monitor)
starting_time = time.time()
frame_counter = 0
while True:
sct_img = sct.grab(monitor)
mss.tools.to_png(sct_img.rgb, sct_img.size, output=output)
print(output)
cap = cv.imread(output)
x1, x2, x3, x4 = 0, 0, 0, 0
frame = cap
frame_counter += 1
classes, scores, boxes = model.detect(frame, Conf_threshold, NMS_threshold)
for (classid, score, box) in zip(classes, scores, boxes):
color = COLORS[int(classid) % len(COLORS)]
label = "%s : %f" % (class_name[classid[0]], score)
cv.rectangle(frame, box, color, 1)
x1, x2, x3, x4 = box[0], box[2], box[1], box[3]
print (box[0], box[2], box[1], box[3])
cv.putText(frame, label, (box[0], box[1]-10),
cv.FONT_HERSHEY_COMPLEX, 0.3, color, 1)
if x1 > 0:
pg.moveTo(x1+x2/2, x3+x4/3)
else:
pass
endingTime = time.time() - starting_time
fps = frame_counter/endingTime
cv.putText(frame, f'FPS: {fps}', (20, 50),
cv.FONT_HERSHEY_COMPLEX, 0.7, (0, 255, 0), 2)
cv.imshow('frame', frame)
key = cv.waitKey(1)
if key == ord('q'):
break
cap.release()
cv.destroyAllWindows()
Гитхаб где можно скачать веса: https://github.com/Imandyr/Auto-aim-bot-YOLOv4-python-CS-1.6
Что можно сделать, что бы его ускорить?
UPD: Поэксперементировав, обнаружил, что даже без самого обнаружения обьектов на кадре, лишь при его получении и отображении, скорость работы лишь чуть-чуть больше чем с обнаружением обьектов.
Ответы (2 шт):
Я бы советовал так попрофайлить
import contextlib
import time
def some_lib_func():
time.sleep(3)
@contextlib.contextmanager
def profiler_register_time_context(func_name):
start = time.perf_counter()
yield
delta = time.perf_counter() - start
print(f"{func_name} worked {delta}s")
with profiler_register_time_context("some_lib_func"):
some_lib_func()
В общем я понял, что ускорить тут просто никак, так-как этот код:
import time
import cv2
import mss
import numpy as np
with mss.mss() as sct:
monitor = {"top": 40, "left": 0, "width": 1920, "height": 1080}
output = "sct-{top}x{left}_{width}x{height}.png".format(**monitor)
while "Screen capturing":
last_time = time.time()
img = sct.grab(monitor)
mss.tools.to_png(img.rgb, img.size, output=output)
print(output)
img = cv2.imread(output)
cv2.imshow("img", img)
if cv2.waitKey(25) & 0xFF == ord("q"):
cv2.destroyAllWindows()
break
не содержащий никаких действий кроме делания снимка, конвертации в грб(без которой не работает детекция) и вывода, показывает практически те же результаты что и вместе со всем остальным, то-есть дело всё именно в этом, но не один из пунктов пропустить нельзя, я пытался.
Я ещё пробовал этот код из документации по mss:
import time
import cv2
import mss
import numpy
with mss.mss() as sct:
# Part of the screen to capture
monitor = {"top": 40, "left": 0, "width": 800, "height": 640}
while "Screen capturing":
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("OpenCV/Numpy normal", img)
# Display the picture in grayscale
# cv2.imshow('OpenCV/Numpy grayscale',
# cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY))
print("fps: {}".format(1 / (time.time() - last_time)))
# Press "q" to quit
if cv2.waitKey(25) & 0xFF == ord("q"):
cv2.destroyAllWindows()
break
очень быстро транслирует экран, но проблема в том, что с массивом numpy банально не удаётся провести нужных мне манипуляций (ну, или у меня просто не получается), так-что ничего не поделать.