Brug denne teknik til at anvende noget smart matematik på dine videoer og reducere rystelser.
Videostabilisering er en teknik, der reducerer uønsket bevægelse og rystelser i videooptagelser. Håndholdt optagelse, vibration og bevægelse kan alle forårsage ustabile kamerabevægelser. Videostabilisering giver en video, der ser mere jævnt ud.
Det primære mål med videostabilisering er at estimere kameraets bevægelse mellem på hinanden følgende billeder. Processen kan derefter anvende passende transformationer for at justere rammerne. Dette minimerer den opfattede bevægelse.
Opsætning af dit miljø
Start med skabe et virtuelt miljø for at sikre, at de pakker, du installerer for at køre programmet, ikke er i konflikt med eksisterende. Kør derefter denne terminalkommando for at installere de nødvendige biblioteker:
pip installer opencv-python numpy
Denne kommando installerer NumPy- og OpenCV-biblioteker. NumPy giver værktøjer til numeriske opgaver mens OpenCV beskæftiger sig med computervisionsopgaver.
Den fulde kildekode er tilgængelig i en GitHub-depot.
Import af de nødvendige biblioteker og definition af tre afgørende funktioner
Opret en ny Python-fil, og giv den et navn, du kan lide. Importer NumPy- og OpenCV-biblioteker i begyndelsen af scriptet.
importere nusset som np
importere cv2
Import af disse biblioteker vil gøre dig i stand til at bruge deres funktioner i din kode.
Dernæst skal du definere tre funktioner, der vil være afgørende for stabiliseringsprocessen.
Funktionen beregne_bevægende_gennemsnit
Opret en funktion og navngiv den beregne_bevægende_gennemsnit. Denne funktion vil beregne det glidende gennemsnit af en given kurve ved hjælp af den radius, du angiver. Den anvender en foldningsoperation med en specificeret vinduesstørrelse og en ensartet kerne. Dette glidende gennemsnit hjælper med at udjævne udsving i banen.
defberegne_bevægende_gennemsnit(kurve, radius):
# Beregn det glidende gennemsnit af en kurve ved hjælp af en given radius
vinduesstørrelse = 2 * radius + 1
kernel = np.ones (vinduesstørrelse) / vinduesstørrelse
curve_padded = np.lib.pad (kurve, (radius, radius), 'kant')
smoothed_curve = np.convolve (curve_padded, kernel, mode='samme')
glattet_kurve = glattet_kurve[radius:-radius]
Vend tilbage glattet_kurve
Funktionen returnerer en jævn kurve. Det er med til at reducere støj og udsving i kurven. Det gør det ved at beregne et gennemsnit af værdierne i det glidende vindue.
Funktionen smooth_trajectory
Opret en anden funktion og navngiv den glat_bane. Denne funktion vil anvende det glidende gennemsnit på hver dimension af banen. Det vil opnå dette ved at skabe en udjævnet kopi af den originale bane. Dette vil yderligere forbedre stabiliteten af videoen.
defglat_bane(bane):
# Udglat banen ved hjælp af glidende gennemsnit på hver dimension
smoothed_trajectory = np.copy (bane)til jeg i rækkevidde(3):
smoothed_trajectory[:, i] = beregne_bevægende_gennemsnit(
bane[:, i],
radius=SMOOTHING_RADIUS
)
Vend tilbage glattede_bane
Det glat_bane funktion returnerer en udjævnet bane.
Funktionen fix_border
Opret en sidste funktion og navngiv den fix_border. Denne funktion vil fiksere rammens kant ved at anvende en rotations- og skaleringstransformation. Den tager inputrammen, beregner dens form, konstruerer en transformationsmatrix og anvender transformationen til rammen. Til sidst returnerer den den faste ramme.
deffix_border(ramme):
# Fix rammekanten ved at anvende rotation og skaleringstransformation
frame_shape = frame.shape
matrix = cv2.getRotationMatrix2D(
(ramme_form[1] / 2, rammeform[0] / 2),
0,
1.04
)
ramme = cv2.warpAffine (ramme, matrix, (ramme_form[1], rammeform[0]))
Vend tilbage ramme
Det fix_border funktion sikrer, at de stabiliserede rammer ikke har nogen kantartefakter forårsaget af stabiliseringsprocessen.
Initialisering af videostabilisering og modtagelse af input
Start med at indstille den radius, som baneudjævningsfunktionen skal bruge.
SMOOTHING_RADIUS = 50
Gå derefter ind i videostien til den rystende video, du vil stabilisere.
# Åbn inputvideofilen
# Erstat stien med 0 for at bruge dit webcam
cap = cv2.VideoCapture('inputvid.mp4')
Få den rystede videos egenskaber:
num_frames = int (cap.get (cv2.CAP_PROP_FRAME_COUNT))
width = int (cap.get (cv2.CAP_PROP_FRAME_WIDTH))
højde = int (cap.get (cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get (cv2.CAP_PROP_FPS)
Indstil outputformatet. Dette er det format, som programmet vil gemme den stabiliserede video med. Du kan bruge enhver almindeligt videoformat Du kan lide.
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
Til sidst initialiserer du videoskriveren:
ud = cv2.VideoWriter('video_out.mp4', fourcc, fps, (2 * bredde højde))
Udvidelsen af filnavnet, du sender til videobrænderen, skal være den samme som den, du indstillede i outputformatet.
Læse- og bearbejdningsrammer
Det første trin i behandlingen af den rystende video starter her. Det involverer at læse rammer fra inputvideoen, beregne transformationer og udfylde transformationsarrayet.
Start med at læse den første ramme.
_, prev_frame = cap.read()
prev_gray = cv2.cvtColor (prev_frame, cv2.COLOR_BGR2GRAY)
Initialiser derefter transformationsarrayet. Det vil gemme oplysninger for hver frame.
transformerer = np.zeros((antal_frames - 1, 3), np.float32)
Til sidst skal du beregne det optiske flow mellem på hinanden følgende billeder. Estimer derefter affin transformation mellem punkterne.
til jeg i interval (antal_frames - 2):
# Beregn optisk flow mellem på hinanden følgende billeder
prev_points = cv2.goodFeaturesToTrack(
prev_grå,
maxHjørner=200,
kvalitetsniveau=0.01,
minDistance=30,
blokstørrelse=3
)succes, curr_frame = cap.read()
hvisikke succes:
pausecurr_gray = cv2.cvtColor (curr_frame, cv2.COLOR_BGR2GRAY)
curr_points, status, err = cv2.calcOpticalFlowPyrLK(
prev_grå,
curr_grå,
prev_points,
Ingen
)hævde prev_points.shape == curr_points.shape
idx = np.where (status == 1)[0]
prev_points = prev_points[idx]
curr_points = curr_points[idx]
# Estimer affin transformation mellem punkterne
matrix, _ = cv2.estimateAffine2D(prev_points, curr_points)
translation_x = matrix[0, 2]
translation_y = matrix[1, 2]
rotationsvinkel = np.arctan2(matrix[1, 0], matrix[0, 0])
transformerer[i] = [translation_x, translation_y, rotation_angle]
prev_gray = curr_gray
Sløjfen itererer over hver ramme (undtagen den sidste ramme) for at beregne transformationer. Den beregner optisk flow mellem på hinanden følgende billeder ved hjælp af Lucas-Kanade-metoden. cv2.goodFeaturesToTrack registrerer punkter i det forrige billede prev_grå. Derefter, cv2.calcOpticalFlowPyrLK sporer disse punkter i det aktuelle billede curr_grå.
Kun punkterne med status 1 (indikerer vellykket sporing) hjælper med at estimere en affin transformationsmatrix. Koden opdaterer prev_grå variabel med den aktuelle gråtoneramme til næste iteration.
Udjævning af banen
Du skal udjævne banen opnået fra transformationerne for at opnå et stabilt resultat.
# Beregn banen ved kumulativt at summere transformationerne
bane = np.cumsum (transformeres, akse=0)# Udglat banen ved hjælp af glidende gennemsnit
smoothed_trajectory = smooth_trajectory (bane)# Beregn forskellen mellem den udjævnede og den oprindelige bane
difference = smoothed_trajectory - bane
# Tilføj forskellen tilbage til de oprindelige transformationer for at opnå jævn
# transformationer
transformer_glat = transformerer + forskel
Ovenstående kode beregner kamerabevægelsens bane og udjævner den.
Stabiliserende og skrive rammer
Det sidste trin er at stabilisere rammerne og skrive den stabiliserede video ind i en outputfil.
Start med at nulstille videooptagelsen. Dette sikrer, at fremtidige operationer læses fra starten af videoen.
cap.set (cv2.CAP_PROP_POS_FRAMES, 0)
Stabiliser derefter videoen ved at behandle hvert enkelt billede.
# Bearbejd hvert billede og stabiliser videoen
til jeg i interval (antal_frames - 2):
succes, frame = cap.read()hvisikke succes:
pausetranslation_x = transformerer_glat[i, 0]
translation_y = transformerer_glat[i, 1]
rotationsvinkel = transformerer_glat[i, 2]# Opret transformationsmatrixen til stabilisering
transformation_matrix = np.zeros((2, 3), np.float32)
transformationsmatrix[0, 0] = np.cos (rotationsvinkel)
transformationsmatrix[0, 1] = -np.sin (rotationsvinkel)
transformationsmatrix[1, 0] = np.sin (rotationsvinkel)
transformationsmatrix[1, 1] = np.cos (rotationsvinkel)
transformationsmatrix[0, 2] = oversættelse_x
transformationsmatrix[1, 2] = oversættelse_y# Anvend transformationen for at stabilisere rammen
frame_stabilized = cv2.warpAffine(
ramme,
transformation_matrix,
(bredde højde)
)# Fastgør kanten af den stabiliserede ramme
frame_stabilized = fix_border (ramme_stabilized)# Sammenkæd de originale og stabiliserede rammer side om side
frame_out = cv2.hconcat([ramme, frame_stabilized])# Ændr størrelsen på rammen, hvis dens bredde overstiger 1920 pixels
hvis frame_out.shape[1] > 1920:
frame_out = cv2.resize(
frame_out,
(ramme_ud.form[1] // 2, frame_out.shape[0] // 2)
)# Vis før- og efterbillederne
cv2.imshow("Før og efter", frame_out)
cv2.waitKey(10)
# Skriv rammen til outputvideofilen
out.write (frame_out)
Ovenstående kode stabiliserer hver frame ved hjælp af de beregnede transformationer, inklusive translation og rotationsjusteringer. Den kombinerer derefter de stabiliserede rammer med de originale for at give en sammenligning.
Frigivelse af videooptagelse og forfatter
Afslut programmet ved at frigive videooptagelses- og skriveobjekterne.
# Slip videooptagelsen og forfatteren, og luk alle åbne vinduer
cap.release()
out.release()
cv2.destroyAllWindows()
Denne kode lukker også alle åbne vinduer.
Endeligt program output
Udgangen af programmet vil se nogenlunde således ud:
Og her er et eksempel på den stabiliserede video:
Outputtet viser sammenligningen mellem den rystende video og den stabiliserede.
Udforsk OpenCV-funktioner
Du kan anvende OpenCV på mange områder, der involverer computersyn. Det er fordi det tilbyder en bred vifte af funktionaliteter. Du bør udforske dens muligheder ved at arbejde på flere projekter, der involverer computersyn. Dette vil introducere dig til nye koncepter og give dig nye områder at forske i.