本文介绍了处理大量RTSP摄像头,不受实时限制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
问题定义
假设我有大量的RTSP摄像头(>;100),我想对其执行一些操作,如图像特征提取。
重要提示:我对实时性能不感兴趣,我可以立即进行4次特征提取。显然,越多越好!
像现在一样,瓶颈是图像获取。帧的获取方式为cv2
有关我尝试的内容,请阅读下面的部分。伪码(当前解决方案)
while True:
for every rstp_cameras:
open_connection
read_current_frame(no batch - the real time frame)
process_frame
close
我尝试的内容
在Stackoverflow上,你可以找到很多关于实时读取RTSP摄像头的答案,但都受到摄像头数量的限制,或者都有一些缺点。我尝试过(使用python):
- 每个摄像头都有一个线程[带ffmpeg的CV2]
- 打开线程中每个摄像机的连接,然后获取每个摄像机可用的最后一帧。
- 此解决方案有效,但仅适用于少量摄像头。如果我们增加这个数字,高端CPU的使用率将达到100%(因为后台的线程总是在读取最后一帧,如果我不是在请求最后一帧,则会将其丢弃)
- [当前解决方案,无线程,带CV2的ffmpeg]每次迭代打开连接,读框,关闭连接。此解决方案允许我有最后一帧可用,但主要缺点是在打开过程中损失了时间(打开所有帧需要大约70秒)
- 带有GStreamer的CV2,无线程
- 基于此answer。是我找到的最好的解决方案如果您有少量的摄像头。对于20个或更多的摄像头,我在线程解决方案中也遇到了同样的问题。
问题总结(&A)
现在,我很清楚,在一个工作站上处理所有这些摄像头是很困难的,因为我找到的所有解决方案都是为了返回最后一个可用帧(实时帧),在后台连续读取该帧。
目前,我还没有找到一种解决方案,可以让我一次打开连接,读取低CPU使用率的实时帧,以便我可以在大量摄像头下使用它。
阅读并行化是解决问题的唯一途径吗?我的意思是,将摄像机分成几批,在不同的工作站分配批次,然后以某种方式合并图像?
谢谢。
推荐答案
您可以尝试将-discard nokey
参数与here参数一起使用。
我不确定这是否会奏效...
据我所知-discard nokey
只解码关键帧,跳过所有其他视频帧。
仅对关键帧进行解码应该会大大减少CPU使用量(取决于关键帧的频率)。
以下是一个代码示例(针对一个RTSP流):
import numpy as np
import subprocess as sp
# Use public RTSP Streaming for testing:
in_stream = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"
# Use OpenCV for getting the video resolution.
cap = cv2.VideoCapture(in_stream)
# Get resolution of input video
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# Release VideoCapture - it was used just for getting video resolution
cap.release()
# http://zulko.github.io/blog/2013/09/27/read-and-write-video-frames-in-python-using-ffmpeg/
FFMPEG_BIN = "ffmpeg" # on Linux ans Mac OS (also works on Windows when ffmpeg.exe is in the path)
ffmpeg_cmd = [FFMPEG_BIN,
'-discard', 'nokey',
'-rtsp_transport', 'tcp',
'-max_delay', '30000000', # 30 seconds
'-i', in_stream,
'-f', 'rawvideo',
'-pix_fmt', 'bgr24',
'-vcodec', 'rawvideo', '-an', 'pipe:']
# Open sub-process that gets in_stream as input and uses stdout as an output PIPE.
process = sp.Popen(ffmpeg_cmd, stdout=sp.PIPE)
while True:
raw_frame = process.stdout.read(width*height*3)
if len(raw_frame) != (width*height*3):
print('Error reading frame!') # Break the loop in case of an error (too few bytes were read).
break
# Transform the byte read into a numpy array, and reshape it to video frame dimensions
frame = np.frombuffer(raw_frame, np.uint8).reshape((height, width, 3))
# Show frame for testing
cv2.imshow('frame', frame)
cv2.waitKey(1)
process.stdout.close()
process.wait()
cv2.destroyAllWindows()
尝试如上打开100个FFmpeg子进程...
这篇关于处理大量RTSP摄像头,不受实时限制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!