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