Naudokite šią techniką, kad vaizdo įrašams pritaikytumėte protingą matematiką ir sumažintumėte drebėjimą.

Vaizdo įrašo stabilizavimas yra technika, kuri sumažina nepageidaujamą judesį ir drebėjimą filmuotoje medžiagoje. Fotografavimas laikant ranką, vibracija ir judesys gali sukelti netolygus fotoaparato judesius. Vaizdo įrašo stabilizavimas sukuria sklandžiau atrodantį vaizdo įrašą.

Pagrindinis vaizdo stabilizavimo tikslas yra įvertinti kameros judėjimą tarp nuoseklių kadrų. Tada procesas gali pritaikyti atitinkamas transformacijas, kad suderintų rėmus. Tai sumažina judesį.

Aplinkos nustatymas

Pradėkite nuo sukurti virtualią aplinką užtikrinti, kad paketai, kuriuos įdiegiate norėdami paleisti programą, neprieštarauja esamiems. Tada paleiskite šią terminalo komandą, kad įdiegtumėte reikiamas bibliotekas:

pip įdiegti opencv-python numpy

Ši komanda įdiegia NumPy ir OpenCV bibliotekas. „NumPy“ teikia skaitmeninių užduočių įrankius o OpenCV nagrinėja kompiuterinio matymo užduotis.

Visą šaltinio kodą rasite a GitHub saugykla.

instagram viewer

Reikalingų bibliotekų importavimas ir trijų esminių funkcijų apibrėžimas

Sukurkite naują Python failą ir suteikite jam patinkantį pavadinimą. Scenarijaus pradžioje importuokite NumPy ir OpenCV bibliotekas.

importuoti nelygus kaip np
importuoti cv2

Importuodami šias bibliotekas galėsite naudoti jų funkcijas savo kode.

Toliau apibrėžkite tris funkcijas, kurios bus labai svarbios stabilizavimo procesui.

Funkcija Calculation_moving_average

Sukurkite funkciją ir pavadinkite ją apskaičiuoti_slenkantį_vidurkį. Ši funkcija apskaičiuos tam tikros kreivės slankųjį vidurkį, naudodama jūsų nurodytą spindulį. Jame naudojama konvoliucijos operacija su nurodytu lango dydžiu ir vienodu branduoliu. Šis slenkamasis vidurkis padeda išlyginti trajektorijos svyravimus.

defapskaičiuoti_slenkantį_vidurkį(kreivė, spindulys):
# Apskaičiuokite kreivės slankųjį vidurkį naudodami nurodytą spindulį
lango_dydis = 2 * spindulys + 1
branduolys = np.ones (lango_dydis) / lango_dydis
curve_padded = np.lib.pad (kreivė, (spindulys, spindulys), "kraštas")
smoothed_curve = np.convolve (curve_padded, branduolys, mode='tas pats')
išlyginta_kreivė = išlyginta_kreivė[spindulys:-spindulys]
grąžinti išlyginta_kreivė

Funkcija grąžina lygią kreivę. Tai padeda sumažinti triukšmą ir kreivės svyravimus. Tai daroma slankiojančiame lange apskaičiuojant verčių vidurkį.

Funkcija sklandžiai_trajektorija

Sukurkite kitą funkciją ir pavadinkite ją sklandi_trajektorija. Ši funkcija pritaikys slankųjį vidurkį kiekvienam trajektorijos matmeniui. Tai pasieks sukurdama išlygintą originalios trajektorijos kopiją. Tai dar labiau pagerins vaizdo įrašo stabilumą.

defsklandi_trajektorija(trajektorija):
# Išlyginkite trajektoriją naudodami slankųjį kiekvieno matmens vidurkį
išlyginta_trajektorija = np.copy (trajektorija)

dėl i in diapazonas(3):
išlyginta_trajektorija[:, i] = apskaičiuoti_judantį_vidurkį(
trajektorija[:, i],
spindulys=SMOOTHING_RADIUS
)

grąžinti išlyginta_trajektorija

The sklandi_trajektorija funkcija grąžina išlygintą trajektoriją.

Funkcija fix_border

Sukurkite galutinę funkciją ir pavadinkite ją fix_border. Ši funkcija fiksuos kadro kraštą taikydama pasukimo ir mastelio transformaciją. Jis paima įvesties kadrą, apskaičiuoja jo formą, sukonstruoja transformacijos matricą ir taiko transformaciją kadrui. Galiausiai jis grąžina fiksuotą kadrą.

deffix_border(rėmas):
# Pataisykite rėmelio kraštą taikydami pasukimo ir mastelio transformaciją
rėmo_forma = rėmas.forma

