繁体   English   中英

为 opencv 'VideoCapture.read' function 设置自定义超时

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM