Izmantojiet šo paņēmienu, lai izmantotu gudru matemātiku saviem videoklipiem un samazinātu drebēšanu.

Video stabilizācija ir paņēmiens, kas samazina nevēlamu kustību un drebēšanu video materiālā. Fotografēšana, turot rokās, vibrācija un kustība var izraisīt nestabilas kameras kustības. Video stabilizācija nodrošina vienmērīgāku video izskatu.

Video stabilizācijas galvenais mērķis ir novērtēt kameras kustību starp secīgiem kadriem. Pēc tam process var piemērot atbilstošas ​​transformācijas, lai izlīdzinātu kadrus. Tas samazina uztverto kustību.

Jūsu vides iestatīšana

Sāciet ar veidojot virtuālo vidi lai nodrošinātu, ka pakotnes, kuras instalējat programmas palaišanai, nav pretrunā esošajām. Pēc tam palaidiet šo termināļa komandu, lai instalētu nepieciešamās bibliotēkas:

pip instalēt opencv-python numpy

Šī komanda instalē NumPy un OpenCV bibliotēkas. NumPy nodrošina rīkus skaitliskiem uzdevumiem kamēr OpenCV nodarbojas ar datorredzes uzdevumiem.

Pilns pirmkods ir pieejams a GitHub repozitorijs.

instagram viewer

Nepieciešamo bibliotēku importēšana un trīs svarīgāko funkciju definēšana

Izveidojiet jaunu Python failu un piešķiriet tam sev tīkamu nosaukumu. Importējiet NumPy un OpenCV bibliotēkas skripta sākumā.

imports nejutīgs  np
imports cv2

Importējot šīs bibliotēkas, varēsit izmantot to funkcijas savā kodā.

Tālāk definējiet trīs funkcijas, kurām būs izšķiroša nozīme stabilizācijas procesā.

Funkcija Calculation_moving_average

Izveidojiet funkciju un nosauciet to aprēķināt_kustīgo_vidējo. Šī funkcija aprēķinās dotās līknes mainīgo vidējo, izmantojot jūsu norādīto rādiusu. Tajā tiek izmantota konvolūcijas darbība ar noteiktu loga izmēru un vienotu kodolu. Šis mainīgais vidējais palīdz izlīdzināt trajektorijas svārstības.

defaprēķināt_kustīgo_vidējo(līkne, rādiuss):
# Aprēķiniet līknes mainīgo vidējo, izmantojot noteiktu rādiusu
loga_izmērs = 2 * rādiuss + 1
kodols = np.ones (window_size) / window_size
curve_padded = np.lib.pad (līkne, (rādiuss, rādiuss), 'mala')
smoothed_curve = np.convolve (curve_padded, kodols, mode='tas pats')
izlīdzināta_līkne = izlīdzināta_līkne[rādiuss:-rādiuss]
atgriezties izlīdzināta_līkne

Funkcija atgriež vienmērīgu līkni. Tas palīdz samazināt troksni un līknes svārstības. Tas tiek darīts, bīdāmajā logā aprēķinot vidējo vērtību.

Funkcija gluda_trajektorija

Izveidojiet citu funkciju un nosauciet to gluda_trajektorija. Šī funkcija piemēros mainīgo vidējo vērtību katrai trajektorijas dimensijai. Tas tiks sasniegts, izveidojot izlīdzinātu sākotnējās trajektorijas kopiju. Tas vēl vairāk uzlabos video stabilitāti.

defgluda_trajektorija(trajektorija):
# Izlīdziniet trajektoriju, izmantojot mainīgo vidējo katrā dimensijā
izlīdzināta_trajektorija = np.copy (trajektorija)

priekš i iekšā diapazons(3):
izlīdzināta_trajektorija[:, i] = aprēķināt_kustīgo_vidējo(
trajektorija[:, i],
rādiuss=SMOOTHING_RADIUS
)

atgriezties izlīdzinātā_trajektorija

The gluda_trajektorija funkcija atgriež izlīdzinātu trajektoriju.

Funkcija fix_border

Izveidojiet galīgo funkciju un nosauciet to fix_border. Šī funkcija nofiksēs kadra apmali, izmantojot pagriešanas un mērogošanas transformāciju. Tas ņem ievades rāmi, aprēķina tā formu, izveido transformācijas matricu un piemēro transformāciju kadram. Visbeidzot, tas atgriež fiksēto rāmi.