matrica = cv2.getRotationMatrix2D(
(rėmo_forma[1] / 2, rėmo_forma[0] / 2),
0,
1.04
)

rėmelis = cv2.warpAffine (rėmas, matrica, (frame_shape[1], rėmelio_forma[0]))
grąžinti rėmelis

The fix_border funkcija užtikrina, kad stabilizuotuose rėmeliuose nebūtų jokių kraštinių artefaktų, atsiradusių dėl stabilizavimo proceso.

Vaizdo įrašo stabilizavimo inicijavimas ir įvesties paėmimas

Pradėkite nustatydami spindulį, kurį naudos trajektorijos išlyginimo funkcija.

SMOOTHING_RADIUS = 50

Tada pradėkite drebančio vaizdo įrašo, kurį norite stabilizuoti, vaizdo įrašo kelią.

# Atidarykite įvesties vaizdo failą
# Norėdami naudoti internetinę kamerą, pakeiskite kelią į 0
cap = cv2.VideoCapture('inputvid.mp4')

Gaukite drebančio vaizdo įrašo savybes:

num_frames = int (cap.get (cv2.CAP_PROP_FRAME_COUNT))
plotis = int (cap.get (cv2.CAP_PROP_FRAME_WIDTH))
aukštis = int (cap.get (cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get (cv2.CAP_PROP_FPS)

Nustatykite išvesties formatą. Tai yra formatas, kuriuo programa išsaugos stabilizuotą vaizdo įrašą. Galite naudoti bet kurį įprastas vaizdo įrašo formatas tau patinka.

fourcc = cv2.VideoWriter_fourcc(*"mp4v")

Galiausiai inicijuokite vaizdo įrašo kūrėją:

out = cv2.VideoWriter(„video_out.mp4“, fourcc, fps, (2 * plotis Aukštis))

Failo pavadinimo, kurį perduodate vaizdo įrašų kūrėjui, plėtinys turi būti toks pat, kaip ir išvesties formatu.

Rėmelių skaitymas ir apdorojimas

Čia prasideda pirmasis drebančio vaizdo įrašo apdorojimo žingsnis. Tai apima kadrų skaitymą iš įvesties vaizdo įrašo, transformacijų skaičiavimą ir transformacijų masyvo užpildymą.

Pradėkite skaitydami pirmąjį kadrą.

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

Tada inicijuokite transformacijos masyvą. Jame bus saugoma kiekvieno kadro informacija.

transforms = np.zeros((kadrų_skaičius - 1, 3), np.float32)

Galiausiai reikia apskaičiuoti optinį srautą tarp nuoseklių kadrų. Tada įvertinkite afininę transformaciją tarp taškų.

dėl i in diapazonas (kadrų_skaičius – 2):
# Apskaičiuokite optinį srautą tarp nuoseklių kadrų
prev_points = cv2.goodFeaturesToTrack(
prev_grey,
maxCorners=200,
kokybės Lygis =0.01,
minAtstumas =30,
blockSize=3
)

sėkmės, curr_frame = cap.read()

jeigune sėkmė:
pertrauka

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

curr_points, status, err = cv2.calcOpticalFlowPyrLK(
prev_grey,
curr_grey,
ankstesni_taškai,
Nė vienas
)

tvirtinti prev_points.shape == curr_points.shape
idx = np.kur (būsena == 1)[0]
ankstesni_taškai = ankstesni_taškai[idx]
curr_points = curr_points[idx]

# Įvertinkite afininę transformaciją tarp taškų
matrica, _ = cv2.estimateAffine2D(ankstesni_taškai, Curr_points)
vertimas_x = matrica[0, 2]
vertimas_y = matrica[1, 2]
sukimosi_kampas = np.arctan2(matrica[1, 0], matrica[0, 0])
transforms[i] = [vertimas_x, vertimas_y, sukimosi_kampas]
prev_grey = curr_grey

Ciklas kartojasi per kiekvieną kadrą (išskyrus paskutinį kadrą), kad būtų apskaičiuotos transformacijos. Jis apskaičiuoja optinį srautą tarp nuoseklių kadrų, naudodamas Lucas-Kanade metodą. cv2.goodFeaturesToTrack aptinka objekto taškus ankstesniame kadre ankstesnis_pilka. Tada cv2.calcOpticalFlowPyrLK seka šiuos taškus dabartiniame kadre curr_grey.

Tik taškai, kurių būsena yra 1 (rodo sėkmingą sekimą), padeda įvertinti afininės transformacijos matricą. Kodas atnaujina ankstesnis_pilka kintamasis su dabartiniu pilkos spalvos rėmeliu kitai iteracijai.

Trajektorijos išlyginimas

Norint pasiekti stabilų rezultatą, reikia išlyginti transformacijų trajektoriją.

# Apskaičiuokite trajektoriją sumuodami transformacijas
trajektorija = np.cumsum (transformuoja, ašis=0)

# Išlyginkite trajektoriją naudodami slankųjį vidurkį
išlyginta_trajektorija = sklandi_trajektorija (trajektorija)

# Apskaičiuokite skirtumą tarp išlygintos ir pradinės trajektorijos
skirtumas = išlyginta_trajektorija – trajektorija

# Pridėkite skirtumą atgal prie pradinių transformacijų, kad gautumėte sklandų
# transformacijos
transforms_smooth = transformuoja + skirtumas

Aukščiau pateiktas kodas apskaičiuoja kameros judėjimo trajektoriją ir ją išlygina.

Stabilizuojantys ir rašymo rėmeliai

Paskutinis žingsnis yra stabilizuoti kadrus ir įrašyti stabilizuotą vaizdo įrašą į išvesties failą.

Pradėkite iš naujo nustatydami vaizdo įrašą. Tai užtikrina, kad būsimos operacijos bus skaitomos nuo vaizdo įrašo pradžios.

cap.set (cv2.CAP_PROP_POS_FRAMES, 0)

Tada stabilizuokite vaizdo įrašą apdorodami kiekvieną kadrą.

# Apdorokite kiekvieną kadrą ir stabilizuokite vaizdo įrašą
dėl i in diapazonas (kadrų_skaičius – 2):
sėkmė, rėmelis = cap.read()

jeigune sėkmė:
pertrauka

vertimas_x = transformuoja_smooth[i, 0]
vertimas_y = transforms_smooth[i, 1]
rotation_angle = transformuoja_smooth[i, 2]

# Sukurkite transformacijos matricą stabilizavimui
transformacijos_matrica = np.zeros((2, 3), np.float32)
transformacijos_matrica[0, 0] = np.cos (sukimo kampas)
transformacijos_matrica[0, 1] = -np.sin (sukimo kampas)
transformacijos_matrica[1, 0] = np.sin (sukimosi kampas)
transformacijos_matrica[1, 1] = np.cos (sukimo kampas)
transformacijos_matrica[0, 2] = vertimas_x
transformacijos_matrica[1, 2] = vertimo_y

# Taikykite transformaciją, kad stabilizuotumėte rėmą
frame_stabilized = cv2.warpAffine(
rėmas,
transformacijos_matrica,
(plotis Aukštis)
)

# Užfiksuokite stabilizuoto rėmo kraštą
rėmas_stabilizuotas = fix_border (rėmas_stabilizuotas)

# Sujunkite originalius ir stabilizuotus rėmus vienas šalia kito
frame_out = cv2.hconcat([rėmas, kadras_stabilizuotas])

# Pakeiskite rėmelio dydį, jei jo plotis viršija 1920 pikselių
jeigu frame_out.shape[1] > 1920:
frame_out = cv2.resize(
frame_out,
(frame_out.shape[1] // 2, frame_out.shape[0] // 2)
)

# Rodyti kadrus prieš ir po
cv2.imshow("Prieš ir po", frame_out)
cv2.waitKey(10)

# Įrašykite kadrą į išvesties vaizdo failą
out.write (frame_out)

Aukščiau pateiktas kodas stabilizuoja kiekvieną kadrą naudodamas apskaičiuotas transformacijas, įskaitant vertimo ir pasukimo koregavimus. Tada jis sujungia stabilizuotus rėmus su originaliais, kad būtų galima palyginti.

Vaizdo įrašymo ir rašytojo išleidimas

Užbaikite programą atleisdami vaizdo įrašymo ir rašymo objektus.

# Atleiskite vaizdo įrašymo ir rašymo programą ir uždarykite visus atidarytus langus
cap.release()
out.release()
cv2.destroyAllWindows()

Šis kodas taip pat uždaro visus atidarytus langus.

Galutinis programos rezultatas

Programos išvestis atrodys maždaug taip:

Ir štai stabilizuoto vaizdo įrašo pavyzdys:

Išvestis rodo drebančio vaizdo ir stabilizuoto vaizdo palyginimą.

Ištirkite OpenCV galimybes

Galite taikyti OpenCV daugelyje sričių, susijusių su kompiuterine vizija. Taip yra todėl, kad jis siūlo platų funkcijų spektrą. Turėtumėte ištirti jo galimybes dirbdami su daugiau projektų, susijusių su kompiuterine vizija. Tai supažindins jus su naujomis sąvokomis ir suteiks naujų tyrimų sričių.