Használja ezt a technikát, hogy okos matematikát alkalmazzon videóira, és csökkentse a remegést.

A videostabilizálás egy olyan technika, amely csökkenti a nem kívánt mozgást és remegést a videofelvételeken. A kézi fényképezés, a vibráció és a mozgás bizonytalan kameramozgást okozhat. A videostabilizálás simább megjelenésű videót eredményez.

A videostabilizálás elsődleges célja a kamera mozgásának becslése az egymást követő képkockák között. A folyamat ezután megfelelő átalakításokat alkalmazhat a keretek igazításához. Ez minimálisra csökkenti az észlelt mozgást.

Környezetének beállítása

Kezdje ezzel virtuális környezet létrehozása hogy a program futtatásához telepített csomagok ne ütközzenek a meglévőkkel. Ezután futtassa ezt a terminálparancsot a szükséges könyvtárak telepítéséhez:

pip install opencv-python numpy

Ez a parancs telepíti a NumPy és az OpenCV könyvtárakat. A NumPy eszközöket biztosít a numerikus feladatokhoz míg az OpenCV számítógépes látási feladatokkal foglalkozik.

A teljes forráskód elérhető a GitHub adattár.

instagram viewer

A szükséges könyvtárak importálása és három kulcsfontosságú funkció meghatározása

Hozzon létre egy új Python-fájlt, és adjon neki egy tetszőleges nevet. Importálja a NumPy és OpenCV könyvtárakat a szkript elejére.

import zsibbadt mint np
import cv2

Ezen könyvtárak importálása lehetővé teszi a funkcióik használatát a kódban.

Ezután határozzon meg három olyan funkciót, amelyek kulcsfontosságúak lesznek a stabilizációs folyamat szempontjából.

A számítási_mozgó_átlag függvény

Hozzon létre egy függvényt, és nevezze el számolja ki a mozgóátlagot. Ez a függvény kiszámítja egy adott görbe mozgóátlagát az Ön által megadott sugár segítségével. Konvolúciós műveletet alkalmaz meghatározott ablakmérettel és egységes kernellel. Ez a mozgóátlag segít kisimítani a pálya ingadozásait.

defszámolja ki a mozgóátlagot(görbe, sugár):
# Számítsa ki egy görbe mozgóátlagát egy adott sugár használatával
window_size = 2 * sugár + 1
kernel = np.ones (ablakméret) / ablakméret
curve_padded = np.lib.pad (görbe, (sugár, sugár), 'él')
smoothed_curve = np.convolve (curve_padded, kernel, mode='azonos')
simított_görbe = simított_görbe[sugár:-sugár]
Visszatérés simított_görbe

A függvény sima görbét ad vissza. Segít csökkenteni a zajt és a görbe ingadozásait. Ezt a csúszó ablakon belüli értékek átlagolásával teszi.

A smooth_trajectory függvény

Hozzon létre egy másik függvényt, és nevezze el sima_pálya. Ez a funkció a mozgóátlagot alkalmazza a pálya minden dimenziójára. Ezt úgy éri el, hogy elkészíti az eredeti pálya simított másolatát. Ez tovább javítja a videó stabilitását.

defsima_pálya(röppálya):
# Simítsa a pályát a mozgóátlag segítségével minden dimenzióban
kisimított_pálya = np.copy (pálya)

számára én ban ben hatótávolság(3):
simított_trajektória[:, i] = számolja_mozgó_átlag(
pálya[:, i],
sugár=SMOOTHING_RADIUS
)

Visszatérés simított_pálya

A sima_pálya függvény simított pályát ad vissza.

A fix_border függvény

Hozzon létre egy végső függvényt, és nevezze el fix_border. Ez a funkció rögzíti a keret szegélyét elforgatás és méretezési transzformáció alkalmazásával. Felveszi a bemeneti keretet, kiszámítja az alakját, összeállít egy transzformációs mátrixot, és alkalmazza a transzformációt a keretre. Végül visszaadja a rögzített keretet.

deffix_border(keret):
# Rögzítse a keret szegélyét elforgatás és méretezési transzformáció alkalmazásával
frame_shape = keret.alak

