簡體   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