如何在 numpy 数组中转换视频

How to convert a video in numpy array

将视频文件转换为 NumPy 数组的程序,反之亦然。找了很多搜索引擎都没有找到答案。

人们为此使用多个库(即 PyAVdecordopencv);我个人经常使用Python OpenCV(主要使用PyTorch,但原理类似),所以我将在那里谈谈我的经验。您可以使用 cv2.VideoCapture 将视频文件加载到 numpy 数组中;理论上,您也可以使用 cv2.VideoWriter 将其写回,但实际上,我很难在自己的项目中使用它。

视频到 Numpy 数组

tl;dr:创建一个 cv2.VideoCapture 包装器;从视频中迭代加载图像(即帧)。

frames = []

path = "/path/to/my/video/file.mp4"
cap = cv2.VideoCapture(path)
ret = True
while ret:
    ret, img = cap.read() # read one frame from the 'capture' object; img is (H, W, C)
    if ret:
        frames.append(img)
video = np.stack(frames, axis=0) # dimensions (T, H, W, C)

请注意,图像将以 BGR 通道格式返回,而不是更常见的 RGB;如果需要转成RGB颜色space,img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)就够了。

Numpy 数组到视频

理论上,我看到的使用 cv2.VideoWriter 的例子是这样的

# let `video` be an array with dimensionality (T, H, W, C)
num_frames, height, width, _ = video.shape

filename = "/path/where/video/will/be/saved.mp4"
codec_id = "mp4v" # ID for a video codec.
fourcc = cv2.VideoWriter_fourcc(*code)
out = cv2.VideoWriter(filename, fourcc, 20, (width, height))

for frame in np.split(video, num_frames, axis=0):
    out.write(frame)

您也可以将帧保存到临时图像(存在许多 np.ndarray -> 图像管道;我个人使用 Pillow),然后使用 ffmpeg(命令行实用程序)进行编码帧到视频文件中。不过,这会占用更多的 space,当我需要检查视频数组的各个帧时,我会使用这种方法(在这种情况下,我会使用 ffmpeg,但那是另一回事)。

另外请注意——您可能希望根据视频编码方式更改 codec_id 变量(如果这对您来说毫无意义,请不要担心——它可能不会”对您的应用程序无关紧要);这只是一个四字节代码,用于识别用于生成视频的视频编解码器(参见 this page; availability may vary by platform(. H.264 is the most common one in use today AFAIK, which is given by code "H264" or "X264", but I've had trouble getting this to work with OpenCV (more details here);然而,array -> images -> video file 方法与命令行中的 ffmpeg 无缝协作。