Utilice esta técnica para aplicar algunas matemáticas inteligentes a sus videos y reducir el temblor.

La estabilización de video es una técnica que reduce el movimiento y la vibración no deseados en las secuencias de video. Las tomas manuales, la vibración y el movimiento pueden causar movimientos inestables de la cámara. La estabilización de video produce un video de aspecto más suave.

El objetivo principal de la estabilización de video es estimar el movimiento de la cámara entre fotogramas consecutivos. Luego, el proceso puede aplicar las transformaciones adecuadas para alinear los marcos. Esto minimiza el movimiento percibido.

Configuración de su entorno

Comienza por creando un entorno virtual para asegurarse de que los paquetes que instale para ejecutar el programa no entren en conflicto con los existentes. Luego ejecute este comando de terminal para instalar las bibliotecas requeridas:

pip instalar opencv-python numpy

Este comando instala las bibliotecas NumPy y OpenCV. NumPy proporciona herramientas para tareas numéricas mientras que OpenCV se ocupa de tareas de visión artificial.

instagram viewer

El código fuente completo está disponible en un repositorio GitHub.

Importación de las bibliotecas requeridas y definición de tres funciones cruciales

Cree un nuevo archivo de Python y asígnele un nombre de su agrado. Importe las bibliotecas NumPy y OpenCV al comienzo del script.

importar entumecido como notario público
importar cv2

La importación de estas bibliotecas le permitirá usar sus funciones en su código.

A continuación, defina tres funciones que serán cruciales para el proceso de estabilización.

La función calcular_promedio_móvil

Crea una función y nómbrala calcular_promedio_móvil. Esta función calculará el promedio móvil de una curva determinada utilizando el radio que especifique. Emplea una operación de convolución con un tamaño de ventana específico y un núcleo uniforme. Este promedio móvil ayuda a suavizar las fluctuaciones en la trayectoria.

definitivamentecalcular_promedio_móvil(curva, radio):
# Calcular el promedio móvil de una curva usando un radio dado
tamaño_ventana = 2 * radio + 1
kernel = np.ones (tamaño_ventana) / tamaño_ventana
curve_padded = np.lib.pad (curva, (radio, radio), 'borde')
curva_suavizada = np.convolve (curva_acolchada, núcleo, modo='mismo')
curva_suavizada = curva_suavizada[radio:-radio]
devolver curva_suavizada

La función devuelve una curva suave. Ayuda a reducir el ruido y las fluctuaciones en la curva. Lo hace promediando los valores dentro de la ventana deslizante.

La función smooth_trayectory

Crea otra función y nómbrala trayectoria_suave. Esta función aplicará la media móvil en cada dimensión de la trayectoria. Lo logrará creando una copia suavizada de la trayectoria original. Esto mejorará aún más la estabilidad del video.

definitivamentetrayectoria_suave(trayectoria):
# Suaviza la trayectoria usando el promedio móvil en cada dimensión
smoothed_trajectory = np.copia (trayectoria)

para i en rango(3):
trayectoria_suavizada[:, i] = calcular_promedio_móvil(
trayectoria[:, i],
radio=RADIO_SUAVIZANTE
)

devolver trayectoria_suavizada

El trayectoria_suave La función devuelve una trayectoria suavizada.

La función fix_border

Crea una función final y asígnale un nombre arreglar_border. Esta función arreglará el borde del marco aplicando una rotación y transformación de escala. Toma el marco de entrada, calcula su forma, construye una matriz de transformación y aplica la transformación al marco. Finalmente, devuelve el marco fijo.

definitivamentearreglar_border(marco):
# Corrija el borde del marco aplicando rotación y transformación de escala
marco_forma = marco.forma

matriz = cv2.getRotationMatrix2D(
(forma_marco[1] / 2, forma_marco[0] / 2),
0,
1.04
)

marco = cv2.warpAffine (marco, matriz, (forma_marco[1], forma_marco[0]))
devolver marco

El arreglar_border La función garantiza que los marcos estabilizados no tengan artefactos de borde causados ​​por el proceso de estabilización.

Inicializar la estabilización de video y tomar la entrada

Comience configurando el radio que utilizará la función de suavizado de trayectoria.

SUAVIZAR_RADIO = 50

Luego, pase la ruta de video del video inestable que desea estabilizar.

# Abra el archivo de video de entrada
# Reemplace la ruta con 0 para usar su cámara web
cap = cv2.VideoCapture('entradavid.mp4')

Obtenga las propiedades del video inestable:

