Используйте эту технику, чтобы применить к своим видео умную математику и уменьшить дрожание.
Стабилизация видео — это метод, который уменьшает нежелательное движение и дрожание видеоматериала. Съемка с рук, вибрация и движение могут вызвать неустойчивое движение камеры. Стабилизация видео делает видео более плавным.
Основная цель стабилизации видео — оценить движение камеры между последовательными кадрами. Затем процесс может применить соответствующие преобразования для выравнивания кадров. Это сводит к минимуму воспринимаемое движение.
Настройка вашей среды
Начать с создание виртуальной среды чтобы убедиться, что пакеты, которые вы устанавливаете для запуска программы, не конфликтуют с существующими. Затем запустите эту команду терминала, чтобы установить необходимые библиотеки:
pip установить opencv-python numpy
Эта команда устанавливает библиотеки NumPy и OpenCV. NumPy предоставляет инструменты для числовых задач в то время как OpenCV занимается задачами компьютерного зрения.
Полный исходный код доступен в Репозиторий GitHub.
Импорт необходимых библиотек и определение трех важных функций
Создайте новый файл Python и дайте ему имя по своему вкусу. Импортируйте библиотеки NumPy и OpenCV в начале скрипта.
Импортировать пустышка как нп
Импортировать cv2
Импорт этих библиотек позволит вам использовать их функции в вашем коде.
Затем определите три функции, которые будут иметь решающее значение для процесса стабилизации.
Функция calculate_moving_average
Создайте функцию и назовите ее calculate_moving_average. Эта функция будет вычислять скользящее среднее заданной кривой, используя указанный вами радиус. Он использует операцию свертки с заданным размером окна и однородным ядром. Эта скользящая средняя помогает сгладить колебания траектории.
дефcalculate_moving_average(кривая, радиус):
# Рассчитать скользящее среднее кривой, используя заданный радиус
размер_окна = 2 * радиус + 1
ядро = np.ones (размер_окна) / размер_окна
curve_padded = np.lib.pad (кривая, (радиус, радиус), 'край')
smoothed_curve = np.convolve (curve_padded, ядро, режим ='такой же')
сглаженная_кривая = сглаженная_кривая[радиус:-радиус]
возвращаться сглаженная_кривая
Функция возвращает гладкую кривую. Это помогает уменьшить шум и колебания кривой. Это делается путем усреднения значений в скользящем окне.
Функция smooth_trajectory
Создайте еще одну функцию и назовите ее Smooth_trajectory. Эта функция будет применять скользящее среднее значение для каждого измерения траектории. Это будет достигнуто за счет создания сглаженной копии исходной траектории. Это еще больше улучшит стабильность видео.
дефSmooth_trajectory(траектория):
# Сгладить траекторию, используя скользящее среднее по каждому измерению
smoothed_trajectory = np.copy (траектория)для я в диапазон(3):
smoothed_trajectory[:, i] = calculate_moving_average(
траектория [:, я],
радиус=SMOOTHING_RADIUS
)
возвращаться сглаженная_траектория
Smooth_trajectory функция возвращает сглаженную траекторию.
Функция fix_border
Создайте последнюю функцию и назовите ее fix_border. Эта функция зафиксирует границу кадра, применив вращение и преобразование масштабирования. Он берет входной кадр, вычисляет его форму, строит матрицу преобразования и применяет преобразование к кадру. Наконец, он возвращает фиксированный кадр.
дефfix_border(рамка):
# Исправить границу кадра, применив вращение и преобразование масштабирования
frame_shape = рамка.форма
матрица = cv2.getRotationMatrix2D (
(frame_shape[1] / 2, рамка_форма[0] / 2),
0,
1.04
)
кадр = cv2.warpAffine (кадр, матрица, (frame_shape[1], форма_рамки[0]))
возвращаться рамка
fix_border Функция гарантирует, что стабилизированные кадры не имеют артефактов границ, вызванных процессом стабилизации.
Инициализация стабилизации видео и получение входных данных
Начните с установки радиуса, который будет использовать функция сглаживания траектории.
РАДИУС_СГЛАЖИВАНИЯ = 50
Затем введите видеодорожку дрожащего видео, которое вы хотите стабилизировать.
# Открыть входной видеофайл
# Замените путь на 0, чтобы использовать вашу веб-камеру
крышка = cv2.VideoCapture('inputvid.mp4')
Получите свойства дрожащего видео:
num_frames = int (cap.get (cv2.CAP_PROP_FRAME_COUNT))
ширина = int (cap.get (cv2.CAP_PROP_FRAME_WIDTH))
высота = интервал (cap.get (cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get (cv2.CAP_PROP_FPS)
Установите выходной формат. Это формат, в котором программа будет сохранять стабилизированное видео. Вы можете использовать любой общий формат видео тебе нравится.
Fourcc = cv2.VideoWriter_fourcc(*'mp4v')
Наконец, инициализируйте средство записи видео:
выход = cv2.VideoWriter('video_out.mp4', фурсс, фпс, (2 * ширина высота))
Расширение имени файла, которое вы передаете автору видео, должно совпадать с тем, которое вы установили в выходном формате.
Чтение и обработка кадров
Здесь начинается первый шаг обработки дрожащего видео. Он включает в себя чтение кадров из входного видео, вычисление преобразований и заполнение массива преобразований.
Начните с чтения первого кадра.
_, пред_кадр = шапка.читать()
prev_gray = cv2.cvtColor (prev_frame, cv2.COLOR_BGR2GRAY)
Затем инициализируйте массив преобразования. Он будет хранить информацию для каждого кадра.
преобразования = np.zeros ((num_frames - 1, 3), np.float32)
Наконец, вам нужно рассчитать оптический поток между последовательными кадрами. Затем оцените аффинное преобразование между точками.
для я в диапазон (число_кадров - 2):
# Расчет оптического потока между последовательными кадрами
prev_points = cv2.goodFeaturesToTrack(
prev_gray,
МаксКорнерс=200,
уровень качества=0.01,
минРасстояние=30,
размер блока=3
)успех, curr_frame = cap.read()
еслинет успех:
перерывcurr_gray = cv2.cvtColor (curr_frame, cv2.COLOR_BGR2GRAY)
curr_points, статус, ошибка = cv2.calcOpticalFlowPyrLK(
prev_gray,
curr_gray,
пред_точки,
Никто
)утверждать prev_points.shape == curr_points.shape
idx = np.where (статус == 1)[0]
предыдущие_точки = предыдущие_точки[idx]
текущие_точки = текущие_точки[idx]
# Оценить аффинное преобразование между точками
матрица, _ = cv2.estimateAffine2D (предыдущие_точки, текущие_точки)
translation_x = матрица[0, 2]
translation_y = матрица[1, 2]
rotate_angle = np.arctan2 (матрица [1, 0], матрица[0, 0])
преобразования[i] = [перевод_x, перевод_y, угол_поворота]
предыдущий_серый = текущий_серый
Цикл перебирает каждый кадр (кроме последнего кадра) для вычисления преобразований. Он рассчитывает оптический поток между последовательными кадрами, используя метод Лукаса-Канаде. cv2.goodFeaturesToTrack обнаруживает характерные точки в предыдущем кадре prev_gray. Затем, cv2.calcOpticalFlowPyrLK отслеживает эти точки в текущем кадре curr_gray.
Только точки со статусом 1 (указывающие на успешное отслеживание) помогают в оценке матрицы аффинного преобразования. Код обновляет prev_gray переменная с текущим кадром в градациях серого для следующей итерации.
Сглаживание траектории
Вам нужно сгладить траекторию, полученную от трансформаций, чтобы добиться стабильного результата.
# Рассчитать траекторию путем кумулятивного суммирования преобразований
траектория = np.cumsum (преобразует, ось =0)# Сгладить траекторию, используя скользящее среднее
smoothed_trajectory = smooth_trajectory (траектория)# Рассчитать разницу между сглаженной и исходной траекторией
разница = сглаженная_траектория - траектория
# Добавьте разницу обратно к исходным преобразованиям, чтобы получить плавное
# трансформации
transforms_smooth = преобразования + разница
Приведенный выше код вычисляет траекторию движения камеры и сглаживает ее.
Стабилизация и запись кадров
Последним шагом является стабилизация кадров и запись стабилизированного видео в выходной файл.
Начните со сброса захвата видео. Это гарантирует, что будущие операции будут считываться с начала видео.
cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
Затем стабилизируйте видео, обрабатывая каждый кадр.
# Обрабатывать каждый кадр и стабилизировать видео
для я в диапазон (число_кадров - 2):
успех, фрейм = cap.read()еслинет успех:
перерывtranslation_x = transforms_smooth[i, 0]
translation_y = transforms_smooth[i, 1]
поворот_угол = transforms_smooth[я, 2]# Создаем матрицу трансформации для стабилизации
матрица_преобразования = np.zeros((2, 3), np.float32)
преобразование_матрица[0, 0] = np.cos (угол_поворота)
преобразование_матрица[0, 1] = -np.sin (угол_поворота)
преобразование_матрица[1, 0] = np.sin (угол_поворота)
преобразование_матрица[1, 1] = np.cos (угол_поворота)
преобразование_матрица[0, 2] = перевод_х
преобразование_матрица[1, 2] = перевод_у# Применяем трансформацию для стабилизации кадра
frame_стабилизированный = cv2.warpAffine (
рамка,
преобразование_матрица,
(ширина высота)
)# Исправить границу стабилизированного кадра
frame_стабилизированный = fix_border (frame_стабилизированный)# Объединить исходный и стабилизированный кадры рядом
frame_out = cv2.hconcat([кадр, кадр_стабилизированный])# Изменяем размер кадра, если его ширина превышает 1920 пикселей
если frame_out.shape[1] > 1920:
frame_out = cv2.resize(
кадр_выход,
(frame_out.shape[1] // 2, кадр_выход.форма[0] // 2)
)# Показать кадры до и после
cv2.imshow ("До и после", кадр_выход)
cv2.waitKey(10)
# Записываем кадр в выходной видеофайл
out.write (frame_out)
Вышеприведенный код стабилизирует каждый кадр, используя рассчитанные преобразования, включая корректировку перемещения и поворота. Затем он объединяет стабилизированные кадры с исходными для сравнения.
Выпуск видеозахвата и записи
Завершите работу программы, освободив объекты видеозахвата и записи.
# Освободите захват и запись видео и закройте все открытые окна.
крышка.релиз()
выход.выпуск()
cv2.destroyAllWindows()
Этот код также закрывает все открытые окна.
Окончательный результат программы
Вывод программы будет выглядеть примерно так:
А вот пример стабилизированного видео:
На выходе показано сравнение дрожащего видео и стабилизированного.
Изучите возможности OpenCV
Вы можете применять OpenCV во многих областях, связанных с компьютерным зрением. Это связано с тем, что он предлагает широкий спектр функций. Вам следует изучить его возможности, работая над большим количеством проектов, связанных с компьютерным зрением. Это познакомит вас с новыми концепциями и даст вам новые области для исследований.