Verwenden Sie diese Technik, um clevere Mathematik auf Ihre Videos anzuwenden und Verwacklungen zu reduzieren.

Die Videostabilisierung ist eine Technik, die unerwünschte Bewegungen und Verwacklungen im Videomaterial reduziert. Handaufnahmen, Vibrationen und Bewegungen können zu instabilen Kamerabewegungen führen. Die Videostabilisierung sorgt für ein flüssigeres Video.

Das Hauptziel der Videostabilisierung besteht darin, die Bewegung der Kamera zwischen aufeinanderfolgenden Bildern abzuschätzen. Der Prozess kann dann geeignete Transformationen anwenden, um die Frames auszurichten. Dadurch wird die wahrgenommene Bewegung minimiert.

Einrichten Ihrer Umgebung

Beginnen Sie mit Erstellen einer virtuellen Umgebung um sicherzustellen, dass die Pakete, die Sie zum Ausführen des Programms installieren, nicht mit vorhandenen Paketen in Konflikt geraten. Führen Sie dann diesen Terminalbefehl aus, um die erforderlichen Bibliotheken zu installieren:

pip installiere opencv-python numpy

Dieser Befehl installiert NumPy- und OpenCV-Bibliotheken.

instagram viewer
NumPy bietet Werkzeuge für numerische Aufgaben während OpenCV sich mit Computer-Vision-Aufgaben befasst.

Der vollständige Quellcode ist in a verfügbar GitHub-Repository.

Importieren der erforderlichen Bibliotheken und Definieren von drei entscheidenden Funktionen

Erstellen Sie eine neue Python-Datei und geben Sie ihr einen Namen nach Ihren Wünschen. Importieren Sie NumPy- und OpenCV-Bibliotheken am Anfang des Skripts.

importieren Numpy als np
importieren Lebenslauf 2

Durch den Import dieser Bibliotheken können Sie deren Funktionen in Ihrem Code verwenden.

Definieren Sie als Nächstes drei Funktionen, die für den Stabilisierungsprozess entscheidend sind.

Die Funktion „calcure_moving_average“.

Erstellen Sie eine Funktion und benennen Sie sie berechne den gleitenden_Durchschnitt. Diese Funktion berechnet den gleitenden Durchschnitt einer bestimmten Kurve anhand des von Ihnen angegebenen Radius. Es verwendet eine Faltungsoperation mit einer bestimmten Fenstergröße und einem einheitlichen Kernel. Dieser gleitende Durchschnitt hilft, Schwankungen in der Flugbahn auszugleichen.

defberechne den gleitenden_Durchschnitt(Kurve, Radius):
# Berechnen Sie den gleitenden Durchschnitt einer Kurve mit einem gegebenen Radius
window_size = 2 * Radius + 1
kernel = np.ones (window_size) / window_size
Curve_padded = np.lib.pad (Kurve, (Radius, Radius), 'Rand')
Smoothed_curve = np.convolve (curve_padded, Kernel, Mode='Dasselbe')
Smoothed_curve = Smoothed_curve[Radius:-Radius]
zurückkehren geglättete_Kurve

Die Funktion gibt eine glatte Kurve zurück. Es hilft, Geräusche und Schwankungen in der Kurve zu reduzieren. Dies geschieht durch Mittelung der Werte innerhalb des Schiebefensters.

Die Funktion „smooth_trajectory“.

Erstellen Sie eine weitere Funktion und benennen Sie sie glatte_Trajektorie. Diese Funktion wendet den gleitenden Durchschnitt auf jede Dimension der Flugbahn an. Dies wird erreicht, indem eine geglättete Kopie der ursprünglichen Flugbahn erstellt wird. Dadurch wird die Stabilität des Videos weiter verbessert.

defglatte_Trajektorie(Flugbahn):
# Glätten Sie die Flugbahn mithilfe des gleitenden Durchschnitts für jede Dimension
Smoothed_trajectory = np.copy (Flugbahn)

für ich In Bereich(3):
Smoothed_trajectory[:, i] = berechne_bewegenden_Durchschnitt(
Flugbahn[:, i],
radius=SMOOTHING_RADIUS
)

zurückkehren geglättete_Trajektorie

Der glatte_Trajektorie Die Funktion gibt eine geglättete Flugbahn zurück.

Die fix_border-Funktion

Erstellen Sie eine endgültige Funktion und benennen Sie sie fix_border. Diese Funktion fixiert den Rand des Rahmens durch Anwenden einer Rotations- und Skalierungstransformation. Es nimmt den Eingaberahmen, berechnet seine Form, erstellt eine Transformationsmatrix und wendet die Transformation auf den Rahmen an. Schließlich wird der feste Rahmen zurückgegeben.