num_frames = int (cap.get (cv2.CAP_PROP_FRAME_COUNT))
ancho = int (cap.get (cv2.CAP_PROP_FRAME_WIDTH))
altura = int (cap.get (cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get (cv2.CAP_PROP_FPS)

Establezca el formato de salida. Este es el formato con el que el programa guardará el video estabilizado. Puedes usar cualquier formato de vídeo común te gusta.

cuatrocc = cv2.VideoWriter_fourcc(*'mp4v')

Finalmente, inicialice el escritor de video:

salida = cv2.VideoWriter('video_out.mp4', cuatrocc, fps, (2 * ancho, alto))

La extensión del nombre de archivo que pasa al escritor de video debe ser la misma que la que configuró en el formato de salida.

Marcos de lectura y procesamiento

El primer paso para procesar el video inestable comienza aquí. Implica leer fotogramas del video de entrada, calcular transformaciones y completar la matriz de transformaciones.

Comience leyendo el primer cuadro.

_, marco_anterior = cap.read()
anterior_gray = cv2.cvtColor (prev_frame, cv2.COLOR_BGR2GRAY)

Luego inicialice la matriz de transformación. Almacenará información para cada cuadro.

transforma = np.zeros((num_frames - 1, 3), np.float32)

Finalmente, necesita calcular el flujo óptico entre fotogramas consecutivos. Luego, calcule la transformación afín entre los puntos.

para i en rango (num_fotogramas - 2):
# Calcula el flujo óptico entre fotogramas consecutivos
prev_points = cv2.buenascaracterísticasparaseguir(
anterior_gris,
maxCorners=200,
nivel de calidad =0.01,
minDistancia=30,
tamaño de bloque=3
)

éxito, curr_frame = cap.read()

sino éxito:
romper

curr_gray = cv2.cvtColor (curr_frame, cv2.COLOR_BGR2GRAY)

curr_points, estado, err = cv2.calcOpticalFlowPyrLK(
anterior_gris,
curr_gray,
puntos_anteriores,
Ninguno
)

afirmar prev_points.shape == curr_points.shape
idx = np.where (estado == 1)[0]
puntos_anteriores = puntos_anteriores[idx]
puntos_actuales = puntos_actuales[idx]

# Estimar la transformación afín entre los puntos
matriz, _ = cv2.estimateAffine2D(prev_points, curr_points)
traducción_x = matriz[0, 2]
traducción_y = matriz[1, 2]
ángulo_de_rotación = np.arctan2(matriz[1, 0], matriz[0, 0])
transforma[i] = [traducción_x, traducción_y, ángulo_de_rotación]
anterior_gray = curr_gray

El ciclo itera sobre cada cuadro (excepto el último cuadro) para calcular las transformaciones. Calcula el flujo óptico entre fotogramas consecutivos utilizando el método de Lucas-Kanade. cv2.buenas características para rastrear detecta puntos característicos en el cuadro anterior anterior_gray. Entonces, cv2.calcOpticalFlowPyrLK rastrea estos puntos en el marco actual curr_gray.

Solo los puntos con un estado de 1 (que indica un seguimiento exitoso) ayudan a estimar una matriz de transformación afín. El código actualiza el anterior_gray variable con el marco de escala de grises actual para la próxima iteración.

Suavizar la trayectoria

Debe suavizar la trayectoria obtenida de las transformaciones para lograr un resultado estable.

# Calcular la trayectoria sumando acumulativamente las transformaciones
trayectoria = np.cumsum (transforma, eje=0)

# Suaviza la trayectoria usando la media móvil
trayectoria_suavizada = trayectoria_suavizada (trayectoria)

# Calcula la diferencia entre la trayectoria suavizada y la original
diferencia = trayectoria_suavizada - trayectoria

# Vuelva a agregar la diferencia a las transformaciones originales para obtener
# transformaciones
transforms_smooth = transforma + diferencia

El código anterior calcula la trayectoria del movimiento de la cámara y la suaviza.

Marcos estabilizadores y de escritura

El paso final es estabilizar los cuadros y escribir el video estabilizado en un archivo de salida.

Comience por restablecer la captura de video. Esto garantiza que las operaciones futuras se leerán desde el comienzo del video.

cap.set (cv2.CAP_PROP_POS_FRAMES, 0)

Luego estabilice el video procesando cada cuadro.

# Procesa cada cuadro y estabiliza el video
para i en rango (num_fotogramas - 2):
éxito, cuadro = cap.read()

sino éxito:
romper

traducción_x = transforma_suave[i, 0]
traducción_y = transforma_suave[i, 1]
ángulo_de_rotación = transforma_suave[i, 2]

# Crear la matriz de transformación para la estabilización
transformación_matriz = np.ceros((2, 3), np.float32)
transformación_matriz[0, 0] = np.cos (ángulo_de_rotación)
transformación_matriz[0, 1] = -np.sin (ángulo_de_rotación)
transformación_matriz[1, 0] = np.sen (ángulo_de_rotación)
transformación_matriz[1, 1] = np.cos (ángulo_de_rotación)
transformación_matriz[0, 2] = traducción_x
transformación_matriz[1, 2] = traducción_y

# Aplicar la transformación para estabilizar el marco
frame_stabilized = cv2.warpAffine(
marco,
transformación_matriz,
(ancho, alto)
)

# Fijar el borde del marco estabilizado
frame_stabilized = fix_border (frame_stabilized)

# Concatenar los marcos originales y estabilizados uno al lado del otro
frame_out = cv2.hconcat([frame, frame_stabilized])

# Cambia el tamaño del marco si su ancho excede los 1920 píxeles
si marco_fuera.forma[1] > 1920:
frame_out = cv2.resize(
marco_fuera,
(marco_fuera.forma[1] // 2, marco_fuera.forma[0] // 2)
)

# Mostrar los marcos antes y después
cv2.imshow("Antes y después de", marco_fuera)
cv2.esperaClave(10)

# Escribir el marco en el archivo de video de salida
fuera.escribir (marco_fuera)

El código anterior estabiliza cada fotograma utilizando las transformaciones calculadas, incluidos los ajustes de traslación y rotación. Luego combina los marcos estabilizados con los originales para proporcionar una comparación.

Liberación de Video Capture and Writer

Finalice el programa liberando los objetos de captura y escritura de video.

# Libere la captura y el escritor de video, y cierre las ventanas abiertas
cap.liberar()
fuera.liberar()
cv2.destroyAllWindows()

Este código también cierra las ventanas abiertas.

Salida final del programa

La salida del programa se verá así:

Y aquí hay un ejemplo del video estabilizado:

La salida muestra la comparación entre el video inestable y el estabilizado.

Explore las capacidades de OpenCV

Puede aplicar OpenCV en muchos campos que involucran la visión por computadora. Esto se debe a que ofrece una amplia gama de funcionalidades. Debe explorar sus capacidades trabajando en más proyectos que involucren la visión por computadora. Esto le introducirá a nuevos conceptos y le dará nuevas áreas para investigar.