Kasutage seda tehnikat, et rakendada oma videotele nutikat matemaatikat ja vähendada värisemist.
Video stabiliseerimine on tehnika, mis vähendab videomaterjalis soovimatut liikumist ja värinat. Käsipildistamine, vibratsioon ja liikumine võivad põhjustada kaamera ebakindlat liikumist. Video stabiliseerimine annab sujuvama välimusega video.
Video stabiliseerimise esmane eesmärk on hinnata kaamera liikumist järjestikuste kaadrite vahel. Seejärel saab protsess rakendada sobivaid teisendusi kaadrite joondamiseks. See vähendab tajutavat liikumist.
Oma keskkonna seadistamine
Alusta sellest virtuaalse keskkonna loomine tagamaks, et programmi käivitamiseks installitavad paketid ei oleks vastuolus olemasolevatega. Seejärel käivitage vajalike teekide installimiseks see terminalikäsk:
pip install opencv-python numpy
See käsk installib NumPy ja OpenCV teegid. NumPy pakub tööriistu numbriliste ülesannete jaoks samas kui OpenCV tegeleb arvutinägemise ülesannetega.
Täielik lähtekood on saadaval a GitHubi hoidla.
Nõutavate teekide importimine ja kolme olulise funktsiooni määratlemine
Looge uus Pythoni fail ja andke sellele endale meelepärane nimi. Importige skripti algusesse NumPy ja OpenCV teegid.
importida tuim nagu np
importida cv2
Nende teekide importimine võimaldab teil oma koodis kasutada nende funktsioone.
Järgmisena määratlege kolm funktsiooni, mis on stabiliseerimisprotsessi jaoks otsustava tähtsusega.
Arvuta_liikuva_keskmise funktsioon
Looge funktsioon ja nimetage see arvuta_liikuva_keskmine. See funktsioon arvutab antud kõvera liikuva keskmise, kasutades teie määratud raadiust. See kasutab konvolutsioonioperatsiooni määratud akna suuruse ja ühtlase tuumaga. See liikuv keskmine aitab tasandada trajektoori kõikumisi.
defarvuta_liikuva_keskmine(kõver, raadius):
# Arvutage etteantud raadiuse abil kõvera liikuv keskmine
akna_suurus = 2 * raadius + 1
kernel = np.ones (akna_suurus) / akna_suurus
curve_padded = np.lib.pad (kõver, (raadius, raadius), 'serv')
smoothed_curve = np.convolve (curve_padded, kernel, mode='sama')
silutud_kõver = silutud_kõver[raadius:-raadius]
tagasi silutud_kõver
Funktsioon tagastab sujuva kõvera. See aitab vähendada müra ja kõvera kõikumisi. See teeb seda libiseva akna väärtuste keskmistamisega.
Funktsioon sujuva_trajektoori funktsioon
Looge teine funktsioon ja nimetage see sujuv_trajektoor. See funktsioon rakendab libiseva keskmise trajektoori igale mõõtmele. See saavutatakse algse trajektoori silutud koopia loomisega. See parandab veelgi video stabiilsust.
defsujuv_trajektoor(trajektoor):
# Siluge trajektoori, kasutades iga mõõtme libisevat keskmist
silutud_trajektoor = np.copy (trajektoor)jaoks i sisse vahemik(3):
silutud_trajektoor[:, i] = arvuta_liikuv_keskmine(
trajektoor[:, i],
raadius=SMOOTHING_RADIUS
)
tagasi silutud_trajektoor
The sujuv_trajektoor funktsioon tagastab silutud trajektoori.
Funktsioon fix_border
Looge lõplik funktsioon ja nimetage see fix_border. See funktsioon fikseerib kaadri piiri, rakendades pööramise ja skaleerimise teisendust. See võtab sisendkaadri, arvutab selle kuju, konstrueerib teisendusmaatriksi ja rakendab teisenduse kaadrile. Lõpuks tagastab see fikseeritud raami.
deffix_border(raam):
# Kinnitage raami piir, rakendades pööramise ja skaleerimise teisendust
raami_kuju = raam.kuju
maatriks = cv2.getRotationMatrix2D(
(raami_kuju[1] / 2, raami_kuju[0] / 2),
0,
1.04
)
frame = cv2.warpAffine (raam, maatriks, (frame_shape[1], raami_kuju[0]))
tagasi raami
The fix_border funktsioon tagab, et stabiliseeritud raamidel ei oleks stabiliseerimisprotsessist põhjustatud ääriseid.
Video stabiliseerimise käivitamine ja sisendi võtmine
Alustuseks määrake raadius, mida trajektoori silumise funktsioon kasutab.
SMOOTHING_RADIUS = 50
Seejärel sisestage stabiliseeritava väriseva video videotee.
# Avage sisendvideofail
# Veebikaamera kasutamiseks asendage tee 0-ga
cap = cv2.VideoCapture('inputvid.mp4')
Vaadake väriseva video omadused:
num_frames = int (cap.get (cv2.CAP_PROP_FRAME_COUNT))
laius = int (cap.get (cv2.CAP_PROP_FRAME_WIDTH))
kõrgus = int (cap.get (cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get (cv2.CAP_PROP_FPS)
Määrake väljundvorming. See on vorming, milles programm salvestab stabiliseeritud video. Võite kasutada mis tahes tavaline videovorming sulle meeldib.
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
Lõpuks lähtestage video kirjutaja:
out = cv2.VideoWriter("video_out.mp4", neli cc, kaadrit sekundis, (2 * laius kõrgus))
Videokirjutajale edastatava failinime laiend peaks olema sama, mis väljundvormingus määrasite.
Raamide lugemine ja töötlemine
Väriseva video töötlemise esimene samm algab siit. See hõlmab kaadrite lugemist sisendvideost, teisenduste arvutamist ja teisendusmassiivi täitmist.
Alustage esimese kaadri lugemisest.
_, prev_frame = cap.read()
prev_gray = cv2.cvtColor (prev_frame, cv2.COLOR_BGR2GRAY)
Seejärel lähtestage teisendusmassiivi. See salvestab teabe iga kaadri kohta.
teisendab = np.zeros((kaadrite_arv - 1, 3), np.float32)
Lõpuks peate arvutama optilise voolu järjestikuste kaadrite vahel. Seejärel hinnake punktide vahelist afiinset teisendust.
jaoks i sisse vahemik (kaadrite_arv - 2):
# Arvutage optiline voog järjestikuste kaadrite vahel
prev_points = cv2.goodFeaturesToTrack(
prev_grey,
maxCorners=200,
kvaliteeditase=0.01,
minDistance=30,
blockSize=3
)edu, curr_frame = cap.read()
kuimitte edu:
murdacurr_gray = cv2.cvtColor (curr_frame, cv2.COLOR_BGR2GRAY)
curr_points, status, err = cv2.calcOpticalFlowPyrLK(
prev_grey,
curr_gray,
prev_points,
Mitte ühtegi
)väita prev_points.shape == curr_points.shape
idx = np.where (olek == 1)[0]
eel_punktid = eel_punktid[idx]
curr_points = curr_points[idx]
# Hinnake punktide vahelist afiinset teisendust
maatriks, _ = cv2.estimateAffine2D(eelmised_punktid, praegused_punktid)
tõlge_x = maatriks[0, 2]
tõlge_y = maatriks[1, 2]
pöörlemisnurk = np.arctan2(maatriks[1, 0], maatriks[0, 0])
transforms[i] = [tõlge_x, tõlke_y, pöörlemisnurk]
eelmine_hall = curr_grey
Silmus kordab iga kaadri (v.a viimane kaader), et arvutada teisendusi. See arvutab optilise voolu järjestikuste kaadrite vahel, kasutades Lucas-Kanade meetodit. cv2.goodFeaturesToTrack tuvastab funktsioonipunktid eelmises kaadris eelmine_hall. Siis cv2.calcOpticalFlowPyrLK jälgib neid punkte praeguses kaadris curr_grey.
Ainult punktid, mille olek on 1 (näitab edukat jälgimist), aitavad hinnata afiinset teisendusmaatriksit. Kood värskendab eelmine_hall muutuja praeguse halltoonide raamiga järgmise iteratsiooni jaoks.
Trajektoori silumine
Stabiilse tulemuse saavutamiseks peate teisendustest saadud trajektoori siluma.
# Arvutage trajektoor, liites teisendused kumulatiivselt
trajektoor = np.cumsum (teisendus, telg=0)# Siluge trajektoori libiseva keskmise abil
silutud_trajektoor = sujuv_trajektoor (trajektoor)# Arvutage tasandatud ja algse trajektoori vahe
erinevus = silutud_trajektoor – trajektoor
# Sujuvuse saavutamiseks lisage erinevus tagasi algsetele teisendustele
# teisendusi
transforms_smooth = teiseneb + erinevus
Ülaltoodud kood arvutab välja kaamera liikumise trajektoori ja silub seda.
Stabiliseerivad ja kirjutamisraamid
Viimane samm on kaadrite stabiliseerimine ja stabiliseeritud video kirjutamine väljundfaili.
Alustage video jäädvustamise lähtestamisega. See tagab, et tulevasi toiminguid loetakse video algusest peale.
cap.set (cv2.CAP_PROP_POS_FRAMES, 0)
Seejärel stabiliseerige video iga kaadri töötlemisega.
# Töötle iga kaadrit ja stabiliseeri video
jaoks i sisse vahemik (kaadrite_arv - 2):
edu, raam = cap.read()kuimitte edu:
murdatõlge_x = teisendab_smooth[i, 0]
tõlge_y = teisendab_smooth[i, 1]
rotation_angle = teisendab_smooth[i, 2]# Loo stabiliseerimiseks teisendusmaatriks
teisenduse_maatriks = np.zeros((2, 3), np.float32)
teisendusmaatriks[0, 0] = np.cos (pööramisnurk)
teisendusmaatriks[0, 1] = -np.sin (pöörlemisnurk)
teisendusmaatriks[1, 0] = np.sin (pöörlemisnurk)
teisendusmaatriks[1, 1] = np.cos (pööramisnurk)
teisendusmaatriks[0, 2] = tõlge_x
teisendusmaatriks[1, 2] = tõlke_y# Rakendage raami stabiliseerimiseks teisendust
frame_stabilized = cv2.warpAffine(
raam,
transformation_matrix,
(laius kõrgus)
)# Kinnitage stabiliseeritud raami ääris
kaader_stabiliseeritud = fix_border (raam_stabiliseeritud)# Ühendage originaal- ja stabiliseeritud raamid kõrvuti
frame_out = cv2.hconcat([kaader, kaader_stabiliseeritud])# Muutke raami suurust, kui selle laius ületab 1920 pikslit
kui frame_out.shape[1] > 1920:
frame_out = cv2.resize(
frame_out,
(frame_out.shape[1] // 2, frame_out.shape[0] // 2)
)# Kuva enne ja pärast kaadreid
cv2.imshow("Enne ja pärast", kaadri_väljas)
cv2.waitKey(10)
# Kirjutage kaader väljundvideofaili
out.write (frame_out)
Ülaltoodud kood stabiliseerib iga kaadri, kasutades arvutatud teisendusi, sealhulgas translatsiooni ja pööramise kohandusi. Seejärel ühendab see võrdluse pakkumiseks stabiliseeritud raamid originaalidega.
Videohõive ja kirjutaja vabastamine
Lõpetage programm, vabastades videohõive- ja kirjutamisobjektid.
# Vabastage videohõive ja kirjutaja ning sulgege kõik avatud aknad
cap.release()
out.release()
cv2.destroyAllWindows()
See kood sulgeb ka kõik avatud aknad.
Programmi lõppväljund
Programmi väljund näeb välja umbes selline:
Ja siin on näide stabiliseeritud videost:
Väljund näitab raputava ja stabiliseeritud video võrdlust.
Uurige OpenCV võimalusi
OpenCV-d saate rakendada paljudes arvutinägemisega seotud valdkondades. Seda seetõttu, et see pakub laia valikut funktsioone. Peaksite uurima selle võimalusi, töötades rohkemate arvutinägemisega seotud projektidega. See tutvustab teile uusi kontseptsioone ja annab teile uusi uurimisvaldkondi.