S to tehniko uporabite nekaj pametne matematike za svoje videoposnetke in zmanjšajte tresenje.
Stabilizacija videa je tehnika, ki zmanjša neželeno gibanje in tresenje v videoposnetkih. Fotografiranje iz roke, vibracije in gibanje lahko povzročijo neenakomerno gibanje fotoaparata. Stabilizacija videa ustvari bolj gladek video.
Primarni cilj stabilizacije videa je oceniti gibanje kamere med zaporednimi sličicami. Postopek lahko nato uporabi ustrezne transformacije za poravnavo okvirjev. To zmanjša zaznano gibanje.
Nastavitev vašega okolja
Začni z ustvarjanje virtualnega okolja da zagotovite, da paketi, ki jih namestite za zagon programa, niso v nasprotju z obstoječimi. Nato zaženite ta terminalski ukaz, da namestite zahtevane knjižnice:
pip namestite opencv-python numpy
Ta ukaz namesti knjižnici NumPy in OpenCV. NumPy ponuja orodja za numerične naloge medtem ko se OpenCV ukvarja z nalogami računalniškega vida.
Celotna izvorna koda je na voljo v a Repozitorij GitHub.
Uvoz zahtevanih knjižnic in definiranje treh ključnih funkcij
Ustvarite novo datoteko Python in jo poimenujte po svojih željah. Uvozite knjižnici NumPy in OpenCV na začetku skripta.
uvoz numpy kot np
uvoz cv2
Uvoz teh knjižnic vam bo omogočil uporabo njihovih funkcij v vaši kodi.
Nato definirajte tri funkcije, ki bodo ključne za proces stabilizacije.
Funkcija izračun_moving_average
Ustvarite funkcijo in jo poimenujte izračunaj drseče_povprečje. Ta funkcija bo izračunala drseče povprečje dane krivulje z uporabo polmera, ki ga določite. Uporablja konvolucijsko operacijo z določeno velikostjo okna in enotnim jedrom. To drseče povprečje pomaga zgladiti nihanja v trajektoriji.
defizračunaj drseče_povprečje(krivulja, radij):
# Izračunajte drseče povprečje krivulje z danim radijem
velikost_okna = 2 * polmer + 1
jedro = np.ones (velikost_okna) / velikost_okna
curve_padded = np.lib.pad (krivulja, (polmer, polmer), 'rob')
smoothed_curve = np.convolve (curve_paded, kernel, mode='enako')
zglajena_krivulja = zglajena_krivulja[polmer:-polmer]
vrnitev zglajena_krivulja
Funkcija vrne gladko krivuljo. Pomaga zmanjšati hrup in nihanja v krivulji. To naredi s povprečenjem vrednosti znotraj drsnega okna.
Funkcija smooth_trajectory
Ustvarite drugo funkcijo in jo poimenujte gladka_pot. Ta funkcija bo uporabila drseče povprečje za vsako dimenzijo trajektorije. To bo dosegel z ustvarjanjem zglajene kopije izvirne trajektorije. To bo dodatno izboljšalo stabilnost videa.
defgladka_pot(pot):
# Zgladite trajektorijo z drsečim povprečjem na vsaki dimenziji
smoothed_trajectory = np.copy (trajectory)za jaz v obseg (3):
zglajena_trajektorija[:, i] = izračunaj drseče_povprečje(
pot [:, i],
radius=SMOOTHING_RADIUS
)
vrnitev zglajena_pot
The gladka_pot funkcija vrne zglajeno trajektorijo.
Funkcija fix_border
Ustvari končno funkcijo in jo poimenuj popravi mejo. Ta funkcija bo popravila rob okvirja z uporabo transformacije vrtenja in spreminjanja velikosti. Vzame vhodni okvir, izračuna njegovo obliko, sestavi transformacijsko matriko in transformacijo uporabi za okvir. Na koncu vrne fiksni okvir.
defpopravi mejo(okvir):
# Popravite obrobo okvirja z uporabo rotacije in spreminjanja velikosti
okvir_oblika = okvir.oblika
matrix = cv2.getRotationMatrix2D(
(oblika_okvirja[1] / 2, oblika_okvirja [0] / 2),
0,
1.04
)
frame = cv2.warpAffine (frame, matrix, (frame_shape[1], oblika_okvirja[0]))
vrnitev okvir
The popravi mejo funkcija zagotavlja, da stabilizirani okvirji nimajo robnih artefaktov, ki bi jih povzročil postopek stabilizacije.
Inicializacija video stabilizacije in prevzem vhoda
Začnite z nastavitvijo polmera, ki ga bo uporabljala funkcija glajenja trajektorije.
SMOOTHING_RADIUS = 50
Nato prenesite video pot tresočega videa, ki ga želite stabilizirati.
# Odprite vhodno video datoteko
# Zamenjajte pot z 0, če želite uporabiti svojo spletno kamero
cap = cv2.VideoCapture('inputvid.mp4')
Pridobite lastnosti tresočega videoposnetka:
num_frames = int (cap.get (cv2.CAP_PROP_FRAME_COUNT))
širina = int (cap.get (cv2.CAP_PROP_FRAME_WIDTH))
višina = int (cap.get (cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get (cv2.CAP_PROP_FPS)
Nastavite izhodni format. To je format, v katerem bo program shranil stabiliziran video. Uporabite lahko katero koli običajni video format rad imaš.
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
Končno inicializirajte zapisovalnik videa:
out = cv2.VideoWriter('video_out.mp4', fourcc, fps, (2 * širina višina))
Končnica imena datoteke, ki jo posredujete zapisovalniku videoposnetkov, mora biti enaka tisti, ki ste jo nastavili v izhodnem formatu.
Branje in obdelava okvirjev
Tukaj se začne prvi korak obdelave tresočega videa. Vključuje branje okvirjev iz vhodnega videa, izračun transformacij in polnjenje matrike transformacij.
Začnite z branjem prvega okvirja.
_, prev_frame = cap.read()
prev_gray = cv2.cvtColor (prev_frame, cv2.COLOR_BGR2GRAY)
Nato inicializirajte transformacijsko polje. Shranil bo informacije za vsak okvir.
transformacije = np.zeros((število_okvirov - 1, 3), np.float32)
Nazadnje morate izračunati optični pretok med zaporednimi sličicami. Nato ocenite afino transformacijo med točkami.
za jaz v obseg (število_okvirov - 2):
# Izračunajte optični pretok med zaporednimi sličicami
prev_points = cv2.goodFeaturesToTrack(
prev_gray,
maxCorners=200,
Raven kakovosti=0.01,
minDistance=30,
velikost bloka=3
)uspeh, curr_frame = cap.read()
čene uspeh:
odmorcurr_gray = cv2.cvtColor (curr_frame, cv2.COLOR_BGR2GRAY)
curr_points, status, err = cv2.calcOpticalFlowPyrLK(
prev_gray,
curr_gray,
prejšnje_točke,
Noben
)trditi prev_points.shape == curr_points.shape
idx = np.kjer (stanje == 1)[0]
prejšnje_točke = prejšnje_točke[idx]
curr_points = curr_points[idx]
# Oceni afino transformacijo med točkami
matrika, _ = cv2.estimateAffine2D(prev_points, curr_points)
prevod_x = matrika[0, 2]
prevod_y = matrika[1, 2]
rotacijski kot = np.arctan2(matrika[1, 0], matrika[0, 0])
transforms[i] = [translation_x, translation_y, rotation_angle]
prejšnja_siva = curr_siva
Zanka ponavlja vsak okvir (razen zadnji okvir), da izračuna transformacije. Izračunava optični pretok med zaporednimi sličicami z uporabo metode Lucas-Kanade. cv2.goodFeaturesToTrack zazna značilne točke v prejšnjem okvirju prev_gray. potem, cv2.calcOpticalFlowPyrLK sledi tem točkam v trenutnem okviru curr_gray.
Samo točke s statusom 1 (kar kaže na uspešno sledenje) pomagajo pri ocenjevanju matrike afine transformacije. Koda posodablja prev_gray spremenljivko s trenutnim okvirjem v sivinah za naslednjo ponovitev.
Glajenje poti
Za dosego stabilnega rezultata morate zgladiti pot, pridobljeno s transformacijami.
# Izračunajte trajektorijo s kumulativnim seštevanjem transformacij
trajektorija = np.cumsum (transformacije, os=0)# Zgladite pot z drsečim povprečjem
zglajena_pot = gladka_pot (pot)# Izračunajte razliko med zglajeno in izvirno trajektorijo
razlika = zglajena_pot - trajektorija
# Dodajte razliko prvotnim transformacijam, da dobite gladkost
# transformacije
transforms_smooth = transforms + razlika
Zgornja koda izračuna trajektorijo gibanja kamere in jo zgladi.
Stabilizacijski in pisalni okvirji
Zadnji korak je stabilizacija okvirjev in pisanje stabiliziranega videa v izhodno datoteko.
Začnite s ponastavitvijo zajema videa. To zagotavlja, da bodo prihodnje operacije brale od začetka videa.
cap.set (cv2.CAP_PROP_POS_FRAMES, 0)
Nato stabilizirajte video z obdelavo vsakega okvirja.
# Obdelajte vsak okvir in stabilizirajte video
za jaz v obseg (število_okvirov - 2):
uspeh, okvir = cap.read()čene uspeh:
odmorprevod_x = transforms_smooth[i, 0]
prevod_y = transforms_smooth[i, 1]
rotation_angle = transforms_smooth[i, 2]# Ustvarite transformacijsko matriko za stabilizacijo
transformacijska_matrika = np.ničle((2, 3), np.float32)
transformacijska_matrika[0, 0] = np.cos (rotacijski kot)
transformacijska_matrika[0, 1] = -np.sin (rotacijski kot)
transformacijska_matrika[1, 0] = np.sin (rotacijski kot)
transformacijska_matrika[1, 1] = np.cos (rotacijski kot)
transformacijska_matrika[0, 2] = prevod_x
transformacijska_matrika[1, 2] = prevod_y# Uporabite transformacijo za stabilizacijo okvirja
frame_stabilized = cv2.warpAffine(
okvir,
transformacijska_matrika,
(širina višina)
)# Popravite obrobo stabiliziranega okvirja
okvir_stabiliziran = fix_border (frame_stabilized)# Združite izvirne in stabilizirane okvirje enega poleg drugega
frame_out = cv2.hconcat([frame, frame_stabilized])# Spremenite velikost okvirja, če njegova širina presega 1920 slikovnih pik
če frame_out.shape[1] > 1920:
frame_out = cv2.resize(
frame_out,
(frame_out.shape[1] // 2, frame_out.shape[0] // 2)
)# Prikaži okvirje pred in po
cv2.imshow("Pred in po", frame_out)
cv2.waitKey(10)
# Zapišite okvir v izhodno video datoteko
out.write (frame_out)
Zgornja koda stabilizira vsak okvir z izračunanimi transformacijami, vključno s prilagoditvami prevajanja in vrtenja. Nato združi stabilizirane okvirje z originalnimi, da zagotovi primerjavo.
Izdaja Video Capture in Writer
Dokončajte program tako, da sprostite objekte za zajem videa in zapisovanje.
# Sprostite zajem in zapisovalnik videa ter zaprite vsa odprta okna
cap.release()
out.release()
cv2.destroyAllWindows()
Ta koda tudi zapre vsa odprta okna.
Končni rezultat programa
Izhod programa bo videti nekako takole:
In tukaj je primer stabiliziranega videa:
Izhod prikazuje primerjavo med drhtajočim videoposnetkom in stabiliziranim.
Raziščite zmogljivosti OpenCV
OpenCV lahko uporabite na številnih področjih, ki vključujejo računalniški vid. To je zato, ker ponuja široko paleto funkcionalnosti. Raziščite njegove zmožnosti z delom na več projektih, ki vključujejo računalniški vid. To vam bo predstavilo nove koncepte in vam dalo nova področja za raziskovanje.