mátrix = cv2.getRotationMatrix2D(
(keret_alak[1] / 2, frame_shape[0] / 2),
0,
1.04
)

frame = cv2.warpAffine (keret, mátrix, (frame_shape[1], frame_shape[0]))
Visszatérés keret

A fix_border A funkció biztosítja, hogy a stabilizált kereteken ne legyen a stabilizációs folyamat által okozott szegélymű.

A videostabilizálás inicializálása és a bemenet felvétele

Kezdje a sugár beállításával, amelyet a pályasimító funkció használni fog.

SMOOTHING_RADIUS = 50

Ezután adja meg a stabilizálni kívánt remegő videó videoútját.

# Nyissa meg a bemeneti videofájlt
# Cserélje ki az elérési utat 0-ra a webkamera használatához
cap = cv2.VideoCapture("inputvid.mp4")

Szerezze meg a remegő videó tulajdonságait:

num_frames = int (cap.get (cv2.CAP_PROP_FRAME_COUNT))
szélesség = int (cap.get (cv2.CAP_PROP_FRAME_WIDTH))
magasság = int (cap.get (cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get (cv2.CAP_PROP_FPS)

Állítsa be a kimeneti formátumot. Ez az a formátum, amellyel a program elmenti a stabilizált videót. Bármelyiket használhatod általános videóformátum kedveled.

fourcc = cv2.VideoWriter_fourcc(*'mp4v')

Végül inicializálja a videó íróját:

out = cv2.VideoWriter("video_out.mp4", négycc, fps, (2 * szélesség magasság))

A videóírónak átadott fájlnév kiterjesztésének meg kell egyeznie a kimeneti formátumban megadott kiterjesztéssel.

Keretek olvasása és feldolgozása

A remegő videó feldolgozásának első lépése itt kezdődik. Ez magában foglalja a képkockák beolvasását a bemeneti videóból, a transzformációk kiszámítását és a transzformációs tömb feltöltését.

Kezdje az első képkocka elolvasásával.

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

Ezután inicializálja a transzformációs tömböt. Minden egyes képkockához tárolja az információkat.

transzformációk = np.zeros((kockák_száma - 1, 3), np.float32)

Végül ki kell számítania az egymást követő képkockák közötti optikai áramlást. Ezután becsülje meg a pontok közötti affin transzformációt.

számára én ban ben tartomány (kockák_száma - 2):
# Számítsa ki az egymást követő képkockák közötti optikai áramlást
prev_points = cv2.goodFeaturesToTrack(
prev_grey,
maxCorners=200,
minőségi szint=0.01,
minDistance=30,
blockSize=3
)

siker, curr_frame = cap.read()

hanem siker:
szünet

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

curr_points, status, err = cv2.calcOpticalFlowPyrLK(
prev_grey,
curr_grey,
prev_points,
Egyik sem
)

állítja prev_points.shape == curr_points.shape
idx = np.where (állapot == 1)[0]
előző_pontok = előző_pontok[idx]
curr_points = curr_points[idx]

# A pontok közötti affin transzformáció becslése
mátrix, _ = cv2.estimateAffine2D(előző_pontok, aktuális_pontok)
fordítás_x = mátrix[0, 2]
fordítás_y = mátrix[1, 2]
forgásszög = np.arctan2(mátrix[1, 0], mátrix[0, 0])
transzformációk[i] = [fordítás_x, fordítás_y, elforgatási_szög]
prev_gray = curr_gray

A ciklus minden egyes kereten keresztül iterál (kivéve az utolsó képkockát) a transzformációk kiszámításához. Az egymást követő képkockák közötti optikai áramlást a Lucas-Kanade módszerrel számítja ki. cv2.goodFeaturesToTrack észleli az előző képkocka jellemzőpontjait prev_grey. Akkor, cv2.calcOpticalFlowPyrLK követi ezeket a pontokat az aktuális keretben curr_grey.

Az affin transzformációs mátrix becslésében csak az 1-es státuszú (a sikeres követést jelző) pontok segítenek. A kód frissíti a prev_grey változó az aktuális szürkeárnyalatos kerettel a következő iterációhoz.

A pálya simítása

Egyeníteni kell az átalakításokból kapott pályát a stabil eredmény eléréséhez.

# Számítsa ki a trajektóriát a transzformációk kumulatív összegzésével
pálya = np.cumsum (transzformálja, tengely=0)

# Simítsa a pályát mozgóátlag segítségével
kisimított_pálya = sima_pálya (pálya)

# Számítsa ki a különbséget a simított és az eredeti pálya között
különbség = simított_pálya - pálya

# Adja hozzá a különbséget az eredeti átalakításokhoz, hogy egyenletes legyen
# átalakítások
transforms_smooth = átalakul + különbség

A fenti kód kiszámítja a kamera mozgásának pályáját és simítja azt.

Stabilizáló és írókeretek

Az utolsó lépés a képkockák stabilizálása és a stabilizált videó kimeneti fájlba írása.

Kezdje a videórögzítés alaphelyzetbe állításával. Ez biztosítja, hogy a jövőbeni műveletek a videó elejétől olvashatók legyenek.

cap.set (cv2.CAP_PROP_POS_FRAMES, 0)

Ezután stabilizálja a videót az egyes képkockák feldolgozásával.

# Minden képkockát dolgozzon fel, és stabilizálja a videót
számára én ban ben tartomány (kockák_száma - 2):
siker, keret = cap.read()

hanem siker:
szünet

fordítás_x = átalakul_smooth[i, 0]
fordítás_y = átalakul_smooth[i, 1]
rotation_angle = átalakíts_smooth[i, 2]

# Hozzon létre egy transzformációs mátrixot a stabilizáláshoz
transzformációs_mátrix = np.zeros((2, 3), np.float32)
transzformációs_mátrix[0, 0] = np.cos (elforgatási_szög)
transzformációs_mátrix[0, 1] = -np.sin (forgási_szög)
transzformációs_mátrix[1, 0] = np.sin (forgási_szög)
transzformációs_mátrix[1, 1] = np.cos (elforgatási_szög)
transzformációs_mátrix[0, 2] = fordítás_x
transzformációs_mátrix[1, 2] = fordítás_y

# Alkalmazza az átalakítást a keret stabilizálásához
frame_stabilized = cv2.warpAffine(
keret,
transzformációs_mátrix,
(szélesség magasság)
)

# Rögzítse a stabilizált keret szegélyét
frame_stabilized = fix_border (frame_stabilized)

# Kösse össze az eredeti és a stabilizált kereteket egymás mellé
frame_out = cv2.hconcat([frame, frame_stabilized])

# Méretezze át a keretet, ha a szélessége meghaladja az 1920 képpontot
ha frame_out.shape[1] > 1920:
frame_out = cv2.resize(
frame_out,
(frame_out.shape[1] // 2, frame_out.shape[0] // 2)
)

# Az előtti és utáni keret megjelenítése
cv2.imshow("Előtt és után", frame_out)
cv2.waitKey(10)

# Írja be a keretet a kimeneti videofájlba
out.write (frame_out)

A fenti kód stabilizálja az egyes képkockákat a kiszámított transzformációk segítségével, beleértve a fordítási és elforgatási beállításokat. Ezután egyesíti a stabilizált kereteket az eredetivel, hogy összehasonlítást nyújtson.

A Video Capture és Writer kiadása

Végezze el a programot a videorögzítő és -író objektumok felszabadításával.

# Engedje el a videórögzítést és -írót, és zárjon be minden nyitott ablakot
cap.release()
out.release()
cv2.destroyAllWindows()

Ez a kód bezár minden nyitott ablakot is.

Végső programkimenet

A program kimenete valahogy így fog kinézni:

És itt van egy példa a stabilizált videóra:

A kimenet a remegő és a stabilizált videó összehasonlítását mutatja.

Fedezze fel az OpenCV képességeit

Az OpenCV-t számos olyan területen alkalmazhatja, amely számítógépes látással jár. Ennek az az oka, hogy a funkciók széles skáláját kínálja. Fedezze fel a képességeit, ha több olyan projekten dolgozik, amelyek számítógépes látást foglalnak magukban. Ez új fogalmakat vezet be, és új kutatási területeket kínál.