Pomocou tejto techniky môžete na svoje videá použiť dômyselnú matematiku a obmedziť otrasy.

Stabilizácia videa je technika, ktorá znižuje nežiaduci pohyb a chvenie vo videu. Snímanie z ruky, vibrácie a pohyb môžu spôsobiť nestabilné pohyby fotoaparátu. Stabilizácia videa vytvára plynulejšie video.

Primárnym cieľom stabilizácie videa je odhadnúť pohyb kamery medzi po sebe idúcimi snímkami. Proces potom môže použiť vhodné transformácie na zarovnanie snímok. Tým sa minimalizuje vnímaný pohyb.

Nastavenie vášho prostredia

Začnite tým vytváranie virtuálneho prostredia aby ste zabezpečili, že balíky, ktoré nainštalujete na spustenie programu, nebudú v konflikte s existujúcimi. Potom spustite tento príkaz terminálu a nainštalujte požadované knižnice:

pip install opencv-python numpy

Tento príkaz nainštaluje knižnice NumPy a OpenCV. NumPy poskytuje nástroje pre numerické úlohy zatiaľ čo OpenCV sa zaoberá úlohami počítačového videnia.

Úplný zdrojový kód je dostupný v a úložisko GitHub.

Import požadovaných knižníc a definovanie troch kľúčových funkcií

instagram viewer

Vytvorte nový súbor Python a pomenujte ho podľa svojich predstáv. Importujte knižnice NumPy a OpenCV na začiatku skriptu.

importovať numpy ako np
importovať cv2

Import týchto knižníc vám umožní používať ich funkcie vo vašom kóde.

Ďalej definujte tri funkcie, ktoré budú kľúčové pre proces stabilizácie.

Funkcia vypočítať_pohybový_priemer

Vytvorte funkciu a pomenujte ju vypočítať_pohyblivý_priemer. Táto funkcia vypočíta kĺzavý priemer danej krivky pomocou vami zadaného polomeru. Využíva konvolučnú operáciu so špecifikovanou veľkosťou okna a jednotným jadrom. Tento kĺzavý priemer pomáha vyhladiť výkyvy trajektórie.

defvypočítať_pohyblivý_priemer(krivka, polomer):
# Vypočítajte kĺzavý priemer krivky pomocou daného polomeru
veľkosť_okna = 2 * polomer + 1
kernel = np.ones (veľkosť_okna) / veľkosť_okna
curve_padded = np.lib.pad (krivka, (polomer, polomer), 'hrana')
smoothed_curve = np.convolve (curve_padded, kernel, mode='rovnaký')
vyhladená_krivka = vyhladená_krivka[polomer:-polomer]
vrátiť vyhladená_krivka

Funkcia vráti hladkú krivku. Pomáha znižovať hluk a kolísanie krivky. Robí to spriemerovaním hodnôt v rámci posuvného okna.

Funkcia smooth_trajectory

Vytvorte ďalšiu funkciu a pomenujte ju hladká_trajektória. Táto funkcia použije kĺzavý priemer na každý rozmer trajektórie. Dosiahne to vytvorením vyhladenej kópie pôvodnej trajektórie. Toto ešte viac zlepší stabilitu videa.

defhladká_trajektória(dráha):
# Vyhladzujte trajektóriu pomocou kĺzavého priemeru v každej dimenzii
smoothed_trajectory = np.copy (trajektória)

pre i v rozsah(3):
smoothed_trajectory[:, i] = vypočítať_pohyblivý_priemer (
trajektória[:, i],
polomer=SMOOTHING_RADIUS
)

vrátiť vyhladená_trajektória

The hladká_trajektória funkcia vráti vyhladenú trajektóriu.

Funkcia fix_border

Vytvorte konečnú funkciu a pomenujte ju fix_border. Táto funkcia zafixuje hranicu rámu použitím transformácie rotácie a zmeny mierky. Zoberie vstupný rámec, vypočíta jeho tvar, vytvorí transformačnú maticu a aplikuje transformáciu na rámec. Nakoniec vráti pevný rám.

