Как читать видео mp4 для обработки scikit-image?

Я хотел бы применить функцию scikit-image (в частности, функцию сопоставления шаблонов match_template) к кадрам видео mp4, кодирования h264. Для моего приложения важно отслеживать время каждого кадра, но я знаю частоту кадров, поэтому могу легко рассчитать по номеру кадра.

Обратите внимание, что у меня мало ресурсов, и я хотел бы, чтобы зависимости были как можно более тонкими: numpy все равно нужен, и, поскольку я планирую использовать scikit-image, я бы не стал импортировать (и компилировать) openCV только для чтения видео.

В нижней части этой страницы я вижу, что scikit-image может легко обрабатывать видео, хранящееся в виде numpy массива, получение этого было бы таким образом идеальным.


person gaggio    schedule 18.04.2015    source источник
comment
Что ж, я попробовал openCV при разработке прототипа своего приложения на ПК. Но поскольку я собираюсь доставлять приложение на raspberry pi, я оцениваю более легкие альтернативы, а также учитывая усилия и зависимости для компиляции opencv на raspi.   -  person gaggio    schedule 19.04.2015
comment
См. также этот обзор что мы готовим для руководства пользователя.   -  person Stefan van der Walt    schedule 20.04.2015
comment
@StefanvanderWalt: обзор действительно очень полезен, спасибо. Это может быть улучшено добавлением imageio, что также решает проблему доступа к определенному номеру кадра, который также упоминается в вашем обзоре.   -  person gaggio    schedule 21.04.2015
comment
@gaggio Не могли бы вы прокомментировать запрос на включение, тогда я уверен, что автор с удовольствием включит его.   -  person Stefan van der Walt    schedule 23.04.2015


Ответы (3)


Пакет Python Imageio должен делать то, что вы хотите. Вот фрагмент 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()

введите здесь описание изображениявведите здесь описание изображения

Вы также можете напрямую перебирать изображения в файле (см. документацию):

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

Чтобы установить imageio, вы можете использовать pip:

pip install imageio

Другим решением было бы использовать 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

Чтобы отобразить временную метку каждого кадра:

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')
person head7    schedule 20.04.2015
comment
Спасибо за полезную ссылку и пример. Что не учитывается, так это время, соответствующее каждому кадру. Я попробую, время может быть в метаданных кадра, в противном случае его нужно рассчитывать по номеру кадра, что нормально при условии, что номинальная частота кадров правильно поддерживается во время записи видео. - person gaggio; 21.04.2015
comment
Хороший вопрос, и на некоторых видео номинальная частота кадров поддерживается неправильно. Чтобы проверить это, вы можете подсчитать количество кадров в итераторе и сравнить с количеством кадров в метаданных, если они равны, вы можете вычислить временную метку каждого кадра на основе frame_number / fps_rate. Я обновил свой ответ, чтобы сравнить два числа. - person head7; 22.04.2015
comment
Это хорошо работает для меня. Большое спасибо. IMO намного дружелюбнее, чем ощущение opencv ffmpeg / avconv / opencv / scikit-video. Жаль, что я обнаружил это раньше. - person rd11; 26.05.2016

Вы можете использовать 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

Это использует avconv или ffmpeg под капотом. Производительность довольно хорошая, с небольшими накладными расходами на перемещение данных в python по сравнению с простым декодированием видео в avconv.

Преимущество scikit-video заключается в том, что API точно такой же, как API чтения/записи видео OpenCV; просто замените cv2.VideoCapture на skvideo.io.VideoCapture.

person Alex I    schedule 17.08.2015

Простой способ читать видео на питоне — использовать skviode. Однострочный код может помочь прочитать все видео.

import skvideo.io  
videodata = skvideo.io.vread("video_file_name")  
print(videodata.shape)

http://mllearners.blogspot.in/2018/01/scikit-video-skvideo-tutorial-for.html

person Win GATE ECE    schedule 19.01.2018