Как поддерживать постоянный FPS при захвате кадров с помощью opencv и python?

Я использую OpenCV4 вместе с python 3, чтобы открывать веб-камеру, захватывать кадры и отображать их в окне, как и в первом руководстве по коду, предоставленном здесь. Однако для захвата разных кадров требуется разное количество времени: иногда для захвата требуется 0,01 с, а иногда - 0,33 с, что создает задержки при отображении кадров в окне.

Есть ли способ установить постоянное время при захвате кадров, чтобы я мог видеть видео без задержек? Я думаю, что это происходит с OpenCV, потому что, когда я использую программу просмотра камеры Windows по умолчанию для просмотра видео, она отображает это нормально.

Я уже пробовал подождать некоторое время, используя time.sleep(), прежде чем снова захватить кадр. Но это не помогает.

import numpy as np
import cv2

cap = cv2.VideoCapture(0)

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()

    # Display the resulting frame
    cv2.imshow('frame',gray)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

person underfloor    schedule 25.06.2019    source источник
comment
Я не думаю, что есть какой-либо способ осуществить то, что вы описываете. Можете ли вы записать видео, а затем обработать его?   -  person Stephen Meschke    schedule 25.06.2019
comment
К сожалению, я не могу записать видео. Мне нужно, чтобы пользователь видел видео с веб-камеры в реальном времени.   -  person underfloor    schedule 25.06.2019


Ответы (3)


Один из возможных способов - установить метку времени в цикле и отслеживать время, когда был показан последний кадр. Например, вы показываете рамку только по прошествии определенного времени. В то же время вы постоянно читаете фреймы, чтобы буфер оставался пустым, чтобы гарантировать, что у вас самый последний фрейм. Вы не хотите использовать time.sleep(), потому что это заморозит программу и не оставит буфер пустым. Как только метка времени попадает, вы показываете кадр и сбрасываете метку времени.

import cv2
import time

cap = cv2.VideoCapture(0)

# Timeout to display frames in seconds
# FPS = 1/TIMEOUT 
# So 1/.025 = 40 FPS
TIMEOUT = .025
old_timestamp = time.time()

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()

    if (time.time() - old_timestamp) > TIMEOUT:
        # Display the resulting frame
        cv2.imshow('frame',frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
        old_timestamp = time.time()

# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
person nathancy    schedule 25.06.2019

Я недавно наткнулся на эту проблему. Вместо использования захвата кадров OpenCV я создал отдельный процесс - использую ffmpeg для захвата и записи их на ramdisk.

Сторожевой таймер Python позволил мне получать уведомления об обновлениях и запускать процесс распознавания текста.

Оказалось, что это быстрее и эффективнее с большой степенью детализации в управлении захватом.

person Andrew McClure    schedule 27.12.2019
comment
Не могли бы вы подробно объяснить предложенное вами решение? У вас есть пример кода для сторожевого пса Python? Спасибо - person Hung Le; 05.08.2020

При правильной работе это приложение будет приостановлено при вызове read () до тех пор, пока не станет доступен следующий кадр с потоковой веб-камеры. Плавное отображение зависит от возможности выполнить все, что вы, возможно, добавили в цикл, менее чем за 1 / FPS секунд. Это также зависит от UVC-совместимости камеры и может зависеть от алгоритма кодирования MJPEG, что характерно для большинства веб-камер. Однако тот факт, что вы видите задержку до 1/3 секунды, любопытен, потому что это типичный период GOP для mpeg или других межкадровых кодеров.

Если ничего из вышеперечисленного не относится к вашему случаю, то я подозреваю, что проблема связана с платформой, а не с проблемой OCV. Вы пытались воспроизвести проблему в другой системе?

person Roger Levy    schedule 26.03.2020