Pomocí této techniky můžete na svá videa použít chytrou matematiku a omezit otřesy.

Stabilizace videa je technika, která snižuje nežádoucí pohyb a chvění ve videu. Fotografování z ruky, vibrace a pohyb mohou způsobit nestabilní pohyby fotoaparátu. Stabilizace videa vytváří plynulejší video.

Primárním cílem stabilizace videa je odhadnout pohyb kamery mezi po sobě jdoucími snímky. Proces pak může použít vhodné transformace k zarovnání rámců. Tím se minimalizuje vnímaný pohyb.

Nastavení vašeho prostředí

Začněte tím vytváření virtuálního prostředí abyste zajistili, že balíčky, které nainstalujete ke spuštění programu, nebudou v konfliktu s těmi stávajícími. Poté spusťte tento příkaz terminálu a nainstalujte požadované knihovny:

pip install opencv-python numpy

Tento příkaz nainstaluje knihovny NumPy a OpenCV. NumPy poskytuje nástroje pro numerické úlohy zatímco OpenCV se zabývá úlohami počítačového vidění.

Úplný zdrojový kód je k dispozici v a úložiště GitHub.

Import požadovaných knihoven a definování tří klíčových funkcí

instagram viewer

Vytvořte nový soubor Python a pojmenujte jej podle svých představ. Importujte knihovny NumPy a OpenCV na začátku skriptu.

import nemotorný tak jako np
import cv2

Import těchto knihoven vám umožní používat jejich funkce ve vašem kódu.

Dále definujte tři funkce, které budou klíčové pro proces stabilizace.

Funkce vypočítej_pohyblivý_průměr

Vytvořte funkci a pojmenujte ji vypočítat_pohyblivý_průměr. Tato funkce vypočítá klouzavý průměr dané křivky pomocí vámi určeného poloměru. Využívá konvoluční operaci se zadanou velikostí okna a jednotným jádrem. Tento klouzavý průměr pomáhá vyhladit kolísání trajektorie.

defvypočítat_pohyblivý_průměr(křivka, poloměr):
# Vypočítejte klouzavý průměr křivky pomocí daného poloměru
velikost_okna = 2 * poloměr + 1
kernel = np.ones (velikost_okna) / velikost_okna
curve_padded = np.lib.pad (křivka, (poloměr, poloměr), 'okraj')
smoothed_curve = np.convolve (curve_padded, kernel, mode='stejný')
smoothed_curve = smoothed_curve[radius:-radius]
vrátit se vyhlazená_křivka

Funkce vrací hladkou křivku. Pomáhá snižovat hluk a kolísání křivky. Dělá to průměrováním hodnot v posuvném okně.

Funkce smooth_trajectory

Vytvořte další funkci a pojmenujte ji hladká_trajektorie. Tato funkce použije klouzavý průměr na každý rozměr trajektorie. Dosáhne toho vytvořením vyhlazené kopie původní trajektorie. To dále zlepší stabilitu videa.

defhladká_trajektorie(trajektorie):
# Vyhlaďte trajektorii pomocí klouzavého průměru v každém rozměru
smoothed_trajectory = np.copy (trajektorie)

pro i v rozsah(3):
smoothed_trajectory[:, i] = vypočítat_průměr_pohybu(
trajektorie[:, i],
rádius=SMOOTHING_RADIUS
)

vrátit se vyhlazená_trajektorie

The hladká_trajektorie funkce vrací vyhlazenou trajektorii.

Funkce fix_border

Vytvořte konečnou funkci a pojmenujte ji fix_border. Tato funkce zafixuje okraj rámečku použitím transformace rotace a měřítka. Vezme vstupní snímek, vypočítá jeho tvar, sestaví transformační matici a aplikuje transformaci na snímek. Nakonec vrátí pevný rám.

deffix_border(rám):
# Opravte rámeček pomocí transformace rotace a změny měřítka
frame_shape = frame.shape

