Użyj tej techniki, aby zastosować sprytną matematykę do swoich filmów i zmniejszyć drgania.

Stabilizacja wideo to technika, która ogranicza niepożądany ruch i drgania materiału wideo. Fotografowanie z ręki, wibracje i ruch mogą powodować niestabilne ruchy aparatu. Stabilizacja wideo zapewnia płynniejszy obraz wideo.

Podstawowym celem stabilizacji wideo jest oszacowanie ruchu kamery pomiędzy kolejnymi klatkami. Proces może następnie zastosować odpowiednie przekształcenia w celu wyrównania ramek. Minimalizuje to postrzegany ruch.

Konfigurowanie środowiska

Zacząć od tworzenie wirtualnego środowiska aby upewnić się, że pakiety instalowane w celu uruchomienia programu nie kolidują z istniejącymi pakietami. Następnie uruchom to polecenie terminala, aby zainstalować wymagane biblioteki:

pip zainstaluj opencv-python numpy

To polecenie instaluje biblioteki NumPy i OpenCV. NumPy zapewnia narzędzia do zadań numerycznych podczas gdy OpenCV zajmuje się zadaniami widzenia komputerowego.

Pełny kod źródłowy jest dostępny w formacie Repozytorium GitHub.

instagram viewer

Importowanie wymaganych bibliotek i definiowanie trzech kluczowych funkcji

Utwórz nowy plik Pythona i nadaj mu nazwę według własnych upodobań. Zaimportuj biblioteki NumPy i OpenCV na początku skryptu.

import liczba Jak np
import cv2

Zaimportowanie tych bibliotek umożliwi korzystanie z ich funkcji w kodzie.

Następnie zdefiniuj trzy funkcje, które będą kluczowe dla procesu stabilizacji.

Funkcja obliczania_średniej_ruchu

Utwórz funkcję i nazwij ją oblicz_średnią_ruchu. Ta funkcja obliczy średnią ruchomą danej krzywej przy użyciu określonego promienia. Wykorzystuje operację splotu z określonym rozmiarem okna i jednolitym jądrem. Ta średnia ruchoma pomaga wygładzić wahania trajektorii.

pokoblicz_średnią_ruchu(krzywa, promień):
# Oblicz średnią ruchomą krzywej przy użyciu danego promienia
rozmiar_okna = 2 * promień + 1
kernel = np.ones (rozmiar_okna) / rozmiar_okna
curve_padded = np.lib.pad (krzywa, (promień, promień), 'krawędź')
smoothed_curve = np.convolve (curve_padded, jądro, tryb ='To samo')
wygładzona_krzywa = wygładzona_krzywa[promień:-promień]
powrót wygładzona_krzywa

Funkcja zwraca gładką krzywą. Pomaga zredukować szumy i wahania krzywej. Czyni to poprzez uśrednienie wartości w przesuwanym oknie.

Funkcja smooth_trajectory

Utwórz kolejną funkcję i nazwij ją płynna_trajektoria. Ta funkcja zastosuje średnią ruchomą dla każdego wymiaru trajektorii. Osiągnie to poprzez utworzenie wygładzonej kopii oryginalnej trajektorii. Poprawi to jeszcze bardziej stabilność wideo.

pokpłynna_trajektoria(trajektoria):
# Wygładź trajektorię za pomocą średniej ruchomej w każdym wymiarze
smoothed_trajectory = np.copy (trajektoria)

Do I W zakres(3):
wygładzona_trajektoria[:, i] = oblicz_średnia_ruchu(
trajektoria[:, i],
promień=WYGŁADZANIE_PROMIEŃ
)

powrót wygładzona_trajektoria

The płynna_trajektoria funkcja zwraca wygładzoną trajektorię.

Funkcja fix_border

Utwórz ostateczną funkcję i nazwij ją granica_poprawki. Ta funkcja naprawi obramowanie ramki, stosując obrót i transformację skalowania. Pobiera ramkę wejściową, oblicza jej kształt, konstruuje macierz transformacji i stosuje transformację do ramki. Na koniec zwraca stałą ramkę.

pokgranica_poprawki(rama):
# Napraw obramowanie ramki, stosując transformację obrotu i skalowania
kształt_ramki = kształt.ramki

macierz = cv2.getRotationMatrix2D(
(kształt_ramki[1] / 2, kształt_ramki[0] / 2),
0,
1.04
)

