Upotrijebite ovu tehniku ​​da primijenite pametnu matematiku na svoje videozapise i smanjite podrhtavanje.

Video stabilizacija je tehnika koja smanjuje neželjeno kretanje i podrhtavanje u video snimci. Snimanje iz ruke, vibracije i pokreti mogu uzrokovati nestabilne pokrete fotoaparata. Stabilizacija videozapisa daje glatkiji videozapis.

Primarni cilj video stabilizacije je procijeniti kretanje kamere između uzastopnih sličica. Proces zatim može primijeniti odgovarajuće transformacije za poravnavanje okvira. Ovo minimizira percipirano kretanje.

Postavljanje vašeg okruženja

Počni od stvaranje virtualnog okruženja kako biste osigurali da paketi koje instalirate za pokretanje programa nisu u sukobu s postojećima. Zatim pokrenite ovu terminalsku naredbu da instalirate potrebne biblioteke:

pip instaliraj opencv-python numpy

Ova naredba instalira NumPy i OpenCV biblioteke. NumPy nudi alate za numeričke zadatke dok se OpenCV bavi zadacima računalnog vida.

Puni izvorni kod dostupan je u a GitHub spremište.

instagram viewer

Uvoz potrebnih biblioteka i definiranje triju ključnih funkcija

Napravite novu Python datoteku i dodijelite joj naziv po svom ukusu. Uvezite NumPy i OpenCV biblioteke na početku skripte.

uvoz numpy kao np
uvoz cv2

Uvoz ovih biblioteka omogućit će vam korištenje njihovih funkcija u vašem kodu.

Zatim definirajte tri funkcije koje će biti ključne za proces stabilizacije.

Funkcija izračun_pomičnog_prosjeka

Napravite funkciju i dajte joj naziv izračunati_pomični_prosjek. Ova funkcija izračunat će pomični prosjek dane krivulje pomoću polumjera koji navedete. Koristi operaciju konvolucije s određenom veličinom prozora i jedinstvenom jezgrom. Ovaj pomični prosjek pomaže uglađivanju fluktuacija putanje.

defizračunati_pomični_prosjek(krivulja, radijus):
# Izračunajte pomični prosjek krivulje koristeći zadani radijus
veličina_prozora = 2 * radijus + 1
kernel = np.ones (veličina_prozora) / veličina_prozora
curve_padded = np.lib.pad (krivulja, (radijus, radijus), 'rub')
smoothed_curve = np.convolve (curve_padded, kernel, mode='isti')
izglađena_krivulja = izglađena_krivulja[radijus:-radijus]
povratak izglađena_krivulja

Funkcija vraća glatku krivulju. Pomaže smanjiti buku i fluktuacije u krivulji. To čini usrednjavanjem vrijednosti unutar kliznog prozora.

Funkcija smooth_trajectory

Napravite drugu funkciju i dajte joj naziv glatka_putanja. Ova funkcija će primijeniti pomični prosjek na svaku dimenziju putanje. To će postići stvaranjem uglađene kopije izvorne putanje. To će dodatno poboljšati stabilnost videa.

defglatka_putanja(putanja):
# Izgladite putanju koristeći pomični prosjek na svakoj dimenziji
smoothed_trajectory = np.copy (putanja)

za ja u raspon (3):
izglađena_putanja[:, i] = izračunaj_pomični_prosjek(
putanja[:, i],
radijus=RADIJ_IZGLAĐIVANJA
)

povratak izglađena_putanja

The glatka_putanja funkcija vraća izglađenu putanju.

Funkcija fix_border

Napravite konačnu funkciju i dajte joj naziv popraviti_border. Ova funkcija će popraviti obrub okvira primjenom transformacije rotacije i skaliranja. Uzima ulazni okvir, izračunava njegov oblik, konstruira transformacijsku matricu i primjenjuje transformaciju na okvir. Konačno, vraća fiksni okvir.

defpopraviti_border(okvir):
# Popravite obrub okvira primjenom rotacije i transformacije skaliranja
oblik_okvira = okvir.oblik

