使用 scikit-video 读/写视频文件

296 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

前言

在本节中,我们将学习如何使用 scikit-video 库函数从磁盘加载视频,该库使用 FFmpeg 软件执行视频 I/O,因此首先需要安装 FFmpeg 后再安装 scikit-video 模块。

使用 scikit-video 读取视频文件

首先导入所有必需的包:

import skvideo.io
import numpy as np
import matplotlib.pylab as plt

接下来,使用 FFmpegReader() 函数从磁盘读取视频文件,并随机显示视频中的一些图像帧。函数 FFmpegReader() 的用法如下:

skvideo.io.FFmpegReader(*args, **kwargs)

使用 FFmpeg 读取视频帧:

inputparameters = {}
outputparameters = {}
reader = skvideo.io.FFmpegReader('example.mp4',
                inputdict=inputparameters,
                outputdict=outputparameters)

提取视频文件属性

使用 getShape() 方法以及 FFmpegReader() 函数返回的对象获取视频的帧数、高度、宽度和通道数等属性:

读取视频文件属性

num_frames, height, width, num_channels = reader.getShape()
print(num_frames, height, width, num_channels)

使用 nextFrame() 方法从视频中读取帧。通过使用 NumPyrandom.choice() 函数随机选择四个帧,并显示这些帧:

plt.figure(figsize=(20,10))

frame_list = np.random.choice(num_frames, 4)
i, j = 0, 1
for frame in reader.nextFrame():
    if i in frame_list:
        plt.subplot(2,2,j)
        plt.imshow(frame)
        plt.title("Frame {}".format(i), size=20)
        plt.axis('off')
        j += 1
    i += 1
plt.show()

Figure_4.png

二值图像是只有两个不同灰度值(黑色和白色)的图像,二值图像处理通常是图像处理应用程序的主要过程之一,例如,形态学图像处理算法通常需要输入二值图像开始。要计算二值图像,最简单的方法是使用阈值算法,高于阈值的像素变为白色,低于阈值的像素均变为黑色。

使用 filters 模块中的 threshold_otsu() 函数对视频中的图像帧进行阈值处理,threshold_otsu() 函数能够将灰度图像转换为二值图像(在之后的学习中,我们会对其进行详细介绍)。

对每个颜色通道应用阈值以从图像帧中获得二值图像帧。使用 FFmpegWriter() 函数保存二值化视频,方法是按读取视频帧顺序依次叠加二值图像帧:

from skimage.color import rgb2gray
from skimage.filters import threshold_otsu

writer = skvideo.io.FFmpegWriter("r2_binary.mp4", outputdict={})
for frame in skvideo.io.vreader("r3.mp4"):
    frame = rgb2gray(frame)
    thresh = threshold_otsu(frame)
    binary = np.zeros((frame.shape[0], frame.shape[1], 3), dtype=np.uint8)
    binary[...,0] = binary[...,1] = binary[...,2] = 255*(frame > thresh).astype(np.uint8)
    writer.writeFrame(binary)
writer.close()

最后,读取刚刚保存的二进制视频,然后显示一些随机帧:

plt.figure(figsize=(20,10))

reader = skvideo.io.FFmpegReader("example_binary.mp4")
num_frames, height, width, num_channels = reader.getShape()
frame_list = np.random.choice(num_frames, 4)
i, j = 0, 1
for frame in reader.nextFrame():
    if i in frame_list:
        plt.subplot(2,2,j)
        plt.imshow(frame)
        plt.title("Frame {}".format(i), size=20)
        plt.axis('off')
        j += 1
    i += 1
plt.show()

Figure_5.png