ramka = cv2.warpAffine (ramka, macierz, (kształt_ramki[1], kształt_ramki[0]))
powrót rama

The granica_poprawki zapewnia, że ​​ustabilizowane klatki nie mają żadnych artefaktów brzegowych spowodowanych procesem stabilizacji.

Inicjowanie stabilizacji wideo i pobieranie danych wejściowych

Zacznij od ustawienia promienia, którego użyje funkcja wygładzania trajektorii.

WYGŁADZANIE_PROMIEŃ = 50

Następnie podaj ścieżkę wideo drżącego wideo, które chcesz ustabilizować.

# Otwórz wejściowy plik wideo
# Zamień ścieżkę na 0, aby korzystać z kamery internetowej
cap = cv2.VideoCapture(„wejście wideo.mp4”)

Uzyskaj właściwości trzęsącego się wideo:

liczba_ramek = int (cap.get (cv2.CAP_PROP_FRAME_COUNT))
szerokość = int (cap.get (cv2.CAP_PROP_FRAME_WIDTH))
wysokość = int (cap.get (cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get (cv2.CAP_PROP_FPS)

Ustaw format wyjściowy. Jest to format, w którym program zapisze stabilizowane wideo. Możesz użyć dowolnego popularny format wideo lubisz.

czterycc = cv2.VideoWriter_fourcc(*'mp4v')

Na koniec zainicjuj nagrywarkę wideo:

out = cv2.VideoWriter(„wyjście_wideo.mp4”, czterycc, fps, (2 * szerokość wysokość))

Rozszerzenie nazwy pliku, które przekazujesz do nagrywarki wideo, powinno być takie samo jak to, które ustawiłeś w formacie wyjściowym.

Odczytywanie i przetwarzanie ramek

Tutaj rozpoczyna się pierwszy etap przetwarzania chwiejnego wideo. Polega na odczytywaniu klatek z wejściowego wideo, obliczaniu przekształceń i wypełnianiu tablicy przekształceń.

Zacznij od przeczytania pierwszej klatki.

_, poprzednia_klatka = cap.read()
poprzedni_szary = cv2.cvtColor (poprzednia_klatka, cv2.COLOR_BGR2GRAY)

Następnie zainicjuj tablicę transformacji. Będzie przechowywać informacje dla każdej klatki.

transformuje = np.zeros((liczba_ramek - 1, 3), np.float32)

Na koniec należy obliczyć przepływ optyczny między kolejnymi klatkami. Następnie oszacuj transformację afiniczną między punktami.

Do I W zakres (liczba_ramek - 2):
# Oblicz przepływ optyczny między kolejnymi ramkami
prev_points = cv2.goodFeaturesToTrack(
prev_szary,
maxNarożniki=200,
poziom jakości=0.01,
minOdległość=30,
rozmiar bloku=3
)

sukces, curr_frame = cap.read()

Jeślinie powodzenie:
przerwa

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

bieżące_punkty, stan, błąd = cv2.calcOpticalFlowPyrLK(
prev_szary,
curr_szary,
poprzednie_punkty,
Nic
)

zapewniać prev_points.shape == curr_points.shape
idx = np.gdzie (status == 1)[0]
poprzednie_punkty = poprzednie_punkty[idx]
punkty_bieżące = punkty_bieżące[idx]

# Oszacuj transformację afiniczną między punktami
macierz, _ = cv2.estimateAffine2D(prev_points, curr_points)
tłumaczenie_x = macierz [0, 2]
tłumaczenie_y = macierz[1, 2]
kąt obrotu = np.arctan2(macierz[1, 0], macierz[0, 0])
transformacje[i] = [przesunięcie_x, przesunięcie_y, kąt_obrotu]
poprzedni_szary = aktualny_szary

Pętla iteruje po każdej klatce (z wyjątkiem ostatniej) w celu obliczenia przekształceń. Oblicza przepływ optyczny między kolejnymi klatkami za pomocą metody Lucas-Kanade. cv2.goodFeaturesToTrack wykrywa punkty charakterystyczne w poprzedniej klatce poprzedni_szary. Następnie, cv2.calcOpticalFlowPyrLK śledzi te punkty w bieżącej klatce curr_gray.

Tylko punkty o statusie 1 (wskazujące na pomyślne śledzenie) pomagają w oszacowaniu macierzy transformacji afinicznej. Kod aktualizuje plik poprzedni_szary zmienną z bieżącą ramką w skali szarości dla następnej iteracji.

Wygładzanie trajektorii

Musisz wygładzić trajektorię uzyskaną z transformacji, aby osiągnąć stabilny wynik.

# Oblicz trajektorię, sumując łącznie przekształcenia
trajektoria = np.cumsum (przekształcenia, oś=0)

# Wygładź trajektorię za pomocą średniej ruchomej
wygładzona_trajektoria = gładka_trajektoria (trajektoria)

# Oblicz różnicę między wygładzoną a oryginalną trajektorią
różnica = wygładzona_trajektoria - trajektoria

# Dodaj różnicę z powrotem do oryginalnych przekształceń, aby uzyskać gładkość
# transformacje
transforms_smooth = transformacje + różnica

Powyższy kod oblicza trajektorię ruchu kamery i wygładza ją.

Ramki stabilizujące i piszące

Ostatnim krokiem jest ustabilizowanie klatek i zapisanie ustabilizowanego wideo do pliku wyjściowego.

Zacznij od zresetowania przechwytywania wideo. Dzięki temu przyszłe operacje będą odczytywane od początku filmu.

cap.set (cv2.CAP_PROP_POS_FRAMES, 0)

Następnie ustabilizuj wideo, przetwarzając każdą klatkę.

# Przetwarzaj każdą klatkę i stabilizuj wideo
Do I W zakres (liczba_ramek - 2):
powodzenie, ramka = cap.read()

Jeślinie powodzenie:
przerwa

tłumaczenie_x = transformuje_gładko[i, 0]
tłumaczenie_y = transformuje_gładko[i, 1]
kąt obrotu = transformuje_gładko[i, 2]

# Utwórz macierz transformacji dla stabilizacji
macierz_transformacji = np.zera((2, 3), np.float32)
macierz_transformacji[0, 0] = np.cos (kąt_obrotu)
macierz_transformacji[0, 1] = -np.sin (kąt obrotu)
macierz_transformacji[1, 0] = np.sin (kąt obrotu)
macierz_transformacji[1, 1] = np.cos (kąt_obrotu)
macierz_transformacji[0, 2] = tłumaczenie_x
macierz_transformacji[1, 2] = tłumaczenie_y

# Zastosuj transformację, aby ustabilizować ramkę
frame_stabilized = cv2.warpAffine(
rama,
macierz_transformacji,
(szerokość wysokość)
)

# Napraw granicę stabilizowanej ramy
frame_stabilized = fix_border (frame_stabilized)

# Połącz oryginalne i ustabilizowane klatki obok siebie
wyjście_ramki = cv2.hconcat([ramka, stabilizacja_ramki])

# Zmień rozmiar ramki, jeśli jej szerokość przekracza 1920 pikseli
Jeśli frame_out.shape[1] > 1920:
wyjście_ramki = cv2.resize(
ramka_out,
(frame_out.shape[1] // 2, wyjście_ramki.kształt[0] // 2)
)

# Wyświetlanie ramek przed i po
cv2.imshow("Przed i po", ramka_poza)
cv2.waitKey(10)

# Zapisz ramkę do wyjściowego pliku wideo
out.write (frame_out)

Powyższy kod stabilizuje każdą klatkę za pomocą obliczonych transformacji, w tym korekt translacji i obrotu. Następnie łączy ustabilizowane klatki z oryginalnymi, aby zapewnić porównanie.

Zwalnianie programu do przechwytywania i zapisywania wideo

Zakończ program, zwalniając obiekty przechwytywania wideo i zapisu.

# Zwolnij przechwytywanie wideo i nagrywarkę oraz zamknij wszystkie otwarte okna
cap.release()
out.release()
cv2.destroyAllWindows()

Ten kod zamyka również wszystkie otwarte okna.

Końcowe wyjście programu

Wyjście programu będzie wyglądać mniej więcej tak:

A oto przykład ustabilizowanego wideo:

Dane wyjściowe pokazują porównanie chwiejnego wideo i ustabilizowanego.

Poznaj możliwości OpenCV

Możesz zastosować OpenCV w wielu dziedzinach związanych z wizją komputerową. Dzieje się tak, ponieważ oferuje szeroki zakres funkcjonalności. Powinieneś zbadać jego możliwości, pracując nad większą liczbą projektów, które obejmują widzenie komputerowe. Wprowadzi Cię to w nowe koncepcje i da nowe obszary do badań.