matrica = cv2.getRotationMatrix2D(
(oblik_okvira[1] / 2, oblik_okvira[0] / 2),
0,
1.04
)

okvir = cv2.warpAffine (okvir, matrica, (oblik_okvira[1], oblik_okvira[0]))
povratak okvir

The popraviti_border Funkcija osigurava da stabilizirani okviri nemaju nikakvih graničnih artefakata uzrokovanih procesom stabilizacije.

Pokretanje video stabilizacije i uzimanje ulaza

Započnite postavljanjem radijusa koji će koristiti funkcija izglađivanja putanje.

SMOOTHING_RADIUS = 50

Zatim prođite kroz video stazu drhtavog videozapisa koji želite stabilizirati.

# Otvorite ulaznu video datoteku
# Zamijenite put s 0 da biste koristili svoju web kameru
cap = cv2.VideoCapture('inputvid.mp4')

Dohvatite svojstva drhtavog videozapisa:

num_frames = int (cap.get (cv2.CAP_PROP_FRAME_COUNT))
širina = int (cap.get (cv2.CAP_PROP_FRAME_WIDTH))
visina = int (cap.get (cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get (cv2.CAP_PROP_FPS)

Postavite izlazni format. Ovo je format u kojem će program spremiti stabilizirani video. Možete koristiti bilo koji uobičajeni video format tebi se sviđa.

fourcc = cv2.VideoWriter_fourcc(*'mp4v')

Na kraju, inicijalizirajte pisač videozapisa:

out = cv2.VideoWriter('video_out.mp4', fourcc, fps, (2 * širina Visina))

Ekstenzija naziva datoteke koju prosljeđujete pisaču videozapisa trebala bi biti ista kao ona koju ste postavili u izlaznom formatu.

Čitanje i obrada okvira

Ovdje počinje prvi korak obrade drhtavog videa. Uključuje čitanje okvira iz ulaznog videa, izračunavanje transformacija i popunjavanje niza transformacija.

Počnite s čitanjem prvog okvira.

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

Zatim inicijalizirajte polje transformacije. Pohranit će informacije za svaki okvir.

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

Na kraju, morate izračunati optički protok između uzastopnih okvira. Zatim procijenite afinu transformaciju između točaka.

za ja u raspon (broj_okvira - 2):
# Izračunajte optički protok između uzastopnih okvira
prev_points = cv2.goodFeaturesToTrack(
prev_gray,
maxCorners=200,
Razina kvalitete=0.01,
minUdaljenost=30,
veličina bloka=3
)

uspjeh, curr_frame = cap.read()

akone uspjeh:
pauza

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

curr_points, status, err = cv2.calcOpticalFlowPyrLK(
prev_gray,
curr_gray,
prethodne_točke,
Nijedan
)

tvrditi prev_points.shape == curr_points.shape
idx = np.gdje (status == 1)[0]
prethodni_bodovi = prethodni_bodovi[idx]
curr_bodovi = curr_bodovi[idx]

# Procijenite afinu transformaciju između točaka
matrica, _ = cv2.estimateAffine2D(prev_points, curr_points)
prijevod_x = matrica[0, 2]
prijevod_y = matrica[1, 2]
kut_rotacije = np.arctan2(matrica[1, 0], matrica[0, 0])
transformira[i] = [translation_x, translation_y, rotation_angle]
prethodna_siva = curr_siva

Petlja ponavlja svaki okvir (osim zadnjeg okvira) kako bi izračunala transformacije. Izračunava optički protok između uzastopnih okvira koristeći Lucas-Kanade metodu. cv2.goodFeaturesToTrack otkriva značajke u prethodnom okviru prethodna_siva. Zatim, cv2.calcOpticalFlowPyrLK prati te točke u trenutnom okviru curr_gray.

Samo točke sa statusom 1 (što ukazuje na uspješno praćenje) pomažu u procjeni matrice afine transformacije. Kod ažurira prethodna_siva varijablu s trenutnim okvirom u sivim tonovima za sljedeću iteraciju.

Izglađivanje putanje

Morate izgladiti putanju dobivenu transformacijama kako biste postigli stabilan rezultat.

# Izračunajte putanju kumulativnim zbrajanjem transformacija
putanja = np.cumsum (transformira, os=0)

# Izgladite putanju pomoću pomičnog prosjeka
izglađena_putanja = glatka_putanja (putanja)

# Izračunajte razliku između izglađene i originalne putanje
razlika = smoothed_trajectory - putanja

# Dodajte razliku natrag izvornim transformacijama kako biste dobili glatkoću
# transformacije
transformira_glatko = transformira + razlika

Gornji kod izračunava putanju kretanja kamere i izglađuje je.

Okviri za stabilizaciju i pisanje

Zadnji korak je stabilizacija okvira i pisanje stabiliziranog videa u izlaznu datoteku.

Započnite resetiranjem video snimanja. Time se osigurava da će buduće operacije čitati od početka videozapisa.

cap.set (cv2.CAP_PROP_POS_FRAMES, 0)

Zatim stabilizirajte video obradom svakog okvira.

# Obradite svaki okvir i stabilizirajte video
za ja u raspon (broj_okvira - 2):
uspjeh, okvir = cap.read()

akone uspjeh:
pauza

prijevod_x = transformira_glatko[i, 0]
prijevod_y = transformira_glatko[i, 1]
kut_rotacije = transformira_glatko[i, 2]

# Napravite matricu transformacije za stabilizaciju
matrica_transformacije = np.nule((2, 3), np.float32)
transformacijska_matrica[0, 0] = np.cos (kut_rotacije)
transformacijska_matrica[0, 1] = -np.sin (kut_rotacije)
transformacijska_matrica[1, 0] = np.sin (kut_rotacije)
transformacijska_matrica[1, 1] = np.cos (kut_rotacije)
transformacijska_matrica[0, 2] = prijevod_x
transformacijska_matrica[1, 2] = prijevod_y

# Primijenite transformaciju za stabilizaciju okvira
frame_stabilized = cv2.warpAffine(
okvir,
transformacijska_matrica,
(širina Visina)
)

# Popravite obrub stabiliziranog okvira
frame_stabilized = fix_border (frame_stabilized)

# Spojite originalne i stabilizirane okvire jedan pored drugog
frame_out = cv2.hconcat([frame, frame_stabilized])

# Promijenite veličinu okvira ako njegova širina prelazi 1920 piksela
ako frame_out.shape[1] > 1920:
frame_out = cv2.resize(
frame_out,
(frame_out.shape[1] // 2, frame_out.shape[0] // 2)
)

# Prikaz okvira prije i poslije
cv2.imshow("Prije i poslije", frame_out)
cv2.waitKey(10)

# Zapišite okvir u izlaznu video datoteku
out.write (frame_out)

Gornji kod stabilizira svaki okvir pomoću izračunatih transformacija, uključujući prilagodbe translacije i rotacije. Zatim kombinira stabilizirane okvire s originalnim kako bi omogućio usporedbu.

Puštanje Video Capture i Writer

Finalizirajte program otpuštanjem objekata video snimanja i snimanja.

# Otpustite video snimanje i snimanje i zatvorite sve otvorene prozore
cap.release()
out.release()
cv2.destroyAllWindows()

Ovaj kod također zatvara sve otvorene prozore.

Konačni izlaz programa

Izlaz programa izgledat će otprilike ovako:

Evo primjera stabiliziranog videa:

Izlaz prikazuje usporedbu između drhtavog videa i stabiliziranog.

Istražite mogućnosti OpenCV-a

OpenCV možete primijeniti u mnogim područjima koja uključuju računalni vid. To je zato što nudi širok raspon funkcionalnosti. Trebali biste istražiti njegove mogućnosti radeći na više projekata koji uključuju računalni vid. To će vas upoznati s novim konceptima i dati nova područja za istraživanje.