我们希望定期从 rtmp 流中检索帧。为此,我们有 2 个 IP 摄像机并使用两个单独的线程来不断刷新帧。主程序创建两个流,然后在每个线程上调用: getFrame(),以从每个摄像头检索最后一帧。系统运行 3 秒并从每个流中收集 3 帧(中间为 1 秒)。最后,程序将图像写入磁盘。
我们注意到帧的检索存在滞后。当我们在时间 x 请求帧时,检索到的帧是几秒前的帧。每个摄像头的延迟不同,并且随着添加到以下代码中的摄像头数量而增加。
我们已经研究了一些事情: - 我们认为 OpenCV 的缓冲区在初始化期间被填充。因此,在启动主程序之前,我们尝试通过调用 grab() 方法 50 次从缓冲区中删除图像。- 我们使用 Python 队列来存储帧,然后只抓取添加到队列中的最后一帧。
相机日期时间与 NTP 同步并显示在图像中。将此日期时间与请求帧的日期时间进行比较,会导致延迟不一致。这对于两台摄像机的变化在 2 到 10 秒之间。(有点类似于两台相机的OpenCV初始化时间)
该代码在 Nvidia JetsonNano 上运行。
我们使用以下内容在本地存储图像并给出:写入时间、相机编号和 epoch/iteration 作为文件名:
def write_local(frames, epoch, names):
for camera_number, image in enumerate(frames):
name = names[camera_number]
path = Path(".")
if type(image) == np.ndarray:
with io.BytesIO() as in_mem_file:
path = path / "test_{0}_{1}_{2}.jpg".format(epoch, name, datetime.now().strftime("%d/%m/%Y %H:%M:%S").replace(" ", "_").replace('/', '-'))
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
image = Image.fromarray(image)
image.save(in_mem_file, format='jpeg')
image.seek(0)
path.write_bytes(in_mem_file.getbuffer())
我们使用以下对象流式传输多个 rtmp 链接:
class CameraStream:
def __init__(self, rtmp_link=None):
self.currentFrame = None
self.CAMERA_WIDTH = 2560
self.CAMERA_HEIGHT = 1920
self.capture = cv2.VideoCapture(rtmp_link)
self.capture.set(cv2.CAP_PROP_FRAME_WIDTH, self.CAMERA_WIDTH)
self.capture.set(cv2.CAP_PROP_FRAME_HEIGHT, self.CAMERA_HEIGHT)
self.capture.set(cv2.CAP_PROP_BUFFERSIZE, 1)
def start(self):
self.start_time = time.time()
Thread(target=self.updateFrame, args=()).start()
def updateFrame(self):
while(True):
ret, self.current_frame = self.capture.read()
def getFrame(self):
return self.current_frame
初始化相机的:
wig_0 = webcamImageGetter(rtmp_link= 'rtmp://..')
wig_0.start()
wig_1 = webcamImageGetter(rtmp_link= 'rtmp://..')
wig_1.start()
开始会话并从相机中每秒收集一帧。
s = time.time()
time_sinds_last = 0
current_frames = []
while time.time() - s < 100:
if time.time() - s > 1:
# print the datetime when the frame is requested
print(datetime.now().strftime("%d/%m/%Y %H:%M:%S").replace(" ", "_").replace('/', '-'))
# Collect frames and store in current_frames
current_frames += [([wig_0.getFrame(), wig_1.getFrame()], len(current_frames), ['1_1', '1_2'])]
s = time.time()
# Stop after 3 epochs/iterations
if len(current_frames) > 3:
break
# write current frames to disk
for x in current_frames:
write_local(frames=x[0], epoch=x[1], names=x[2])