matice = cv2.getRotationMatrix2D(
(tvar_rámu[1] / 2, tvar_rámečku[0] / 2),
0,
1.04
)

frame = cv2.warpAffine (frame, matrix, (frame_shape[1], frame_shape[0]))
vrátit se rám

The fix_border Funkce zajišťuje, že stabilizované snímky nemají žádné hraniční artefakty způsobené procesem stabilizace.

Inicializace stabilizace videa a převzetí vstupu

Začněte nastavením poloměru, který bude funkce vyhlazení trajektorie používat.

SMOOTHING_RADIUS = 50

Poté předejte cestu videa roztřeseného videa, které chcete stabilizovat.

# Otevřete vstupní video soubor
# Chcete-li použít webovou kameru, nahraďte cestu 0
cap = cv2.VideoCapture('inputvid.mp4')

Získejte vlastnosti roztřeseného videa:

num_frames = int (cap.get (cv2.CAP_PROP_FRAME_COUNT))
šířka = int (cap.get (cv2.CAP_PROP_FRAME_WIDTH))
výška = int (cap.get (cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get (cv2.CAP_PROP_FPS)

Nastavte výstupní formát. Toto je formát, ve kterém program uloží stabilizované video. Můžete použít jakýkoli běžný formát videa máš rád.

fourcc = cv2.VideoWriter_fourcc(*'mp4v')

Nakonec inicializujte zapisovač videa:

out = cv2.VideoWriter('video_out.mp4', fourcc, fps, (2 * šířka výška))

Přípona názvu souboru, který předáte zapisovači videa, by měla být stejná jako přípona, kterou jste nastavili ve výstupním formátu.

Čtení a zpracování rámců

První krok zpracování roztřeseného videa začíná zde. Zahrnuje čtení snímků ze vstupního videa, výpočet transformací a naplnění pole transforms.

Začněte čtením prvního snímku.

_, předchozí_frame = cap.read()
předchozí_šedá = cv2.cvtColor (předchozí_rámec, cv2.COLOR_BGR2GRAY)

Poté inicializujte transformační pole. Uloží informace pro každý snímek.

transforms = np.zeros((počet_snímků - 1, 3), np.float32)

Nakonec musíte vypočítat optický tok mezi po sobě jdoucími snímky. Poté odhadněte afinní transformaci mezi body.

pro i v rozsah (počet_snímků - 2):
# Vypočítejte optický tok mezi po sobě jdoucími snímky
prev_points = cv2.goodFeaturesToTrack(
předchozí_šedá,
maxCorners=200,
kvalitaLevel=0.01,
minDistance=30,
blockSize=3
)

úspěch, curr_frame = cap.read()

-line úspěch:
přestávka

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

curr_points, status, err = cv2.calcOpticalFlowPyrLK(
předchozí_šedá,
curr_grey,
předchozí_body,
Žádný
)

tvrdit prev_points.shape == curr_points.shape
idx = np.where (stav == 1)[0]
prev_points = prev_points[idx]
curr_points = curr_points[idx]

# Odhadněte afinní transformaci mezi body
matice, _ = cv2.estimateAffine2D(předchozí_body, aktuální_body)
překlad_x = matice[0, 2]
translation_y = matice[1, 2]
rotační_úhel = np.arctan2(matice[1, 0], matice[0, 0])
transforms[i] = [translation_x, translation_y, rotace_angle]
prev_gray = curr_gray

Smyčka iteruje přes každý snímek (kromě posledního snímku) za účelem výpočtu transformací. Vypočítává optický tok mezi po sobě jdoucími snímky pomocí metody Lucas-Kanade. cv2.goodFeaturesToTrack detekuje hlavní body v předchozím snímku předchozí_šedá. Pak, cv2.calcOpticalFlowPyrLK sleduje tyto body v aktuálním snímku curr_grey.

Pouze body se stavem 1 (označující úspěšné sledování) pomáhají při odhadu afinní transformační matice. Kód aktualizuje předchozí_šedá proměnnou s aktuálním rámcem ve stupních šedi pro další iteraci.

Vyhlazení trajektorie

Chcete-li dosáhnout stabilního výsledku, musíte vyhladit trajektorii získanou z transformací.

# Vypočítejte trajektorii kumulativním sečtením transformací
trajektorie = np.cumsum (transformuje, osa=0)

# Vyhlaďte trajektorii pomocí klouzavého průměru
smoothed_trajectory = smooth_trajectory (trajektorie)

# Vypočítejte rozdíl mezi vyhlazenou a původní trajektorií
rozdíl = smoothed_trajectory - trajektorie

# Přidejte rozdíl zpět k původním transformacím, abyste získali hladké
# transformací
transforms_smooth = transformuje + rozdíl

Výše uvedený kód vypočítá trajektorii pohybu kamery a vyhlazuje ji.

Stabilizační a zapisovací rámy

Posledním krokem je stabilizace snímků a zápis stabilizovaného videa do výstupního souboru.

Začněte resetováním nahrávání videa. To zajistí, že budoucí operace se budou číst od začátku videa.

cap.set (cv2.CAP_PROP_POS_FRAMES, 0)

Poté stabilizujte video zpracováním každého snímku.

# Zpracujte každý snímek a stabilizujte video
pro i v rozsah (počet_snímků - 2):
úspěch, snímek = cap.read()

-line úspěch:
přestávka

translation_x = transforms_smooth[i, 0]
translation_y = transforms_smooth[i, 1]
rotační_úhel = transforms_smooth[i, 2]

# Vytvořte transformační matici pro stabilizaci
transformační_matice = np.zeros((2, 3), np.float32)
transformační_matice[0, 0] = np.cos (úhel_otočení)
transformační_matice[0, 1] = -np.sin (úhel_otočení)
transformační_matice[1, 0] = np.sin (úhel_rotace)
transformační_matice[1, 1] = np.cos (úhel_otočení)
transformační_matice[0, 2] = překlad_x
transformační_matice[1, 2] = překlad_y

# Aplikujte transformaci ke stabilizaci rámu
frame_stabilized = cv2.warpAffine(
rám,
transformační_matice,
(šířka výška)
)

# Opravte okraj stabilizovaného rámu
frame_stabilized = fix_border (frame_stabilized)

# Spojte původní a stabilizované snímky vedle sebe
frame_out = cv2.hconcat([frame, frame_stabilized])

# Změňte velikost rámečku, pokud jeho šířka přesahuje 1920 pixelů
-li frame_out.shape[1] > 1920:
frame_out = cv2.resize(
frame_out,
(frame_out.shape[1] // 2, frame_out.shape[0] // 2)
)

# Zobrazte snímky před a po
cv2.imshow("Před a po", frame_out)
cv2.waitKey(10)

# Zapište snímek do výstupního video souboru
out.write (frame_out)

Výše uvedený kód stabilizuje každý snímek pomocí vypočítaných transformací, včetně úprav translace a rotace. Poté zkombinuje stabilizované rámy s původními a poskytne srovnání.

Uvolnění aplikace Video Capture and Writer

Dokončete program uvolněním objektů zachycení videa a zápisu.

# Uvolněte nahrávání a zápis videa a zavřete všechna otevřená okna
cap.release()
out.release()
cv2.destroyAllWindows()

Tento kód také zavře všechna otevřená okna.

Konečný výstup programu

Výstup programu bude vypadat nějak takto:

A zde je příklad stabilizovaného videa:

Výstup ukazuje srovnání mezi roztřeseným a stabilizovaným videem.

Prozkoumejte možnosti OpenCV

OpenCV můžete použít v mnoha oblastech, které zahrnují počítačové vidění. To proto, že nabízí širokou škálu funkcí. Měli byste prozkoumat jeho schopnosti prací na více projektech, které zahrnují počítačové vidění. Tím se seznámíte s novými koncepty a získáte nové oblasti ke zkoumání.