Время прочтения: 4 мин.
В аудиторской деятельности мы все чаще в своей работе стали обращаться к материалам камер видеонаблюдения с целью выявления отклонений в обеспечивающих процессах организации. В век высоких технологий анализ огромного объема видео осуществляется с применением различных IT инструментов, в ходе которого на первом этапе производятся действия по кадрированию (формированию фреймов) видео.
Для себя были выделены два инструмента Computer Vision, которые можно использовать для решения нашей задачи: OpenCV, MoviePy.
В тестах будут использованы:
— компьютер мощностью (Intel(R) Core(TM) i3-8109U CPU @ 3.00GHz 3.00 GHz0);
— видео формата mp4 объемом 128,72 МБ, продолжительностью 9 мин. 30 сек. (570 сек.).
В ходе кадрирования мы будем получать по 24 кадра в секунду. По итогам каждого прогона мы получим на выходе порядка 13,68 тыс. файлов, которые будут сохранены в отдельно созданные папки.
OpenCV
Устанавливаем необходимые библиотеки:
import cv2
import os
Загружаем видео и создаем папку с названием клипа, для дальнейшего сохранения в нее фреймов.
cam = cv2.VideoCapture("Путешествие муравья.mp4")
os.makedirs('data')
Запускаем процесс формирования фреймов с сохранением полученных кадров в созданной ранее папке. В данном случае при обработке 1 секунды видео будет сформировано по 24 фрейма.
%%time
#необходимо для подсчета времени, затраченное на кадрирование видео
currentframe = 0
while(True):
ret,frame = cam.read()
if ret:
name = './data/frame' + str(currentframe) + '.jpg'
cv2.imwrite(name, frame)
currentframe += 1
else:
break
Фиксируем время выполнения кода. Wall time: 18min 15s
MoviePy
Устанавливаем необходимые библиотеки:
from moviepy.editor import VideoFileClip
import numpy as np
import os
from datetime import timedelta
Загружаем видео и создаем папку с названием клипа, для дальнейшего сохранения в нее фреймов.
video_file = 'Путешествие муравья.mp4'
video_clip = VideoFileClip(video_file)
filename, _ = os.path.splitext(video_file)
if not os.path.isdir(filename):
os.mkdir(filename)
Функция format_timedelta() принимает объект timedelta и возвращает строковое отображение временной точки видео, в момент которого формируется кадр. В дальнейшем результат выполнения функции будет использован при формировании названия сохраняемого фрейма.
def format_timedelta(td):
result = str(td)
try:
result, ms = result.split(".")
except ValueError:
return result + ".00".replace(":", "-")
ms = int(ms)
ms = round(ms / 1e4)
return f"{result}.{ms:02}".replace(":", "-")
Формируем фреймы с определением шага формирования изображения в переменной step. Сохраняем результат в сформированной ранее папке:
%%time
step = 1/24
#данное значение переменной step определяет шаг кадрирования, соответствующее частоте кадров в видео (24 кадр в секунду)
for current_duration in np.arange(0, video_clip.duration, step):
frame_duration_formatted = format_timedelta(timedelta(seconds=current_duration)).replace(":", "-")
frame_filename = os.path.join(filename, f"frame{frame_duration_formatted}.jpg")
video_clip.save_frame(frame_filename, current_duration)
Фиксируем время отработки кода: Wall time: 11min 55s
Подведем итоги произведенных нами тестов CV инструментов в сводную таблицу.
Инструмент кадрирования | Продолжительность работы, мин.сек. | Общий размер формированных изображений, ГБ |
OpenCV | 4 мин. 22 сек. | 1.99 |
MoviePy | 2 мин. 00 сек. | 0.86 |
Как видим оба инструмента можно использовать при решении нашей задачи. Однако, OpenCV затрачивает больше времени на выполнение задачи и требует выделения дополнительных объемов памяти для сохранения фреймов, а MoviePy.выполнит задачу за меньший промежуток времени и с меньшим использованием дискового пространства.
Для чистоты эксперимента было проведено еще несколько тестов на основе нашего видео, конвертированного и сохраненного посредством внешней программы в разных форматах (avi, mpg, mkv). Ниже итоги тестов:
Формат видео | Размер видео после конвертации, ГБ | OpenCV | MoviePy | ||
Продолжительность работы, мин. сек. | Общий размер формированных изображений, ГБ | Продолжительность рабты, мин. сек. | Общий размер формированных изображений, ГБ | ||
.avi | 0.31 | 9 мин. 31 сек. | 3.81 | 4 мин. 23 сек. | 1.44 |
.mpg | 0.28 | 2 мин. 31 сек. | 1.01 | 1 мин. 43 сек. | 0.5 |
.mkv | 0.09 | 4 мин. 45 сек. | 1.82 | 2 мин. 8 сек. | 0.83 |
Как мы видим, дополнительно проведенные манипуляции подтверждают ранее сделанный вывод и наглядно показывают, что инструмент MoviePy имеет преимущество перед OpenCV при кадрировании, в том числе, независимо от формата, обрабатываемого видео.
Следует обратить внимание, что наилучшие показатели производительности инструментов получены при работе с файлом в формате .mpg. Время кадрирования для OpenCV оптимизировано на 50%, для MoviePy на 14%.
P.S. Через изменение частоты кадрирования видео вы можете значительно ускорить формирование фреймов.
В нашем коде кадрирование соответствует частоте кадров в видео (24-кадра в секунду). В ряде случаев такая частота кадрирования является избыточной, например, при обработке полученных изображений для детекции людей, животных, машин и прочих предметов. Это непосредственно влияет на продолжительность работы инструмента кадрирования и размеры памяти для хранения фреймов.
Путем нехитрых манипуляций мы можем уменьшить частоту формирования фреймов до 1 кадр в секунду:
Для OpenCV
currentframe = 0
while(True):
ret,frame = cam.read()
if ret & (currentframe%24==0):
name = './data/frame' + str(currentframe) + '.jpg'
cv2.imwrite(name, frame)
currentframe += 1
if ret:
continue
else:
break
Для MoviePy
В уже написанном выше коде для переменной step определяем значение, равное 1.
Подобьем итоги произведенных нами действий по уменьшению частоты кадрирования:
Инструмент кадрирования | Частота кадрирования 24 кадра в сек. | Частота кадрирования 1 кадр в сек. | ||
Продолжительность работы, мин. сек. | Общий размер формированных сообщений, ГБ | Продолжительность работы, мин. сек. | Общий размер формированных сообщений, ГБ | |
OpenCV | 4 мин. 22 сек. | 1.99 | 0 мин. 43 сек. | 0.09 |
MoviePy | 2 мин. 0 сек. | 0.86 | 0 мин. 20 сек. | 0.04 |
Таким образом, при установлении кадровой частоты извлечения изображений из видео с периодичностью 1 фрейм в секунду при обработке исходного видео вместо 13,68 тыс. изображений на выходе получим всего 0,57 тыс. кадров, что повышаем производительность инструментов Computer Vision в 6 раз.