Используйте эту технику, чтобы применить к своим видео умную математику и уменьшить дрожание.

Стабилизация видео — это метод, который уменьшает нежелательное движение и дрожание видеоматериала. Съемка с рук, вибрация и движение могут вызвать неустойчивое движение камеры. Стабилизация видео делает видео более плавным.

Основная цель стабилизации видео — оценить движение камеры между последовательными кадрами. Затем процесс может применить соответствующие преобразования для выравнивания кадров. Это сводит к минимуму воспринимаемое движение.

Настройка вашей среды

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

pip установить opencv-python numpy

Эта команда устанавливает библиотеки NumPy и OpenCV. NumPy предоставляет инструменты для числовых задач в то время как OpenCV занимается задачами компьютерного зрения.

Полный исходный код доступен в Репозиторий GitHub.

instagram viewer

Импорт необходимых библиотек и определение трех важных функций

Создайте новый файл 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 во многих областях, связанных с компьютерным зрением. Это связано с тем, что он предлагает широкий спектр функций. Вам следует изучить его возможности, работая над большим количеством проектов, связанных с компьютерным зрением. Это познакомит вас с новыми концепциями и даст вам новые области для исследований.