[英]set a custom timeout for opencv 'VideoCapture.read' function
我正在编写一个从相机读取 rtps stream 的脚本。 问题是有时连接不完美,帧需要一段时间才能到达。 从我发现的内容来看,从cv2.VideoCapture
read
的 function 没有超时,我们可以在不重新编译的情况下进行修改,默认值(30 秒)对于我需要的来说太多了。
我尝试了两种方法,一种使用threading
,另一种使用multiprocessing
。 前者没有按预期工作,因为我无法足够快地终止线程并且脚本死亡。 后者意味着我在一切正常时以 1/fps 的速率创建和销毁进程,我认为这不是一个好主意。
以下是一个最小的工作示例。 当proc = True
时,它使用多处理,当proc = False
时,它使用线程。 可以使用TIMESLEEP > 0
模拟读取 function 的延迟
import cv2
import time
import queue
import psutil
import threading
import multiprocessing as mp
TIMESLEEP = 0
class FrameThread(threading.Thread):
def __init__(self, func, res):
super().__init__()
self.daemon = True
self.res = res
self.func = func
def run(self):
time.sleep(TIMESLEEP)
self.res.put(self.func)
def putframe(func, res):
time.sleep(TIMESLEEP)
res.put(func)
class Test(object):
def __init__(self, url, proc = True):
self.url = url
self.black = [1, 2, 3]
self.fps = 10
self.proc = proc
self._rq = mp.Queue() if self.proc else queue.Queue()
def _timeout_func(self, func, timeout = 10):
if self.proc:
_proc = mp.Process(target = putframe, args = (func, self._rq))
_proc.start()
else:
FrameThread(func, self._rq).start()
try:
t1 = time.time()
ret, frame = self._rq.get(block = True, timeout = timeout)
diff_fps = 1 / self.fps - (time.time() - t1)
time.sleep(diff_fps if diff_fps > 0 else 0)
if self.proc:
_proc.terminate()
frame = frame if ret else self.black.copy()
except queue.Empty:
diff_fps = 1 / self.fps - timeout
time.sleep(diff_fps if diff_fps > 0 else 0)
if self.proc:
_proc.terminate()
ret, frame = True, self.black.copy()
return ret, frame
def run(self):
cap = cv2.VideoCapture(self.url)
while True:
ret, frame = self._timeout_func(cap.read(), timeout = 0.1)
if not ret:
break
print(self.proc if self.proc else len(psutil.Process().threads()), end='\r')
proc = False
test = Test('./video.mp4', proc = proc)
test.run()
你们还有其他想法或方法吗? 或对上述代码有何改进?
谢谢!
没有尝试过这种脚本,但我看到了类似的问题,我建议你使用 e VLC python 绑定(你可以使用 pip install python-vlc 安装它)并播放 stream:
import vlc
player=vlc.MediaPlayer('rtsp://:8554/output.h264')
player.play()
然后每隔一秒左右拍摄一次快照:
while 1:
time.sleep(1)
player.video_take_snapshot(0, '.snapshot.tmp.png', 0, 0)
然后你可以使用 SimpleCV 或其他东西进行处理(只需将图像文件'.snapshot.tmp.png'加载到你的处理库中)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.