根据存储在文本文件中的时间戳显示来自 2 个独立视频的帧

Displaying frames from 2 separate videos according to timestamps stored in a text file

我录制了来自 2 个摄像机的视频,这样我就可以在文本文件中为录制的两个视频提要获取每一帧的时间戳。

现在我想在一个帧中并排显示来自两个相机的帧,但要根据存储在文本文件中的时间。我应该怎么做?

这是从 摄像机 1摄像机 2

录制的视频的示例时间戳数据
Camera1             Camera2
0.200000047         0.000000000
33.515000047        33.315000000

现在根据时间戳文件,摄像机 1 的第 1 帧应该在 0.2 秒可见,摄像机 2 的第 1 帧应该在 0.0 秒(视频开始)可见。 摄像机 2 的第 2 帧在 33.315 秒出现,摄像机 1 的第 2 帧在 33.315000047 秒出现。

我卡在了 'how to display frames at specific time?'

像这样的大纲应该可以完成工作:

import cv2
import numpy as np
import time

# ...

CAMERA_1 = 0
CAMERA_2 = 1

def load_timestamps(camera):
    pass # Implement this

def get_next_frame(camera):
    pass # Implement this

# ...    

timestamps = [
    load_timestamps(CAMERA_1)
    , load_timestamps(CAMERA_2)
    ]

start_time = None

frame_index = [0, 0]
video_done = [False, False]

# Make those default blank images the size of your video...
# Adjust number of channels if you're using grayscale
image =  [np.zeros((100,100,3),np.uint8)] * 2

while True:
    real_time = time.time()
    if start_time is None: # First iteration only
        start_time = real_time
    current_ts = real_time - start_time
    print("ts=%0.3f s" % current_ts)

    # Advance both cameras up to current_ts
    for i in [CAMERA_1, CAMERA_2]:
        while True:
            # Get timestamp of the frame at current position
            current_index = frame_index[i]
            if current_index >= len(timestamps[i]):
                video_done[i] = True
                break # End of the video
            video_ts = timestamps[i][current_index]
            if current_ts < video_ts:
                break # The frame is in future, stop
            # The frame is in the past or present
            print("  camera %d: frame %d" % (i+1, frame_index[i]))
            image[i] = get_next_frame(i)
            frame_index[i] += 1

    cv2.imshow("Output", np.hstack([image[0], image[1]]))
    cv2.waitKey(20) # Max 50 FPS, but probably slower

    if video_done[CAMERA_1] and video_done[CAMERA_2]:
        break

我们有一个周期性运行的循环(大约每 20 毫秒,使用 cv2.waitKey(...) 中的睡眠)。

在每次迭代中,我们都会测量与第一次迭代的时间偏移,这会为我们提供一个从 0 开始的时间戳。

然后我们 "seek" 通过读取帧并将索引推进到我们的时间戳列表来 "seek" 每个视频,直到两个视频都赶上。

最后我们并排显示每个视频的最新帧。


例子

假设我们在时间戳

处有 相机 1 的 3 帧
[ 1.0, 3.0, 5.0 ]

相机 2 的 3 帧在时间戳

[ 2.0, 3.0, 4.0 ]

我们将等待时间设置为 0.5 秒以保持较短。

跟踪程序我们得到以下输出:

ts=0.000 s
ts=0.500 s
ts=1.000 s
  camera 1: frame 0
ts=1.500 s
ts=2.000 s
  camera 2: frame 0
ts=2.500 s
ts=3.000 s
  camera 1: frame 1
  camera 2: frame 1
ts=3.500 s
ts=4.000 s
  camera 2: frame 2
ts=4.500 s
ts=5.000 s
  camera 1: frame 2

和视频,每个步骤都有快照看起来像

注意:第一帧在 t=0.0 秒,最后一帧在 t=5.0 秒。


可能的改进

  • 当帧之间的间隔较长时,等待更长时间
  • 仅当至少一个 images/frame 索引发生变化时才更新显示
  • 等待计时器事件而不是休眠(很可能需要自定义 GUI)