Параллельная обработка видео с помощью OpenCV
Задача: взять видео, выполнить распознавание лица, записать видеофайл с рамкой вокруг лица обратно на диск. А чтобы сделать это быстрее, запустим процесс в нескольких потоках. Обсудить Установка необходимых библиотек Для работы понадобится установить следующие пакеты: OpenCV – cамая популярная библиотека компьютерного зрения – её мы будем использовать для чтения и записи видеофайлов. Пример использования недавно публиковался в Библиотеке программиста. Чтобы установить OpenCV, используйте FFmpeg – кроссплатформенное ПО для записи, конвертации и стриминга аудио и видео. Мы будем использовать FFmpeg для объединения нескольких видеофайлов. Страница загрузки. Импорт библиотек в Python Давайте импортируем необходимые библиотеки: Подробная информация об используемых библиотеках: Конвейер обработки видео в одном процессе Начнем с метода обработки видео в одном процессе. Именно так мы обычно читаем видеофайл, обрабатываем каждый кадр и записываем выходные кадры обратно на диск. Давайте создадим еще одну функцию, которая вызывает видеопроцессор, фиксирует время начала и конца, вычисляет время, необходимое для выполнения обработки и количество обработанных кадров в секунду. Обработка видео с использованием нескольких процессов Теперь определим другую функцию, использующую многопроцессорную обработку: В приведенной функции описана обработка, которая обычно выполняется с помощью одного процесса, но теперь она делится поровну между общим количеством процессоров, доступных на исполняющем устройстве. Если существует 4 процесса, а общее количество кадров в обрабатываемом видео равно 1000, то каждый процесс получает 250 кадров для обработки, которые выполняются параллельно. В итоге каждый процесс создаст отдельный выходной файл с видео. Чтобы объединить эти файлики мы будем использовать ffmpeg. Теперь создаем конвейер для запуска многопроцессорной обработки видео, расчета времени выполнения и кадров, обрабатываемых в секунду. Результаты Эксперимент проводился на Lenovo Yoga 920 с Ubuntu18.04. Количество доступных на устройстве логических процессоров – 8шт. Из этого эксперимента мы можем сделать вывод, что при использовании всех ядер обрабатывается в 2 раза больше кадров в секунду. Чем больше процессоров на тестовой машине, тем больше можно реализовать процессов, и тем быстрее пройдет процесс обработки.pip
:
pip3 install opencv-python
import cv2 as cv import time import subprocess as sp import multiprocessing as mp from os import remove from xailient import dnn
def process_video(): # Читаем файл с видео cap = cv.VideoCapture(file_name) # Получаем высоту, ширину и количество кадров в видео width, height = ( int(cap.get(cv.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv.CAP_PROP_FRAME_HEIGHT)) ) fps = int(cap.get(cv.CAP_PROP_FPS)) # Определяем кодек и создаем объект VideoWriter fourcc = cv.VideoWriter_fourcc('m', 'p', '4', 'v') out = cv.VideoWriter() output_file_name = "output_single.mp4" out.open(output_file_name, fourcc, fps, (width, height), True) try: while cap.isOpened(): ret, frame = cap.read() if not ret: break im = frame # Выполняем распознавание лиц в кадре _, bboxes = detectum.process_frame(im, THRESHOLD) # Цикл по списку (если он пуст, то это пропускаем) и наложение зеленых полей for i in bboxes: cv.rectangle(im, (i[0], i[1]), (i[2], i[3]), (0, 255, 0), 3) # Рисуем рамку out.write(im) except: # Высвобождаем ресурсы cap.release() out.release() # Высвобождаем ресурсы cap.release() out.release()
def single_process(): print("Обработка видео с использованием одного процесса...") start_time = time.time() process_video() end_time = time.time() total_processing_time = end_time - start_time print("Время: {}".format(total_processing_time)) print("FPS : {}".format(frame_count/total_processing_time)) file_name = "input_video.mp4" output_file_name = "output.mp4" width, height, frame_count = get_video_frame_details(file_name) print("Количество кадров = {}".format(frame_count)) print("Ширина = {}, Длина = {}".format(width, height)) single_process()
def process_video_multiprocessing(group_number): # Читаем файл с видео cap = cv.VideoCapture(file_name) cap.set(cv.CAP_PROP_POS_FRAMES, frame_jump_unit * group_number) # Получаем высоту, ширину и количество кадров в видео width, height = ( int(cap.get(cv.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv.CAP_PROP_FRAME_HEIGHT)) ) no_of_frames = int(cap.get(cv.CAP_PROP_FRAME_COUNT)) fps = int(cap.get(cv.CAP_PROP_FPS)) proc_frames = 0 # Определяем кодек и создаем объект VideoWriter fourcc = cv.VideoWriter_fourcc('m', 'p', '4', 'v') out = cv.VideoWriter() output_file_name = "output_multi.mp4" out.open("output_{}.mp4".format(group_number), fourcc, fps, (width, height), True) try: while proc_frames < frame_jump_unit: ret, frame = cap.read() if not ret: break im = frame # Выполняем распознавание лиц в каждом кадре _, bboxes = detectum.process_frame(im, THRESHOLD) # Цикл по списку (если он пуст, то это пропускаем) и наложение зеленых полей for i in bboxes: cv.rectangle(im, (i[0], i[1]), (i[2], i[3]), (0, 255, 0), 3) # Рисуем рамку out.write(im) proc_frames += 1 except: # Высвобождаем ресурсы cap.release() out.release() # Высвобождаем ресурсы cap.release() out.release()
def combine_output_files(num_processes): # Создаем список выходных файлов и складываем имена файлов в текстовый файл list_of_output_files = ["output_{}.mp4".format(i) for i in range(num_processes)] with open("list_of_output_files.txt", "w") as f: for t in list_of_output_files: f.write("file {} n".format(t)) # Используем ffmpeg для объединения выходных видеофайлов ffmpeg_cmd = "ffmpeg -y -loglevel error -f concat -safe 0 -i list_of_output_files.txt -vcodec copy " + output_file_name sp.Popen(ffmpeg_cmd, shell=True).wait() # Удаляем временные файлы for f in list_of_output_files: remove(f) remove("list_of_output_files.txt")
def multi_process(): print("Обработка видео с использованием {} процессов...".format(num_processes)) start_time = time.time() # Параллельное выполнение функции с несколькими входными значениями p = mp.Pool(num_processes) p.map(process_video_multiprocessing, range(num_processes)) combine_output_files(num_processes) end_time = time.time() total_processing_time = end_time - start_time print("Время: {}".format(total_processing_time)) print("FPS : {}".format(frame_count/total_processing_time)) file_name = "input.mp4" output_file_name = "output.mp4" width, height, frame_count = get_video_frame_details(file_name) print("Количество кадров = {}".format(frame_count)) print("Ширина= {}, Высота = {}".format(width, height)) num_processes = mp.cpu_count() print("Количество процессоров: " + str(num_processes)) frame_jump_unit = frame_count// num_processes multi_process()
- 0 views
- 0 Comment
Свежие комментарии