Предотвращение зависания камеры с помощью многопроцессного приложения Python + OpenCV - PullRequest
0 голосов
/ 10 июля 2019

У меня есть приложение Python для обработки видео в реальном времени с использованием OpenCV и камеры USB. Камера получает 30 кадров в секунду. Обработка изображения выполняется параллельно на двух разных ядрах со скоростью около 8 кадров в секунду с общей пропускной способностью ~ 16 кадров в секунду.

Я реализовал этот код с очередью размера 1, в которую записывает основной процесс. Теперь проблема заключается в том, что, как упоминалось в других вопросах (например, здесь ), изображения с камеры сохраняются в FIFO-буфере фиксированного размера, а затем читаются с VideoCapture.read(), что приводит к задержке в некоторых приложениях. С камерой, которую я использую, у меня нет контроля над этим буфером. Поэтому, поскольку буфер заполняется с большей скоростью, изображения, отправляемые дочерним процессам, не самые последние.

Я решил эту проблему, пропустив один кадр для каждой итерации. Однако новая скорость получения не совсем совпадает с пропускной способностью алгоритма. Также скорость алгоритма может измениться в будущем. Как я могу убедиться, что буфер камеры всегда пуст, чтобы избежать нежелательной задержки?

from multiprocessing import Process, Queue
import cv2
import os

VIDEO_DEVICE = 0
SKIP_N_FRAMES = 1

def img_process(img_queue):     

    while True:         
        img = img_queue.get()
        do_some_processing(img)         


def get_frame(cap):

    # skip one frame
    for i in range(SKIP_N_FRAMES):
        cap.grab()  

    retval, frame = cap.read() 

    return frame

if __name__ == '__main__':

    img_queue = Queue(1)    
    cap = cv2.VideoCapture(VIDEO_DEVICE)

    p1 = Process(target=img_process, args=(img_queue,))
    p2 = Process(target=img_process, args=(img_queue,))

    p1.start()
    p2.start()
    # assign the processes to separate cores
    os.system("taskset -p -c %d %d" % (4, p1.pid))
    os.system("taskset -p -c %d %d" % (5, p2.pid))


    while cap.isOpened():

        frame = get_frame(cap)              
        img_queue.put(frame)            

    p1.terminate()
    p2.terminate()
...