Як дізнатися загальну кількість фреймів у файлі (.avi) через Python за допомогою відкритого модуля cv.
Якщо можливо, яку всю інформацію (роздільна здатність, fps, тривалість тощо) ми можемо отримати з відеофайлу за допомогою цього.
Відповіді:
У новішій версії 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_*
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)
дивіться тут для отримання додаткової інформації.
Крім того, все це з достатньою кількістю солі, не всі ці реквізити є обов’язковими, деякі можуть бути недоступні з вашим захопленням / відеокодеком
Ось як це працює з Python 3.6.5 (на Anaconda) та OpenCV 3.4.2. [Примітка]: Вам потрібно вилучити "CV_" з "CV_CAP_PROP_xx" для будь-якого майна, як вказано на офіційному веб-сайті OpenCV .
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 )
length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
Існує два методи визначення кількості кадрів у відеофайлі
Метод №1 швидкий і покладається на функціональність властивостей відео OpenCV, яка майже миттєво визначає кількість кадрів у відеофайлі. Однак існує компроміс з точністю, оскільки він залежить від версій 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 . Тому, якщо вам потрібна швидкість, але ви бажаєте пожертвувати точністю, використовуйте метод No1. У ситуаціях, коли у вас все добре із затримкою, але вам потрібна точна кількість кадрів, використовуйте метод No2
Іншим рішенням, яке не залежить від інколи помилкових помилок, CV_CAP_PROP
є обхід всього вашого відеофайлу в циклі
Збір інформації про роздільну здатність є складнішим, оскільки деякі кодеки підтримують змінну роздільну здатність (подібно до VBR в аудіофайлах, де бітрейт не є константою, а натомість охоплює певний заздалегідь визначений діапазон).
FPS можна розрахувати, проте тут у вас така ж проблема, як і з роздільною здатністю - константа (CFR) проти змінної (VFR). Це більше проблема мульти-потоків omho. Особисто я б використовував лічильник кадрів, який збільшувався після кожного дійсного кадру, тоді як з інтервалом в 1 секунду таймер (що працює у фоновому потоці) запускав би збереження поточного значення лічильника, а потім його скидання. Ви можете зберігати значення у списку, щоб підрахувати середню / постійну частоту кадрів в кінці, коли ви також будете знати загальну кількість кадрів у відео.
Недоліком цього досить спрощеного способу здійснення є те, що вам доведеться пройти весь файл, який - у випадку, якщо це триватиме кілька годин - обов’язково буде помітний користувачеві. У цьому випадку ви можете бути розумними і робити це у фоновому режимі, дозволяючи користувачеві робити щось інше, поки ваша програма збирає цю інформацію про завантажений відеофайл.
Перевага полягає в тому, що незалежно від того, який відеофайл у вас є, якщо OpenCV може з нього читати, ви отримаєте досить точні результати, на відміну від тих, CV_CAP_PROP
які можуть працювати, а можуть і не працювати, як ви очікуєте.