deffix_border(rāmis):
# Nostipriniet rāmja apmali, izmantojot pagriešanas un mērogošanas transformāciju
frame_shape = rāmis.forma

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

rāmis = cv2.warpAffine (rāmis, matrica, (frame_shape[1], rāmja_forma[0]))
atgriezties rāmis

The fix_border funkcija nodrošina, ka stabilizētajiem kadriem nav stabilizēšanas procesa izraisītu robežartefaktu.

Video stabilizācijas inicializēšana un ievades saņemšana

Sāciet ar rādiusa iestatīšanu, ko izmantos trajektorijas izlīdzināšanas funkcija.

SMOOTHING_RADIUS = 50

Pēc tam virziet to nestabilā videoklipa video ceļu, kuru vēlaties stabilizēt.

# Atveriet ievades video failu
# Lai izmantotu tīmekļa kameru, aizstājiet ceļu ar 0
cap = cv2.VideoCapture("inputvid.mp4")

Iegūstiet nestabilā videoklipa īpašības:

num_frames = int (cap.get (cv2.CAP_PROP_FRAME_COUNT))
platums = int (cap.get (cv2.CAP_PROP_FRAME_WIDTH))
augstums = int (cap.get (cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get (cv2.CAP_PROP_FPS)

Iestatiet izvades formātu. Tas ir formāts, kādā programma saglabās stabilizēto video. Jūs varat izmantot jebkuru izplatīts video formāts tev patīk.

fourcc = cv2.VideoWriter_fourcc(*"mp4v")

Visbeidzot inicializējiet video rakstītāju:

out = cv2.VideoWriter("video_out.mp4", fourcc, fps, (2 * platums augstums))

Faila nosaukuma paplašinājumam, kuru nododat video ierakstītājam, ir jābūt tādam pašam kā paplašinājumam, kuru iestatījāt izvades formātā.

Rāmju lasīšana un apstrāde

Šeit sākas drebošā videoklipa apstrādes pirmais solis. Tas ietver kadru nolasīšanu no ievades video, transformāciju aprēķināšanu un transformāciju masīva aizpildīšanu.

Sāciet, izlasot pirmo kadru.

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

Pēc tam inicializējiet transformācijas masīvu. Tajā tiks saglabāta informācija par katru kadru.

transforms = np.zeros((kadru_skaits - 1, 3), np.float32)

Visbeidzot, jums jāaprēķina optiskā plūsma starp secīgiem kadriem. Pēc tam novērtējiet afīnās transformācijas starp punktiem.

priekš i iekšā diapazons (kadru_skaits - 2):
# Aprēķiniet optisko plūsmu starp secīgiem kadriem
prev_points = cv2.goodFeaturesToTrack(
prev_grey,
maxCorners=200,
kvalitātes līmenis=0.01,
minDistance=30,
blockSize=3
)

panākumi, curr_frame = cap.read()

ja panākumi:
pārtraukums

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

curr_points, status, err = cv2.calcOpticalFlowPyrLK(
prev_grey,
curr_grey,
iepriekšējie_punkti,
Nav
)

apgalvot prev_points.shape == curr_points.shape
idx = np.kur (statuss == 1)[0]
iepriekšējie_punkti = iepriekšējie_punkti[idx]
Curr_points = Curr_points[idx]

# Novērtējiet afīnu transformāciju starp punktiem
matrica, _ = cv2.estimateAffine2D(iepriekšējie_punkti, pašreizējā_punkti)
tulkojums_x = matrica[0, 2]
tulkojums_y = matrica[1, 2]
rotācijas_leņķis = np.arctan2(matrica[1, 0], matrica[0, 0])
transforms[i] = [tulkojums_x, tulkojums_y, rotācijas_leņķis]
prev_grey = curr_grey

Cilpa atkārtojas katrā kadrā (izņemot pēdējo kadru), lai aprēķinātu transformācijas. Tas aprēķina optisko plūsmu starp secīgiem kadriem, izmantojot Lucas-Kanade metodi. cv2.goodFeaturesToTrack nosaka iezīmju punktus iepriekšējā kadrā prev_grey. Tad cv2.calcOpticalFlowPyrLK izseko šos punktus pašreizējā kadrā curr_grey.

Tikai punkti ar statusu 1 (norāda uz veiksmīgu izsekošanu) palīdz novērtēt afīnās transformācijas matricu. Kods atjaunina prev_grey mainīgais ar pašreizējo pelēktoņu rāmi nākamajai iterācijai.

Trajektorijas izlīdzināšana

No transformācijām iegūtā trajektorija ir jāizlīdzina, lai sasniegtu stabilu rezultātu.

# Aprēķiniet trajektoriju, kumulatīvi summējot pārvērtības
trajektorija = np.cumsum (pārveido, ass=0)

# Izlīdziniet trajektoriju, izmantojot mainīgo vidējo
nogludināta_trajektorija = gluda_trajektorija (trajektorija)

# Aprēķiniet atšķirību starp izlīdzināto un sākotnējo trajektoriju
atšķirība = nogludināta_trajektorija - trajektorija

# Pievienojiet atšķirību atpakaļ sākotnējām transformācijām, lai iegūtu vienmērīgu
# pārvērtības
transforms_smooth = pārveido + atšķirība

Iepriekš minētais kods aprēķina kameras kustības trajektoriju un izlīdzina to.

Stabilizējošie un rakstāmie rāmji

Pēdējais solis ir stabilizēt kadrus un ierakstīt stabilizēto video izvades failā.

Sāciet ar video uzņemšanas atiestatīšanu. Tas nodrošina, ka turpmākās darbības tiks nolasītas no videoklipa sākuma.

cap.set (cv2.CAP_PROP_POS_FRAMES, 0)

Pēc tam stabilizējiet video, apstrādājot katru kadru.

# Apstrādājiet katru kadru un stabilizējiet video
priekš i iekšā diapazons (kadru_skaits - 2):
panākumi, rāmis = cap.read()

ja panākumi:
pārtraukums

tulkojums_x = pārveido_smooth[i, 0]
tulkojums_y = pārveido_smooth[i, 1]
rotācijas_leņķis = transforms_smooth[i, 2]

# Izveidojiet transformācijas matricu stabilizēšanai
transformācijas_matrica = np.zeros((2, 3), np.float32)
transformācijas_matrica[0, 0] = np.cos (rotācijas_leņķis)
transformācijas_matrica[0, 1] = -np.sin (rotācijas_leņķis)
transformācijas_matrica[1, 0] = np.sin (rotācijas_leņķis)
transformācijas_matrica[1, 1] = np.cos (rotācijas_leņķis)
transformācijas_matrica[0, 2] = tulkojums_x
transformācijas_matrica[1, 2] = tulkojums_y

# Lietojiet transformāciju, lai stabilizētu rāmi
frame_stabilized = cv2.warpAffine(
rāmis,
transformācijas_matrica,
(platums augstums)
)

# Piestipriniet stabilizētā rāmja apmali
frame_stabilized = fix_border (frame_stabilized)

# Savienojiet oriģinālos un stabilizētos kadrus blakus
frame_out = cv2.hconcat([kadrs, kadrs_stabilizēts])

# Mainiet rāmja izmēru, ja tā platums pārsniedz 1920 pikseļus
ja frame_out.shape[1] > 1920:
frame_out = cv2.resize(
frame_out,
(frame_out.shape[1] // 2, frame_out.shape[0] // 2)
)

# Parādiet kadrus pirms un pēc
cv2.imshow("Pirms un pēc", frame_out)
cv2.waitKey(10)

# Ierakstiet rāmi izvades video failā
out.write (frame_out)

Iepriekš minētais kods stabilizē katru kadru, izmantojot aprēķinātās transformācijas, tostarp translācijas un rotācijas korekcijas. Pēc tam tas apvieno stabilizētos rāmjus ar oriģinālajiem, lai nodrošinātu salīdzinājumu.

Video tveršanas un rakstīšanas programmas izlaišana

Pabeidziet programmu, atbrīvojot video uzņemšanas un rakstīšanas objektus.

# Atlaidiet video tveršanu un rakstītāju un aizveriet visus atvērtos logus
cap.release()
out.release()
cv2.destroyAllWindows()

Šis kods arī aizver visus atvērtos logus.

Galīgā programmas izvade

Programmas izvade izskatīsies apmēram šādi:

Un šeit ir stabilizētā videoklipa piemērs:

Izvade parāda salīdzinājumu starp nestabilo un stabilizēto video.

Izpētiet OpenCV iespējas

Varat izmantot OpenCV daudzās jomās, kas saistītas ar datorredzi. Tas ir tāpēc, ka tas piedāvā plašu funkciju klāstu. Jums vajadzētu izpētīt tā iespējas, strādājot pie vairākiem projektiem, kas ietver datora redzi. Tas jūs iepazīstinās ar jauniem jēdzieniem un dos jums jaunas pētniecības jomas.