deffix_border(rahmen):
# Korrigieren Sie den Rahmenrand, indem Sie eine Rotations- und Skalierungstransformation anwenden
Frame_Shape = Frame.Shape

Matrix = cv2.getRotationMatrix2D(
(frame_shape[1] / 2, Frame_Shape[0] / 2),
0,
1.04
)

Frame = cv2.warpAffine (Frame, Matrix, (frame_shape[1], Frame_Shape[0]))
zurückkehren rahmen

Der fix_border Die Funktion stellt sicher, dass die stabilisierten Bilder keine durch den Stabilisierungsprozess verursachten Randartefakte aufweisen.

Initialisierung der Videostabilisierung und Übernahme der Eingabe

Stellen Sie zunächst den Radius ein, den die Funktion zur Flugbahnglättung verwenden soll.

SMOOTHING_RADIUS = 50

Übergeben Sie dann den Videopfad des verwackelten Videos, das Sie stabilisieren möchten.

# Öffnen Sie die Eingabevideodatei
# Ersetzen Sie den Pfad durch 0, um Ihre Webcam zu verwenden
cap = cv2.VideoCapture('inputvid.mp4')

Holen Sie sich die Eigenschaften des verwackelten Videos:

num_frames = int (cap.get (cv2.CAP_PROP_FRAME_COUNT))
width = int (cap.get (cv2.CAP_PROP_FRAME_WIDTH))
height = int (cap.get (cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get (cv2.CAP_PROP_FPS)

Legen Sie das Ausgabeformat fest. Dies ist das Format, in dem das Programm das stabilisierte Video speichert. Sie können jedes verwenden gängiges Videoformat du magst.

fourcc = cv2.VideoWriter_fourcc(*'mp4v')

Initialisieren Sie abschließend den Video-Writer:

out = cv2.VideoWriter('video_out.mp4', fourcc, fps, (2 * Breite Höhe))

Die Erweiterung des Dateinamens, den Sie an den Video-Writer übergeben, sollte mit der Erweiterung übereinstimmen, die Sie im Ausgabeformat festgelegt haben.

Frames lesen und verarbeiten

Hier beginnt der erste Schritt der Verarbeitung des verwackelten Videos. Dazu gehört das Lesen von Frames aus dem Eingabevideo, das Berechnen von Transformationen und das Auffüllen des Transformations-Arrays.

Beginnen Sie mit dem Lesen des ersten Frames.

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

Initialisieren Sie dann das Transformationsarray. Es werden Informationen für jeden Frame gespeichert.

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

Schließlich müssen Sie den optischen Fluss zwischen aufeinanderfolgenden Bildern berechnen. Schätzen Sie dann die affine Transformation zwischen den Punkten.

für ich In Bereich (num_frames - 2):
# Berechnen Sie den optischen Fluss zwischen aufeinanderfolgenden Bildern
prev_points = cv2.goodFeaturesToTrack(
prev_gray,
maxCorners=200,
qualitätsLevel=0.01,
minDistance=30,
blockSize=3
)

Erfolg, curr_frame = cap.read()

Wennnicht Erfolg:
brechen

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

curr_points, status, err = cv2.calcOpticalFlowPyrLK(
prev_gray,
curr_gray,
prev_points,
Keiner
)

behaupten prev_points.shape == curr_points.shape
idx = np.where (status == 1)[0]
prev_points = prev_points[idx]
curr_points = curr_points[idx]

# Schätzen Sie die affine Transformation zwischen den Punkten
Matrix, _ = cv2.estimateAffine2D(prev_points, curr_points)
translation_x = Matrix[0, 2]
translation_y = Matrix[1, 2]
rotation_angle = np.arctan2(matrix[1, 0], Matrix[0, 0])
transforms[i] = [translation_x, translation_y, rotation_angle]
prev_gray = curr_gray

Die Schleife durchläuft jeden Frame (mit Ausnahme des letzten Frames), um Transformationen zu berechnen. Es berechnet den optischen Fluss zwischen aufeinanderfolgenden Bildern mithilfe der Lucas-Kanade-Methode. cv2.goodFeaturesToTrack Erkennt Feature-Punkte im vorherigen Frame prev_gray. Dann, cv2.calcOpticalFlowPyrLK Verfolgt diese Punkte im aktuellen Frame curr_gray.

Nur die Punkte mit dem Status 1 (was eine erfolgreiche Verfolgung anzeigt) helfen bei der Schätzung einer affinen Transformationsmatrix. Der Code aktualisiert die prev_gray Variable mit dem aktuellen Graustufenrahmen für die nächste Iteration.

Glättung der Flugbahn

Sie müssen die aus den Transformationen erhaltene Flugbahn glätten, um ein stabiles Ergebnis zu erzielen.

# Berechnen Sie die Flugbahn, indem Sie die Transformationen kumulativ summieren
trajectory = np.cumsum (transformiert, axis=0)

# Glätten Sie die Flugbahn mithilfe des gleitenden Durchschnitts
Smoothed_trajectory = Smooth_trajectory (Flugbahn)

# Berechnen Sie die Differenz zwischen der geglätteten und der ursprünglichen Flugbahn
Differenz = Smoothed_Trajectory – Flugbahn

# Addieren Sie die Differenz wieder zu den ursprünglichen Transformationen, um eine glatte zu erhalten
# Transformationen
transforms_smooth = Transformationen + Differenz

Der obige Code berechnet die Flugbahn der Kamerabewegung und glättet sie.

Stabilisierungs- und Schreibrahmen

Der letzte Schritt besteht darin, die Frames zu stabilisieren und das stabilisierte Video in eine Ausgabedatei zu schreiben.

Beginnen Sie mit dem Zurücksetzen der Videoaufnahme. Dadurch wird sichergestellt, dass zukünftige Vorgänge vom Beginn des Videos an gelesen werden.

cap.set (cv2.CAP_PROP_POS_FRAMES, 0)

Stabilisieren Sie dann das Video, indem Sie jedes Bild verarbeiten.

# Verarbeiten Sie jedes Bild und stabilisieren Sie das Video
für ich In Bereich (num_frames - 2):
Erfolg, Frame = cap.read()

Wennnicht Erfolg:
brechen

translation_x = transforms_smooth[i, 0]
translation_y = transforms_smooth[i, 1]
rotation_angle = transforms_smooth[i, 2]

# Erstellen Sie die Transformationsmatrix zur Stabilisierung
transformation_matrix = np.zeros((2, 3), np.float32)
transformationsmatrix[0, 0] = np.cos (Rotationswinkel)
transformationsmatrix[0, 1] = -np.sin (Rotationswinkel)
transformationsmatrix[1, 0] = np.sin (Rotationswinkel)
transformationsmatrix[1, 1] = np.cos (Rotationswinkel)
transformationsmatrix[0, 2] = translation_x
transformationsmatrix[1, 2] = translation_y

# Wenden Sie die Transformation an, um den Rahmen zu stabilisieren
frame_stabilized = cv2.warpAffine(
rahmen,
transformation_matrix,
(Breite Höhe)
)

# Fixieren Sie den Rand des stabilisierten Rahmens
frame_stabilized = fix_border (frame_stabilized)

# Verketten Sie die ursprünglichen und stabilisierten Frames nebeneinander
Frame_out = cv2.hconcat([Frame, Frame_Stabilized])

# Ändern Sie die Größe des Rahmens, wenn seine Breite 1920 Pixel überschreitet
Wenn frame_out.shape[1] > 1920:
frame_out = cv2.resize(
Frame_out,
(frame_out.shape[1] // 2, frame_out.shape[0] // 2)
)

# Zeigen Sie die Vorher- und Nachher-Frames an
cv2.imshow("Vorher und nachher", Frame_out)
cv2.waitKey(10)

# Schreiben Sie den Frame in die Ausgabevideodatei
out.write (frame_out)

Der obige Code stabilisiert jeden Frame mithilfe der berechneten Transformationen, einschließlich Übersetzungs- und Rotationsanpassungen. Anschließend werden die stabilisierten Bilder mit den Originalbildern kombiniert, um einen Vergleich zu ermöglichen.

Freigabe des Video Capture und Writers

Schließen Sie das Programm ab, indem Sie die Videoaufnahme- und Writer-Objekte freigeben.

# Lassen Sie die Videoaufnahme und den Schreiber los und schließen Sie alle geöffneten Fenster
cap.release()
out.release()
cv2.destroyAllWindows()

Dieser Code schließt auch alle geöffneten Fenster.

Endgültige Programmausgabe

Die Ausgabe des Programms sieht etwa so aus:

Und hier ist ein Beispiel des stabilisierten Videos:

Die Ausgabe zeigt den Vergleich zwischen dem verwackelten und dem stabilisierten Video.

Entdecken Sie die OpenCV-Funktionen

Sie können OpenCV in vielen Bereichen anwenden, in denen es um Computer Vision geht. Denn es bietet eine große Bandbreite an Funktionalitäten. Sie sollten seine Fähigkeiten erkunden, indem Sie an weiteren Projekten arbeiten, die Computer Vision beinhalten. Dadurch werden Sie in neue Konzepte eingeführt und erhalten neue Forschungsgebiete.