Utilisez cette technique pour appliquer des calculs intelligents à vos vidéos et réduire les secousses.
La stabilisation vidéo est une technique qui réduit les mouvements indésirables et les secousses dans les séquences vidéo. La prise de vue à main levée, les vibrations et les mouvements peuvent tous provoquer des mouvements instables de la caméra. La stabilisation vidéo produit une vidéo plus fluide.
L'objectif principal de la stabilisation vidéo est d'estimer le mouvement de la caméra entre des images consécutives. Le processus peut ensuite appliquer les transformations appropriées pour aligner les images. Cela minimise le mouvement perçu.
Configuration de votre environnement
Commence par créer un environnement virtuel pour vous assurer que les packages que vous installez pour exécuter le programme n'entrent pas en conflit avec ceux qui existent déjà. Exécutez ensuite cette commande de terminal pour installer les bibliothèques requises :
pip installer opencv-python numpy
Cette commande installe les bibliothèques NumPy et OpenCV.
NumPy fournit des outils pour les tâches numériques tandis qu'OpenCV traite des tâches de vision par ordinateur.Le code source complet est disponible dans un Référentiel GitHub.
Importation des bibliothèques requises et définition de trois fonctions cruciales
Créez un nouveau fichier Python et donnez-lui un nom de votre choix. Importez les bibliothèques NumPy et OpenCV au début du script.
importer numpy comme np
importer cv2
L'importation de ces bibliothèques vous permettra d'utiliser leurs fonctions dans votre code.
Ensuite, définissez trois fonctions qui seront cruciales pour le processus de stabilisation.
La fonction calculate_moving_average
Créez une fonction et nommez-la calculate_moving_average. Cette fonction calculera la moyenne mobile d'une courbe donnée en utilisant le rayon que vous spécifiez. Il utilise une opération de convolution avec une taille de fenêtre spécifiée et un noyau uniforme. Cette moyenne mobile permet de lisser les fluctuations de la trajectoire.
définitivementcalculate_moving_average(courbe, rayon):
# Calculer la moyenne mobile d'une courbe en utilisant un rayon donné
taille_fenêtre = 2 * rayon + 1
noyau = np.ones (taille_fenêtre) / taille_fenêtre
curve_padded = np.lib.pad (courbe, (rayon, rayon), 'bord')
courbe_lissée = np.convolve (curve_padded, noyau, mode='même')
courbe_lissée = courbe_lissée[rayon :-rayon]
retour courbe_lissée
La fonction renvoie une courbe lisse. Il aide à réduire le bruit et les fluctuations de la courbe. Pour ce faire, il fait la moyenne des valeurs dans la fenêtre glissante.
La fonction smooth_trajectory
Créez une autre fonction et nommez-la lisse_trajectoire. Cette fonction va appliquer la moyenne mobile sur chaque dimension de la trajectoire. Il y parviendra en créant une copie lissée de la trajectoire d'origine. Cela améliorera encore la stabilité de la vidéo.
définitivementlisse_trajectoire(trajectoire):
# Lisser la trajectoire en utilisant la moyenne mobile sur chaque dimension
smoothed_trajectory = np.copy (trajectoire)pour je dans gamme(3):
trajectoire_lissée[:, je] = calculate_moving_average(
trajectoire[:, je],
rayon=LISSAGE_RAYON
)
retour trajectoire_lissée
Le lisse_trajectoire La fonction renvoie une trajectoire lissée.
La fonction fix_border
Créez une fonction finale et nommez-la fix_border. Cette fonction fixera la bordure du cadre en appliquant une transformation de rotation et de mise à l'échelle. Il prend le cadre d'entrée, calcule sa forme, construit une matrice de transformation et applique la transformation au cadre. Enfin, il renvoie le cadre fixe.
définitivementfix_border(cadre):
# Fixez la bordure du cadre en appliquant une transformation de rotation et de mise à l'échelle
frame_shape = cadre.forme
matrice = cv2.getRotationMatrix2D(
(frame_shape[1] / 2, forme_cadre[0] / 2),
0,
1.04
)
frame = cv2.warpAffine (frame, matrix, (frame_shape[1], forme_cadre[0]))
retour cadre
Le fix_border La fonction garantit que les images stabilisées n'ont pas d'artefacts de bordure causés par le processus de stabilisation.
Initialisation de la stabilisation vidéo et prise de l'entrée
Commencez par définir le rayon que la fonction de lissage de trajectoire utilisera.
LISSAGE_RAYON = 50
Ensuite, passez dans le chemin vidéo de la vidéo tremblante que vous souhaitez stabiliser.
# Ouvrir le fichier vidéo d'entrée
# Remplacez le chemin par 0 pour utiliser votre webcam
cap = cv2.VideoCapture('inputvid.mp4')
Obtenez les propriétés de la vidéo tremblante :
num_frames = int (cap.get (cv2.CAP_PROP_FRAME_COUNT))
largeur = entier (cap.get (cv2.CAP_PROP_FRAME_WIDTH))
hauteur = entier (cap.get (cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get (cv2.CAP_PROP_FPS)
Définissez le format de sortie. C'est le format dans lequel le programme enregistrera la vidéo stabilisée. Vous pouvez utiliser n'importe quel format vidéo commun Tu aimes.
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
Enfin, initialisez le rédacteur vidéo :
sortie = cv2.VideoWriter('video_out.mp4', fourcc, fps, (2 * largeur hauteur))
L'extension du nom de fichier que vous transmettez au graveur vidéo doit être la même que celle que vous avez définie dans le format de sortie.
Lecture et traitement des trames
La première étape du traitement de la vidéo tremblante commence ici. Cela implique de lire les images de la vidéo d'entrée, de calculer les transformations et de remplir le tableau de transformations.
Commencez par lire la première image.
_, prev_frame = cap.read()
prev_gray = cv2.cvtColor (prev_frame, cv2.COLOR_BGR2GRAY)
Initialisez ensuite le tableau de transformation. Il stockera des informations pour chaque image.
transforme = np.zeros((num_frames - 1, 3), np.float32)
Enfin, vous devez calculer le flux optique entre les trames consécutives. Ensuite, estimez la transformation affine entre les points.
pour je dans plage (num_frames - 2):
# Calculer le flux optique entre les trames consécutives
prev_points = cv2.goodFeaturesToTrack(
prev_gray,
maxCoins=200,
niveau de qualité=0.01,
Distance min=30,
taillebloc=3
)succès, curr_frame = cap.read()
sipas succès:
cassercurr_gray = cv2.cvtColor (curr_frame, cv2.COLOR_BGR2GRAY)
curr_points, statut, erreur = cv2.calcOpticalFlowPyrLK(
prev_gray,
curr_gray,
points_précédents,
Aucun
)affirmer prev_points.shape == curr_points.shape
idx = np.où (statut == 1)[0]
prev_points = prev_points[idx]
curr_points = curr_points[idx]
# Estimer la transformation affine entre les points
matrice, _ = cv2.estimateAffine2D(prev_points, curr_points)
traduction_x = matrice[0, 2]
translation_y = matrice[1, 2]
rotation_angle = np.arctan2(matrice[1, 0], matrice[0, 0])
transforme[i] = [translation_x, translation_y, rotation_angle]
prev_gray = curr_gray
La boucle itère sur chaque image (sauf la dernière image) pour calculer les transformations. Il calcule le flux optique entre les trames consécutives en utilisant la méthode Lucas-Kanade. cv2.goodFeaturesToTrack détecte les points caractéristiques dans l'image précédente prev_gray. Alors, cv2.calcOpticalFlowPyrLK suit ces points dans l'image actuelle curr_gray.
Seuls les points avec un statut de 1 (indiquant un suivi réussi) aident à estimer une matrice de transformation affine. Le code met à jour le prev_gray variable avec le cadre en niveaux de gris actuel pour la prochaine itération.
Lisser la trajectoire
Vous devez lisser la trajectoire obtenue à partir des transformations pour obtenir un résultat stable.
# Calculer la trajectoire en additionnant cumulativement les transformations
trajectoire = np.cumsum (transforme, axe=0)# Lisser la trajectoire en utilisant la moyenne mobile
trajectoire_lissée = trajectoire_lisse (trajectoire)# Calculer la différence entre la trajectoire lissée et originale
différence = trajectoire_lissée - trajectoire
# Ajoutez la différence aux transformations d'origine pour obtenir des
# transformation
transforms_smooth = transforme + différence
Le code ci-dessus calcule la trajectoire du mouvement de la caméra et la lisse.
Cadres de stabilisation et d'écriture
La dernière étape consiste à stabiliser les images et à écrire la vidéo stabilisée dans un fichier de sortie.
Commencez par réinitialiser la capture vidéo. Cela garantit que les opérations futures seront lues à partir du début de la vidéo.
cap.set (cv2.CAP_PROP_POS_FRAMES, 0)
Stabilisez ensuite la vidéo en traitant chaque image.
# Traiter chaque image et stabiliser la vidéo
pour je dans plage (num_frames - 2):
succès, frame = cap.read()sipas succès:
cassertranslation_x = transforme_smooth[i, 0]
translation_y = transforme_smooth[i, 1]
rotation_angle = transforms_smooth[i, 2]# Créer la matrice de transformation pour la stabilisation
transformation_matrix = np.zéros((2, 3), np.float32)
matrice_transformation[0, 0] = np.cos (angle_rotation)
matrice_transformation[0, 1] = -np.sin (angle_de_rotation)
matrice_transformation[1, 0] = np.sin (angle_de_rotation)
matrice_transformation[1, 1] = np.cos (angle_rotation)
matrice_transformation[0, 2] = traduction_x
matrice_transformation[1, 2] = traduction_y# Appliquer la transformation pour stabiliser le cadre
cadre_stabilisé = cv2.warpAffine(
cadre,
transformation_matrice,
(largeur hauteur)
)# Fixer la bordure du cadre stabilisé
cadre_stabilisé = fix_border (cadre_stabilisé)# Concaténer les images d'origine et stabilisées côte à côte
frame_out = cv2.hconcat([frame, frame_pressed])# Redimensionner le cadre si sa largeur dépasse 1920 pixels
si frame_out.forme[1] > 1920:
frame_out = cv2.resize(
frame_out,
(frame_out.forme[1] // 2, frame_out.forme[0] // 2)
)# Afficher les images avant et après
cv2.imshow("Avant et après", frame_out)
cv2.waitKey(10)
# Écrire l'image dans le fichier vidéo de sortie
out.write (frame_out)
Le code ci-dessus stabilise chaque image à l'aide des transformations calculées, y compris les ajustements de translation et de rotation. Il combine ensuite les images stabilisées avec celles d'origine pour fournir une comparaison.
Libération de la capture vidéo et de l'enregistreur
Finalisez le programme en libérant les objets de capture vidéo et d'écrivain.
# Relâchez la capture vidéo et l'écrivain, et fermez toutes les fenêtres ouvertes
cap.release()
out.release()
cv2.destroyAllWindows()
Ce code ferme également toutes les fenêtres ouvertes.
Produit final du programme
La sortie du programme ressemblera à ceci :
Et voici un exemple de la vidéo stabilisée :
La sortie montre la comparaison entre la vidéo tremblante et celle stabilisée.
Explorez les capacités d'OpenCV
Vous pouvez appliquer OpenCV dans de nombreux domaines impliquant la vision par ordinateur. En effet, il offre un large éventail de fonctionnalités. Vous devriez explorer ses capacités en travaillant sur plus de projets impliquant la vision par ordinateur. Cela vous présentera de nouveaux concepts et vous donnera de nouveaux domaines de recherche.