<p><img src="https://i.stack.imgur.com/4c0ca.gif" width="425"/></p>
<p>我的假设是,抖动最有可能是由于网络的限制,并且在帧包被丢弃时发生。当一个帧被删除时,这将导致程序显示最后一个“良好”帧,这将导致显示冻结。这可能是硬件或带宽的问题,但我们可以通过软件来缓解一些问题。以下是一些可能的更改:</p>
<p><strong>1。设置最大缓冲区大小</strong></p>
<p>我们使用<code>cv2.videoCapture()</code>参数将<code>cv2.videoCapture()</code>对象设置为具有有限的缓冲区大小。我们的想法是,通过限制缓冲区,我们将始终拥有最新的帧。这也有助于缓解帧随机向前跳的问题。在</p>
<p><strong>2。设置帧检索延迟</strong></p>
<p>目前,我认为<code>read()</code>读得太快了,尽管它在自己的专用线程中。这可能是为什么所有帧看起来都聚集在一起并在下一帧中突然爆裂的原因之一。例如,在一秒的时间间隔内,它可能产生15个新的帧,但是在下一个1秒的时间间隔内,只返回3个帧。这可能是由于网络包的帧丢失,所以为了保证我们获得恒定的帧速率,我们只需在帧检索线程中增加一个延迟。获得大约<code>~30</code>FPS的延迟可以很好地“规范化”帧速率,并在出现包丢失的情况下平滑帧之间的转换。在</p>
<p><strong>注意:</strong>我们应该尝试匹配流的帧速率,但我不确定网络摄像头的帧速率是多少,所以我只是猜测了<code>30</code>FPS。此外,通常有一个“直接”流链接,而不是通过中间的web服务器,这可以大大提高性能。在</p>
<hr/>
<p>如果您尝试使用保存的<code>.mp4</code>视频文件,您将注意到没有抖动。这证实了我的怀疑,问题很可能是由于网络延迟造成的。在</p>
<pre><code>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
</code></pre>