Чтение видео прямо в Numpy с PyAV (без итераций) - PullRequest
1 голос
/ 29 января 2020

Можно ли читать видео прямо в 3D Numpy с помощью PyAV? В настоящее время я перебираю каждый кадр:

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

Первый кадр определяет массив 2D Numpy (i = 0); каждый последующий кадр (i> 0) укладывается в первый массив с помощью np.dstack. В идеале, я хотел бы прочитать все видео в массив черно-белых кадров Numpy, все сразу.

1 Ответ

0 голосов
/ 31 января 2020

Я не смог найти решение, использующее PyAV, и вместо него использует ffmpeg- python.

ffmpeg- python - это привязка Pythoni c для FFmpeg , как PyAV .

Код считывает все видео в массив трехмерных Numpy кадров в оттенках серого одновременно.

Решение выполняет следующие шаги:

  • Создает входной видеофайл (для тестирования).
  • Получает разрешение видеофайла с помощью «зонда».
  • Потоковое видео в байтовый массив.
  • Преобразовать байтовый массив в массив n x height x width numpy.
  • Отображение первого кадра (для тестирования).

Вот код (пожалуйста, прочитайте комментарии):

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

Вывод:
enter image description here

...