首页 > 解决方案 > 使用 OpenCV Python 流式传输多个 IP 摄像机会导致延迟

问题描述

我们希望定期从 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])

标签: pythonmultithreadingip-cameraopencv-pythonnvidia-jetson-nano

解决方案


推荐阅读