Utilizați această tehnică pentru a aplica niște calcule inteligente la videoclipurile dvs. și pentru a reduce tremuratul.
Stabilizarea video este o tehnică care reduce mișcarea nedorită și tremurul în filmările video. Fotografierea în mână, vibrațiile și mișcarea pot provoca mișcări instabile ale camerei. Stabilizarea video produce un videoclip cu aspect mai neted.
Scopul principal al stabilizării video este de a estima mișcarea camerei între cadre consecutive. Procesul poate aplica apoi transformări adecvate pentru a alinia cadrele. Acest lucru minimizează mișcarea percepută.
Configurarea mediului
Începe prin crearea unui mediu virtual pentru a vă asigura că pachetele pe care le instalați pentru a rula programul nu intră în conflict cu cele existente. Apoi rulați această comandă de terminal pentru a instala bibliotecile necesare:
pip install opencv-python numpy
Această comandă instalează bibliotecile NumPy și OpenCV. NumPy oferă instrumente pentru sarcini numerice în timp ce OpenCV se ocupă de sarcini de viziune computerizată.
Codul sursă complet este disponibil în a Depozitul GitHub.
Importarea bibliotecilor necesare și definirea a trei funcții cruciale
Creați un fișier Python nou și dați-i un nume pe placul dvs. Importați bibliotecile NumPy și OpenCV la începutul scriptului.
import numpy la fel de np
import cv2
Importarea acestor biblioteci vă va permite să utilizați funcțiile lor în codul dvs.
În continuare, definiți trei funcții care vor fi cruciale pentru procesul de stabilizare.
Funcția calculate_moving_average
Creați o funcție și denumiți-o calculate_moving_average. Această funcție va calcula media mobilă a unei curbe date folosind raza pe care o specificați. Utilizează o operație de convoluție cu o dimensiune specificată a ferestrei și un nucleu uniform. Această medie mobilă ajută la atenuarea fluctuațiilor din traiectorie.
defcalculate_moving_average(curba, raza):
# Calculați media mobilă a unei curbe folosind o rază dată
window_size = 2 * raza + 1
kernel = np.ones (dimensiunea_ferestrei) / dimensiunea_ferestrei
curve_padded = np.lib.pad (curbă, (rază, rază), 'margine')
smoothed_curve = np.convolve (curba_căptușită, nucleu, mod='la fel')
curba_netezita = curba_netezita[raza:-raza]
întoarcere curbă_netezită
Funcția returnează o curbă netedă. Ajută la reducerea zgomotului și a fluctuațiilor în curbă. Face acest lucru făcând o medie a valorilor din fereastra glisantă.
Funcția smooth_trajectory
Creați o altă funcție și denumiți-o netedă_traiectorie. Această funcție va aplica media mobilă pe fiecare dimensiune a traiectoriei. Acesta va realiza acest lucru prin crearea unei copii netezite a traiectoriei originale. Acest lucru va îmbunătăți și mai mult stabilitatea videoclipului.
defnetedă_traiectorie(traiectorie):
# Neteziți traiectoria folosind media mobilă pe fiecare dimensiune
smoothed_trajectory = np.copy (traiectorie)pentru i în gamă(3):
traiectorie_netezită[:, i] = calculate_moving_average(
traiectorie[:,i],
radius=RAZA_SMOOTHING
)
întoarcere traiectorie_netezită
The netedă_traiectorie funcția returnează o traiectorie netezită.
Funcția fix_border
Creați o funcție finală și denumiți-o fix_border. Această funcție va fixa marginea cadrului prin aplicarea unei transformări de rotație și scalare. Preia cadrul de intrare, calculează forma acestuia, construiește o matrice de transformare și aplică transformarea cadrului. În cele din urmă, returnează cadrul fix.
deffix_border(cadru):
# Fixați chenarul cadrului aplicând transformarea de rotație și scalare
frame_shape = cadru.forma
matrice = cv2.getRotationMatrix2D(
(forma_cadru[1] / 2, forma_cadru[0] / 2),
0,
1.04
)
cadru = cv2.warpAffine (cadru, matrice, (forma_cadru[1], forma_cadru[0]))
întoarcere cadru
The fix_border Funcția asigură că cadrele stabilizate nu au artefacte de margine cauzate de procesul de stabilizare.
Inițializarea stabilizării video și preluarea intrării
Începeți prin a seta raza pe care o va folosi funcția de netezire a traiectoriei.
SMOOTHING_RADIUS = 50
Apoi, treceți în calea video a videoclipului tremurător pe care doriți să-l stabilizați.
# Deschideți fișierul video de intrare
# Înlocuiți calea cu 0 pentru a vă folosi camera web
capac = cv2.VideoCapture(„inputvid.mp4”)
Obțineți proprietățile videoclipului tremurat:
num_frames = int (cap.get (cv2.CAP_PROP_FRAME_COUNT))
lățime = int (cap.get (cv2.CAP_PROP_FRAME_WIDTH))
înălțime = int (cap.get (cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get (cv2.CAP_PROP_FPS)
Setați formatul de ieșire. Acesta este formatul în care programul va salva videoclipul stabilizat. Puteți folosi orice format video comun iti place.
fourcc = cv2.VideoWriter_fourcc(*„mp4v”)
În cele din urmă, inițializați scriitorul video:
out = cv2.VideoWriter(„video_out.mp4”, fourcc, fps, (2 * latime inaltime))
Extensia numelui fișierului pe care îl transmiteți scriitorului video ar trebui să fie aceeași cu cea pe care o setați în formatul de ieșire.
Cadre de citire și procesare
Primul pas al procesării videoclipului tremurător începe aici. Aceasta implică citirea cadrelor din videoclipul de intrare, calcularea transformărilor și popularea matricei de transformări.
Începeți prin a citi primul cadru.
_, prev_frame = cap.read()
prev_gray = cv2.cvtColor (prev_frame, cv2.COLOR_BGR2GRAY)
Apoi inițializați matricea de transformare. Acesta va stoca informații pentru fiecare cadru.
transforms = np.zeros((num_frames - 1, 3), np.float32)
În cele din urmă, trebuie să calculați fluxul optic între cadre consecutive. Apoi, estimați transformarea afină între puncte.
pentru i în interval (num_frames - 2):
# Calculați fluxul optic între cadre consecutive
prev_points = cv2.goodFeaturesToTrack(
prev_gray,
maxColturi=200,
qualityLevel=0.01,
minDistanța=30,
blockSize=3
)succes, curr_frame = cap.read()
dacănu succes:
pauzăcurr_gray = cv2.cvtColor (curr_frame, cv2.COLOR_BGR2GRAY)
curr_points, status, err = cv2.calcOpticalFlowPyrLK(
prev_gray,
curr_gray,
puncte_prev,
Nici unul
)afirma prev_points.shape == curr_points.shape
idx = np.unde (starea == 1)[0]
puncte_prev = puncte_prev[idx]
curr_points = curr_points[idx]
# Estimați transformarea afină între puncte
matrice, _ = cv2.estimateAffine2D(puncte_prev, puncte_curr)
traducere_x = matrice[0, 2]
traducere_y = matrice[1, 2]
unghi_rotatie = np.arctan2(matrice[1, 0], matrice[0, 0])
transforms[i] = [translation_x, translation_y, rotation_angle]
prev_gray = curr_gray
Bucla iterează peste fiecare cadru (cu excepția ultimului cadru) pentru a calcula transformările. Acesta calculează fluxul optic între cadre consecutive folosind metoda Lucas-Kanade. cv2.goodFeaturesToTrack detectează punctele caracteristice din cadrul precedent prev_gray. Apoi, cv2.calcOpticalFlowPyrLK urmărește aceste puncte în cadrul curent curr_gray.
Doar punctele cu statutul 1 (care indică urmărirea reușită) ajută la estimarea unei matrice de transformare afină. Codul actualizează prev_gray variabilă cu cadrul în tonuri de gri curent pentru următoarea iterație.
Netezirea traiectoriei
Trebuie să neteziți traiectoria obținută din transformări pentru a obține un rezultat stabil.
# Calculați traiectoria însumând cumulativ transformările
traiectorie = np.cumsum (transforme, axa=0)# Neteziți traiectoria folosind media mobilă
smoothed_trajectory = traiectorie_netezită (traiectorie)# Calculați diferența dintre traiectoria netezită și cea originală
diferenta = netezit_trajectory - traiectorie
# Adăugați diferența înapoi la transformările originale pentru a obține netede
# transformări
transforms_smooth = transforms + diferență
Codul de mai sus calculează traiectoria mișcării camerei și o netezește.
Stabilizare și cadre de scriere
Pasul final este să stabilizați cadrele și să scrieți videoclipul stabilizat într-un fișier de ieșire.
Începeți prin a reseta captura video. Acest lucru asigură că operațiunile viitoare vor fi citite de la începutul videoclipului.
cap.set (cv2.CAP_PROP_POS_FRAMES, 0)
Apoi stabilizați videoclipul procesând fiecare cadru.
# Procesați fiecare cadru și stabilizați videoclipul
pentru i în interval (num_frames - 2):
succes, frame = cap.read()dacănu succes:
pauzătranslation_x = transforms_smooth[i, 0]
translation_y = transforms_smooth[i, 1]
unghi_rotație = transforms_smooth[i, 2]# Creați matricea de transformare pentru stabilizare
matrice_transformare = np.zeros((2, 3), np.float32)
matrice_transformare[0, 0] = np.cos (unghi_rotație)
matrice_transformare[0, 1] = -np.sin (unghi_rotație)
matrice_transformare[1, 0] = np.sin (unghi_rotație)
matrice_transformare[1, 1] = np.cos (unghi_rotație)
matrice_transformare[0, 2] = traducere_x
matrice_transformare[1, 2] = traducere_y# Aplicați transformarea pentru a stabiliza cadrul
frame_stabilized = cv2.warpAffine(
cadru,
matrice_transformare,
(latime inaltime)
)# Fixați marginea cadrului stabilizat
frame_stabilized = fix_border (frame_stabilized)# Concatenați cadrele originale și cele stabilizate unul lângă altul
frame_out = cv2.hconcat([frame, frame_stabilized])# Redimensionați cadrul dacă lățimea acestuia depășește 1920 de pixeli
dacă formă_cadru[1] > 1920:
frame_out = cv2.resize(
frame_out,
(frame_out.shape[1] // 2, frame_out.shape[0] // 2)
)# Afișați cadrele înainte și după
cv2.imshow("Inainte si dupa", frame_out)
cv2.waitKey(10)
# Scrieți cadrul în fișierul video de ieșire
out.write (frame_out)
Codul de mai sus stabilizează fiecare cadru folosind transformările calculate, inclusiv ajustările de translație și rotație. Apoi combină ramele stabilizate cu cele originale pentru a oferi o comparație.
Lansarea Video Capture and Writer
Finalizați programul eliberând obiectele de captură video și writer.
# Eliberați captura video și writer și închideți toate ferestrele deschise
cap.release()
out.release()
cv2.destroyAllWindows()
Acest cod închide, de asemenea, toate ferestrele deschise.
Rezultatul final al programului
Ieșirea programului va arăta cam așa:
Și iată un exemplu de videoclip stabilizat:
Ieșirea arată comparația dintre videoclipul tremurat și cel stabilizat.
Explorați capabilitățile OpenCV
Puteți aplica OpenCV în multe domenii care implică viziunea computerizată. Acest lucru se datorează faptului că oferă o gamă largă de funcționalități. Ar trebui să-i explorați capacitățile lucrând la mai multe proiecte care implică viziunea computerizată. Acest lucru vă va prezenta concepte noi și vă va oferi noi domenii pe care să cercetați.