deffix_border(rám):
# Opravte okraj rámu použitím transformácie rotácie a zmeny mierky
frame_shape = rám.tvar

matica = cv2.getRotationMatrix2D(
(tvar_rámu[1] / 2, tvar_rámu[0] / 2),
0,
1.04
)

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

The fix_border funkcia zabezpečuje, že stabilizované rámy nemajú žiadne hraničné artefakty spôsobené procesom stabilizácie.

Inicializácia stabilizácie videa a prevzatie vstupu

Začnite nastavením polomeru, ktorý bude funkcia vyhladzovania trajektórie používať.

SMOOTHING_RADIUS = 50

Potom prejdite videocestou roztraseného videa, ktoré chcete stabilizovať.

# Otvorte vstupný video súbor
# Ak chcete použiť webovú kameru, nahraďte cestu 0
cap = cv2.VideoCapture('inputvid.mp4')

Získajte vlastnosti roztraseného videa:

num_frames = int (cap.get (cv2.CAP_PROP_FRAME_COUNT))
šírka = 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, v ktorom program uloží stabilizované video. Môžete použiť akýkoľvek bežný formát videa máš rád.

fourcc = cv2.VideoWriter_fourcc(*'mp4v')

Nakoniec inicializujte zapisovač videa:

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

Prípona názvu súboru, ktorý odovzdáte zapisovaciemu programu videa, by mala byť rovnaká ako prípona, ktorú ste nastavili vo výstupnom formáte.

Rámy na čítanie a spracovanie

Prvý krok spracovania roztraseného videa začína tu. Zahŕňa čítanie snímok zo vstupného videa, výpočet transformácií a naplnenie poľa transformácií.

Začnite prečítaním prvého snímku.

_, predchádzajúci_frame = cap.read()
prev_grey = cv2.cvtColor (predchádzajúca_snímka, cv2.COLOR_BGR2GRAY)

Potom inicializujte transformačné pole. Uloží informácie pre každý rámec.

transformuje = np.zeros((počet_rámcov - 1, 3), np.float32)

Nakoniec musíte vypočítať optický tok medzi po sebe nasledujúcimi snímkami. Potom odhadnite afinnú transformáciu medzi bodmi.

pre i v rozsah (počet_snímok - 2):
# Vypočítajte optický tok medzi po sebe idúcimi snímkami
prev_points = cv2.goodFeaturesToTrack(
prev_grey,
maxCorners=200,
kvalitaLevel=0.01,
minDistance=30,
blockSize=3
)

úspech, curr_frame = cap.read()

aknie úspech:
prestávka

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

curr_points, status, err = cv2.calcOpticalFlowPyrLK(
prev_grey,
curr_grey,
predchádzajúce_body,
žiadne
)

tvrdiť prev_points.shape == curr_points.shape
idx = np.where (stav == 1)[0]
predchádzajúce_body = predchádzajúce_body[idx]
curr_points = curr_points[idx]

# Odhadnite afinnú transformáciu medzi bodmi
matica, _ = cv2.estimateAffine2D(prev_body, curr_points)
preklad_x = matica[0, 2]
preklad_y = matica[1, 2]
rotačný_uhol = np.arctan2(matica[1, 0], matica[0, 0])
transformuje[i] = [preklad_x, preklad_y, uhol_otočenia]
prev_grey = curr_grey

Cyklus iteruje cez každý rámec (okrem posledného), aby vypočítal transformácie. Vypočítava optický tok medzi po sebe idúcimi snímkami pomocou metódy Lucas-Kanade. cv2.goodFeaturesToTrack deteguje hlavné body v predchádzajúcej snímke prev_grey. potom cv2.calcOpticalFlowPyrLK sleduje tieto body v aktuálnej snímke curr_grey.

Iba body so stavom 1 (indikujúce úspešné sledovanie) pomáhajú pri odhade afinnej transformačnej matice. Kód aktualizuje prev_grey premennú s aktuálnym rámcom v odtieňoch sivej pre ďalšiu iteráciu.

