Оптимизация OpenCV для одноплатника
Как можно повысить количество кадров в секунду для обнаружения объектов на плате OrangePi 3? Используется скрипт для обнаружения объектов на основе алгоритма YOLO v8 (вообще, основной целью является обнаружение людей/пешеходов), но проблема заключается в огромной задержке. Со скриптом ниже fps на плате составляет около 0.5 - 1, но с этим ещё можно мириться, если бы не огромная задержка - то, что выводит и обрабатывает плата на 5 - 10 секунд отстаёт от реальной обстановки, а это критично. Есть ли какие-нибудь способы хотя бы убрать задержку?
Код прилагаю:
import numpy as np
import cv2
from ultralytics import YOLO
import random
my_file = open("utils/coco.txt", "r") # Файл с названиями объектов
data = my_file.read()
class_list = data.split("\n")
my_file.close()
detection_colors = []
for i in range(len(class_list)):
r = random.randint(0, 255)
g = random.randint(0, 255)
b = random.randint(0, 255)
detection_colors.append((b, g, r))
model = YOLO("weights/yolov8n.pt", "v8")
frame_wid = 640
frame_hyt = 480
# cap = cv2.VideoCapture(1)
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
ret, frame = cap.read()
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
frame = cv2.resize(frame, (frame_wid, frame_hyt), cv2.INTER_NEAREST)
detect_params = model.predict(source=[frame], conf=0.45, save=False)
DP = detect_params[0].numpy()
if len(detect_params[0]) != 0:
for i in range(len(detect_params[0])):
# print(i)
boxes = detect_params[0].boxes
box = boxes[i]
clsID = box.cls.numpy()[0]
conf = box.conf.numpy()[0]
bb = box.xyxy.numpy()[0]
cv2.rectangle(
frame,
(int(bb[0]), int(bb[1])),
(int(bb[2]), int(bb[3])),
detection_colors[int(clsID)],
3,
)
font = cv2.FONT_HERSHEY_COMPLEX
cv2.putText(
frame,
class_list[int(clsID)]
+ " "
+ str(round(conf, 3))
+ "%",
(int(bb[0]), int(bb[1]) - 10),
font,
1,
(255, 255, 255),
2,
)
cv2.imshow('ObjectDetection', frame)
if cv2.waitKey(1) == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Ответы (1 шт):
- у вас идет нарастающее отставание, цикл while не успевает (сравните 25 кадров/сек и 1 кадр/сек)
- вы можете только уменьшить размер окна изображения. но будет потеря в качестве детекции
- можно поставить радиатор и разогнать микроконтроллер
- попробуйте поискать возможность обработки grayscale в настройках, все ищут решение этого вопроса, но никто не тренирует сети на градациях серого (это один канал вместо 3-х)
по первому пункту попробуйте так, будет брать кадры пореже
from imutils.video import VideoStream
# Initialize multithreading the video stream.
videostream = "rtsp://192.168.x.y/user=admin=xxxxxxx_channel=vvvv=1.sdp?params"
vs = VideoStream(src=videostream, resolution=frameSize,
framerate=32).start()
frame = vs.read()
update: по п.4. это непросто! общая картина следующая, вместо 3 слоев RGB подается на вход только градации серого. это втрое уменьшает вычисления на сетке. НО, сеть надо заново обучать, вроде всё есть, но такой сетки нет, хотя в настройках сети есть параметр ch=
Add ch argument in your MODEL.yaml, if it's not exist:
# Parameters
......
nc: 80
ch: 1 # input channels
depth_multiple: 0.33
width_multiple: 0.50
и... это не работает, либо надо проверить, может сделали.
еще там вариант превращают картинку в серое и с помощью numpy делают трёхслойку с нулевыми значениями остальных двух слоев. я не пробовал.
прим., можете сами поискать по словам: yolo grayscale ultralitics, напр.. тут https://github.com/ultralytics/yolov5/issues/6288