Вопрос или проблема
Я создаю видео из набора изображений, генерируя каждую рамку видео с помощью Python и библиотеки CV2. Это работает.
Чтобы сделать видео более динамичным (вместо просто набора неподвижных изображений, которые появляются одно за другим), я добавил эффект зума к каждому изображению. Я в основном вычисляю для каждой рамки, насколько зум мне нужно применить, а затем немного изменяю размер рамки, используя следующий код.
# Извлекаем увеличенную часть изображения, используя координаты с плавающей точкой
zoomed_image = cv2.resize(current_image[int(y1):int(y2), int(x1):int(x2)], (res_w, res_h), interpolation=cv2.INTER_LINEAR)
Я работаю с ограничением метода cv2.resize, который принимает только целочисленные значения для координат x и y.
Это хорошо работает, когда я применяю, скажем, 5% зум к изображению, которое отображается в течение очень короткого времени. В этом случае, даже если я конвертирую x и y в целые числа, они в итоге оказываются разными для каждой рамки (при 30 fps), и следующая рамка оказывается немного другого размера по сравнению с предыдущей. Зум выходит плавным.
Но когда эффект зума применяется к изображению на более длительный срок, конвертация в целые числа приводит к тому, что несколько рамок имеют одни и те же координаты x или y, или и x, и y одинаковыми на 3-5 рамок. Это делает эффект зума рваным.
Существует ли лучший способ изменить размер изображения для цели зума, где я мог бы использовать плавающие значения координат x и y, которые я вычислил, вместо их преобразования в целые числа?
Или есть ли лучший способ применить эффект зума другим способом к каждой рамке?
Ответ или решение
Для реализации плавного эффекта зума на наборе изображений с использованием библиотеки OpenCV (CV2) в Python, вы сталкиваетесь с проблемой резкого изменения координат при преобразовании их в целые числа. Это может вызвать "дергание" при длительном отображении изображений с эффектом зума. Однако есть подход, который позволяет решить эту проблему.
Решение
Чтобы избежать проблемы с конверсией координат в целые числа, давайте будем работать с плавающей точкой и использовать метод обрезки изображения на основе плавающих значений, перед применением функции cv2.resize
. Вот как это можно реализовать:
- Координаты зума: Рассчитайте координаты для текущего зума в виде чисел с плавающей запятой.
- Обрезка изображения: Вместо того чтобы округлять координаты до целого числа, непосредственно используйте плавающие значения для обрезки изображения.
- Смещение: После обрезки изображения необходимо скорректировать его размеры, чтобы получить плавный эффект зума.
Пример кода
Ниже приведен пример реализации данного подхода:
import cv2
import numpy as np
def smooth_zoom(current_image, zoom_factor, duration, fps):
h, w = current_image.shape[:2]
zoom_steps = int(duration * fps)
zoomed_frames = []
# Определяем начальные и конечные коордианты обрезки
for step in range(zoom_steps):
alpha = step / zoom_steps
current_zoom = 1 + (zoom_factor - 1) * alpha # Линейная интерполяция
new_h = int(h / current_zoom)
new_w = int(w / current_zoom)
# Центрируем обрезку
x1 = (w - new_w) / 2
y1 = (h - new_h) / 2
x2 = (w + new_w) / 2
y2 = (h + new_h) / 2
# Используем плавающие числа для обрезки
crop_image = current_image[int(y1):int(y2), int(x1):int(x2)]
resized_image = cv2.resize(crop_image, (w, h), interpolation=cv2.INTER_LINEAR)
zoomed_frames.append(resized_image)
return zoomed_frames
# Пример использования
current_image = cv2.imread('your_image.jpg')
zoom_factor = 1.5 # Пример зума в 1.5 раза
duration = 2 # Продолжительность зума в секундах
fps = 30 # Частота кадров
frames = smooth_zoom(current_image, zoom_factor, duration, fps)
# Сохраняем видео
video_output = cv2.VideoWriter('zoomed_video.avi', cv2.VideoWriter_fourcc(*'XVID'), fps, (current_image.shape[1], current_image.shape[0]))
for frame in frames:
video_output.write(frame)
video_output.release()
Пояснения к коду:
- Координаты: Мы определяем границы обрезки по центру изображения, чтобы обеспечить симметричный зум.
- Линейная интерполяция: Мы плавно изменяем коэффициент зума от 1 до
zoom_factor
в течение указанного времени. Это позволяет избежать резких переходов. - Запись видео: После получения каждого кадра с эффектом зума вы можете использовать
cv2.VideoWriter
для создания видеофайла.
Заключение
Данный подход позволяет применять эффект зума без "дергания" и делает эффект более плавным за счет использования плавающих чисел для расчёта координат. Настраивая zoom_factor
и duration
, вы сможете артистически контролировать эффект в соответствии со своими требованиями.