![image](https://i.stack.imgur.com/4c0ca.gif)
Моя гипотеза состоит в том, что джиттер наиболее вероятен из-за сетевых ограничений и возникает при отбрасывании пакета кадра. Когда кадр отбрасывается, это приводит к тому, что программа отображает последний «хороший» кадр, что приводит к зависанию дисплея. Вероятно, это проблема с аппаратным обеспечением или пропускной способностью, но некоторые из них можно решить с помощью программного обеспечения. Вот некоторые возможные изменения:
1. Установить максимальный размер буфера
Мы установили для объекта cv2.videoCapture()
ограниченный размер буфера с параметром cv2.CAP_PROP_BUFFERSIZE
. Идея состоит в том, что, ограничивая буфер, мы всегда будем иметь самый последний кадр. Это также может помочь решить проблему случайного скачка кадров вперед.
2. Установить задержку извлечения кадра
В настоящее время я считаю, что read()
читает слишком быстро, даже если он находится в своем собственном выделенном потоке. Это может быть одной из причин, по которой все кадры появляются и объединяются в следующем кадре. Например, скажем, в течение одного секунды, он может произвести 15 новых кадров, но в течение следующего интервала в одну секунду возвращаются только 3 кадра. Это может быть связано с потерей кадров сетевого пакета, поэтому для обеспечения получения постоянной частоты кадров мы просто добавляем задержку в поток поиска кадров. Задержка для получения примерно ~30
FPS делает хорошую работу для «нормализации» частоты кадров и сглаживания перехода между кадрами в случае потери пакетов.
Примечание: Мы должны попытаться сопоставить частоту кадров потока, но я не уверен, что такое FPS веб-камеры, поэтому я только предположил 30
FPS. Кроме того, обычно вместо прямого промежуточного веб-сервера используется прямая ссылка на поток, что может значительно повысить производительность.
Если вы попытаетесь использовать сохраненный .mp4
видеофайл, вы заметите, что тамнет дрожанияЭто подтверждает мое подозрение, что проблема, скорее всего, связана с задержкой в сети.
from threading import Thread
import cv2, time
class ThreadedCamera(object):
def __init__(self, src=0):
self.capture = cv2.VideoCapture(src)
self.capture.set(cv2.CAP_PROP_BUFFERSIZE, 2)
# FPS = 1/X
# X = desired FPS
self.FPS = 1/30
self.FPS_MS = int(self.FPS * 1000)
# Start frame retrieval thread
self.thread = Thread(target=self.update, args=())
self.thread.daemon = True
self.thread.start()
def update(self):
while True:
if self.capture.isOpened():
(self.status, self.frame) = self.capture.read()
time.sleep(self.FPS)
def show_frame(self):
cv2.imshow('frame', self.frame)
cv2.waitKey(self.FPS_MS)
if __name__ == '__main__':
src = 'https://videos3.earthcam.com/fecnetwork/9974.flv/chunklist_w1421640637.m3u8'
threaded_camera = ThreadedCamera(src)
while True:
try:
threaded_camera.show_frame()
except AttributeError:
pass