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í
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ávkacurr_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ávkatranslation_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.