Подтвердить что ты не робот

Как узнать общее количество кадров в файле cv2 в python

Как узнать общее количество кадров в файле (.avi) через Python с помощью открытого модуля cv.

Если возможно, что вся информация (разрешение, fps, продолжительность и т.д.) мы можем получить через видеофайл.

4b9b3361

Ответ 1

С новой версией OpenCV (я использую 3.1.0) она работает следующим образом:

import cv2

cap = cv2.VideoCapture("video.mp4")
length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
print( length )

И аналогично для других свойств видео cv2.CAP_PROP_*

Ответ 2

import cv2

cap = cv2.VideoCapture(fn)

if not cap.isOpened(): 
    print "could not open :",fn
    return

length = int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT))
width  = int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT))
fps    = cap.get(cv2.cv.CV_CAP_PROP_FPS)

см. здесь для получения дополнительной информации.

также, все это с зерном соли, не все эти реквизиты являются обязательными, некоторые могут быть недоступны с вашим кодеком захвата/видео

Ответ 3

Вот как это работает с Python 3.6.5 (на Anaconda) и OpenCV 3.4.2. [Примечание]: вам нужно удалить "CV_" из "CV_CAP_PROP_xx" для любого свойства, указанного на официальном сайте OpenCV website.

import cv2
cap = cv2.VideoCapture("video.mp4")
property_id = int(cv2.CAP_PROP_FRAME_COUNT) 
length = int(cv2.VideoCapture.get(cap, property_id))
print( length )

Ответ 4

Другое решение, не зависящее от иногда багги CV_CAP_PROP, состоит в том, чтобы пересечь весь ваш видеофайл в цикле

  • Увеличивайте переменную фрейма счетчика каждый раз, когда встречается допустимый фрейм и останавливается, когда приходит недопустимый (конец видеофайла).
  • Сбор информации о разрешении сложнее, потому что некоторые кодеки поддерживают разрешение переменной (аналогично VBR в аудиофайлах, где бит-бит не является константой, а вместо этого охватывает некоторый предопределенный диапазон).

    • постоянное разрешение. В этом случае вам нужен только первый кадр, чтобы определить разрешение всего видеофайла, поэтому обход полного видео не требуется.
    • переменное разрешение - вам нужно получить разрешение каждого кадра (ширина и высота) и вычислить среднее значение для получения среднего разрешения видео
  • FPS можно рассчитать, но здесь у вас есть та же проблема, что и с константой разрешения - константы (CFR) и переменной (VFR). Это скорее проблема чересстрочной резьбы omho. Лично я использовал бы счетчик кадров, который увеличивался после каждого действительного кадра, а с интервалом в 1 секунду таймер (работает в фоновом потоке) запускал бы сохранение текущего значения счетчика и затем его сброс. Вы можете сохранить значения в списке, чтобы рассчитать среднюю/постоянную частоту кадров в конце, когда вы также узнаете общее количество кадров, которые есть в видео.

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

Преимущество заключается в том, что независимо от того, какой видеофайл у вас есть, пока OpenCV может читать из него, вы получите довольно точные результаты, в отличие от CV_CAP_PROP, которые могут работать или не работать так, как вы ожидаете.

Ответ 5

Существует два метода определения количества кадров в видеофайле

  • Метод № 1: Использование встроенных свойств OpenCV для доступа к метаинформации видеофайла который быстрый и эффективный, но неточный
  • Метод № 2: Вручную зацикливайте каждый кадр в видеофайле со счетчиком, который медленный и неэффективный, но точный

Метод № 1 быстрый и основан на функциональных возможностях видео OpenCV video property functionality, которые почти мгновенно определяют количество кадров в видеофайле. Тем не менее, существует компромисс между точностью, поскольку он зависит от версий OpenCV и видеокодеков. С другой стороны, ручной подсчет каждого кадра будет точным на 100%, хотя он будет значительно медленнее. Здесь функция, которая пытается выполнить Метод № 1 по умолчанию, в случае сбоя она автоматически использует метод № 2

def frame_count(video_path, manual=False):
    def manual_count(handler):
        frames = 0
        while True:
            status, frame = handler.read()
            if not status:
                break
            frames += 1
        return frames 

    cap = cv2.VideoCapture(video_path)
    # Slow, inefficient but 100% accurate method 
    if manual:
        frames = manual_count(cap)
    # Fast, efficient but inaccurate method
    else:
        try:
            frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
        except:
            frames = manual_count(cap)
    cap.release()
    return frames

Тесты

if __name__ == '__main__':
    import timeit
    import cv2

    start = timeit.default_timer()
    print('frames:', frame_count('fedex.mp4', manual=False))
    print(timeit.default_timer() - start, '(s)')

    start = timeit.default_timer()
    print('frames:', frame_count('fedex.mp4', manual=True))
    print(timeit.default_timer() - start, '(s)')

Результат метода 1

frames: 3671
0.018054921 (s)

Результаты метода № 2

frames: 3521
9.447095287 (s)

Обратите внимание, что два метода отличаются на 150 кадров, а метод № 2 значительно медленнее, чем метод № 1. Поэтому, если вам нужна скорость, но вы готовы пожертвовать точностью, используйте метод № 1. В ситуациях, когда у вас все хорошо с задержкой, но нужно точное количество кадров, используйте метод № 2