简体   繁体   English

使用 PyAV 将视频直接读入 Numpy(无迭代)

[英]Reading a video directly into Numpy with PyAV (no iterations)

Is it possible to read a video directly into a 3D Numpy with PyAV?是否可以使用 PyAV 将视频直接读入 3D Numpy? Currently, I am looping through each frame:目前,我正在遍历每一帧:

i = 0
container = av.open('myvideo.avi')
for frame in container.decode(video=0):
    if i == 0: V = np.array(frame.to_ndarray(format='gray'))
    else: V = np.dstack((V, np.array(frame.to_ndarray(format='gray'))))
    i += 1

The first frame defines a 2D Numpy array (i=0);第一帧定义了一个2D Numpy数组(i=0); each subsequent frame (i>0) is stacked onto the first array using np.dstack .每个后续帧 (i>0) 使用np.dstack堆叠到第一个数组上。 Ideally, I would like to read the entire video into a 3D Numpy array of grayscale frames, all at once.理想情况下,我想一次将整个视频读入灰度帧的 3D Numpy 数组。

I couldn't find a solution using PyAV, and uses ffmpeg-python instead.我找不到使用 PyAV 的解决方案,而是使用ffmpeg-python

ffmpeg-python is a Pythonic binding for FFmpeg like PyAV . ffmpeg-pythonFFmpeg的 Pythonic 绑定,如PyAV

The code reads the entire video into a 3D Numpy array of grayscale frames, all at once.该代码一次性将整个视频读入灰度帧的 3D Numpy 数组。

The solution performs the following steps:该解决方案执行以下步骤:

  • Creates an input video file (for testing).创建输入视频文件(用于测试)。
  • Gets resolution of video file using "probe".使用“探针”获取视频文件的分辨率。
  • Streams the video into byte array.将视频流式传输到字节数组中。
  • Reshape the byte array into nx height x width numpy array.将字节数组重塑为nx height x width numpy 数组。
  • Displays the first frame (for testing).显示第一帧(用于测试)。

Here is the code (please read the comments):这是代码(请阅读评论):

import ffmpeg
import numpy as np
from PIL import Image

in_filename = 'in.avi'

"""Build synthetic video, for testing begins:"""
# ffmpeg -y -r 10 -f lavfi -i testsrc=size=160x120:rate=1 -c:v libx264 -t 5 in.mp4
width, height = 160, 120

(
    ffmpeg
    .input('testsrc=size={}x{}:rate=1'.format(width, height), r=10, f='lavfi')
    .output(in_filename, vcodec='libx264', t=5)
    .overwrite_output()
    .run()
)
"""Build synthetic video ends"""


# Use ffprobe to get video frames resolution
p = ffmpeg.probe(in_filename, select_streams='v');
width = p['streams'][0]['width']
height = p['streams'][0]['height']

# https://github.com/kkroening/ffmpeg-python/blob/master/examples/README.md
# Stream the entire video as one large array of bytes
in_bytes, _ = (
    ffmpeg
    .input(in_filename)
    .video # Video only (no audio).
    .output('pipe:', format='rawvideo', pix_fmt='gray')  # Set the output format to raw video in 8 bit grayscale
    .run(capture_stdout=True)
)

n_frames = len(in_bytes) // (height*width)  # Compute the number of frames.
frames = np.frombuffer(in_bytes, np.uint8).reshape(n_frames, height, width) # Reshape buffer to array of n_frames frames (shape of each frame is (height, width)).

im = Image.fromarray(frames[0, :, :])  # Convert first frame to image object
im.show()  # Display the image

Output:输出:
在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM