如何读取由scikit-image处理的mp4视频?

gag*_*gio 23 python numpy scikit-image

我想将一个scikit-image函数(特别是模板匹配函数match_template)应用于mp4视频帧的h264编码.我的应用程序跟踪每帧的时间非常重要,但我知道帧速率,因此我可以从帧编号轻松计算.

请注意我运行的资源很少,我希望尽可能保持依赖性:numpy无论如何都需要,因为我打算使用scikit-image,我会避免导入(和编译)openCV只是为了阅读视频.

我看到的底部这个scikit-image可以seamleassly存储为处理视频numpy阵列,从而获得这将是理想的.

hea*_*ad7 47

Imageio python包应该做你想要的.这是一个使用此包的python代码段:

import pylab
import imageio
filename = '/tmp/file.mp4'
vid = imageio.get_reader(filename,  'ffmpeg')
nums = [10, 287]
for num in nums:
    image = vid.get_data(num)
    fig = pylab.figure()
    fig.suptitle('image #{}'.format(num), fontsize=20)
    pylab.imshow(image)
pylab.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述 在此输入图像描述

您还可以直接迭代文件中的图像(请参阅文档):

for i, im in enumerate(vid):
    print('Mean of frame %i is %1.1f' % (i, im.mean()))
Run Code Online (Sandbox Code Playgroud)

要安装imageio,您可以使用pip:

pip install imageio
Run Code Online (Sandbox Code Playgroud)

另一种解决方案是使用moviepy(使用类似的代码来读取视频),但我认为imageio更轻,可以完成工作.


对第一条评论的回应

为了检查整个文件的标称帧速率是否相同,您可以计算迭代器中的帧数:

count = 0
try:
    for _ in vid:
        count += 1
except RuntimeError:
    print('something went wront in iterating, maybee wrong fps number')
finally:
    print('number of frames counted {}, number of frames in metada {}'.format(count, vid.get_meta_data()['nframes']))


In [10]: something went wront in iterating, maybee wrong fps number
         number of frames counted 454, number of frames in metada 461
Run Code Online (Sandbox Code Playgroud)

为了显示每个帧的时间戳:

try:
    for num, image in enumerate(vid.iter_data()):
        if num % int(vid._meta['fps']):
            continue
        else:
            fig = pylab.figure()
            pylab.imshow(image)
            timestamp = float(num)/ vid.get_meta_data()['fps']
            print(timestamp)
            fig.suptitle('image #{}, timestamp={}'.format(num, timestamp), fontsize=20)
            pylab.show()
except RuntimeError:
    print('something went wrong')
Run Code Online (Sandbox Code Playgroud)


Ale*_*x I 20

您可以使用scikit-video,如下所示:

from skvideo.io import VideoCapture

cap = VideoCapture(filename)
cap.open()

while True:
    retval, image = cap.read()
    # image is a numpy array containing the next frame
    # do something with image here
    if not retval:
        break
Run Code Online (Sandbox Code Playgroud)

这使用了引擎盖下的avconv或ffmpeg.与仅仅在avconv中解码视频相比,性能非常好,将数据移动到python的开销很小.

scikit-video的优点是API与OpenCV的视频读/写API完全相同; 只需用skvideo.io.VideoCapture替换cv2.VideoCapture即可.