Vyhladzovanie trajektórie

Aby ste dosiahli stabilný výsledok, musíte zjemniť trajektóriu získanú z transformácií.

# Vypočítajte trajektóriu kumulatívnym sčítaním transformácií
trajektória = np.cumsum (transformuje, os=0)

# Vyhladzujte trajektóriu pomocou kĺzavého priemeru
smoothed_trajectory = smooth_trajectory (trajektória)

# Vypočítajte rozdiel medzi vyhladenou a pôvodnou trajektóriou
rozdiel = smoothed_trajectory - trajektória

# Pridajte rozdiel späť k pôvodným transformáciám, aby ste dosiahli hladké
# premien
transforms_smooth = transformuje + rozdiel

Vyššie uvedený kód vypočíta trajektóriu pohybu kamery a vyhladí ju.

Stabilizačné a zapisovacie rámy

Posledným krokom je stabilizácia snímok a zápis stabilizovaného videa do výstupného súboru.

Začnite resetovaním snímania videa. Tým sa zabezpečí, že budúce operácie sa budú čítať od začiatku videa.

cap.set (cv2.CAP_PROP_POS_FRAMES, 0)

Potom stabilizujte video spracovaním každej snímky.

# Spracujte každý snímok a stabilizujte video
pre i v rozsah (počet_snímok - 2):
úspech, rámec = cap.read()

aknie úspech:
prestávka

translation_x = transforms_smooth[i, 0]
translation_y = transforms_smooth[i, 1]
rotačný_uhol = transforms_smooth[i, 2]

# Vytvorte transformačnú maticu pre stabilizáciu
transformačná_matica = np.zeros((2, 3), np.float32)
transformačná_matica[0, 0] = np.cos (uhol_otočenia)
transformačná_matica[0, 1] = -np.sin (uhol_otočenia)
transformačná_matica[1, 0] = np.sin (uhol_otočenia)
transformačná_matica[1, 1] = np.cos (uhol_otočenia)
transformačná_matica[0, 2] = preklad_x
transformačná_matica[1, 2] = preklad_y

# Použite transformáciu na stabilizáciu rámu
frame_stabilized = cv2.warpAffine(
rám,
transformačná_matica,
(šírka výška)
)

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

# Spájajte pôvodný a stabilizovaný rám vedľa seba
frame_out = cv2.hconcat([frame, frame_stabilized])

# Zmeňte veľkosť rámu, ak jeho šírka presahuje 1920 pixelov
ak frame_out.shape[1] > 1920:
frame_out = cv2.resize(
frame_out,
(frame_out.shape[1] // 2, frame_out.shape[0] // 2)
)

# Zobrazte rámčeky pred a po
cv2.imshow("Pred a po", frame_out)
cv2.waitKey(10)

# Zapíšte snímku do výstupného video súboru
out.write (frame_out)

Vyššie uvedený kód stabilizuje každý rámec pomocou vypočítaných transformácií vrátane úprav posunu a rotácie. Potom skombinuje stabilizované rámy s pôvodnými a poskytne porovnanie.

Uvoľnenie aplikácie Video Capture and Writer

Dokončite program uvoľnením objektov zachytávania a zapisovania videa.

# Uvoľnite zachytávanie a zapisovanie videa a zatvorte všetky otvorené okná
cap.release()
out.release()
cv2.destroyAllWindows()

Tento kód tiež zatvorí všetky otvorené okná.

Konečný výstup programu

Výstup programu bude vyzerať asi takto:

A tu je príklad stabilizovaného videa:

Výstup zobrazuje porovnanie roztraseného videa so stabilizovaným.

Preskúmajte možnosti OpenCV

OpenCV môžete použiť v mnohých oblastiach, ktoré zahŕňajú počítačové videnie. Je to preto, že ponúka širokú škálu funkcií. Mali by ste preskúmať jeho možnosti prácou na viacerých projektoch, ktoré zahŕňajú počítačové videnie. To vám predstaví nové koncepty a poskytne vám nové oblasti na skúmanie.