Usa questa tecnica per applicare un po' di matematica intelligente ai tuoi video e ridurre il tremolio.
La stabilizzazione video è una tecnica che riduce i movimenti indesiderati e le vibrazioni nelle riprese video. Le riprese a mano libera, le vibrazioni e il movimento possono causare movimenti instabili della fotocamera. La stabilizzazione video produce un video dall'aspetto più uniforme.
L'obiettivo principale della stabilizzazione video è stimare il movimento della videocamera tra fotogrammi consecutivi. Il processo può quindi applicare le trasformazioni appropriate per allineare i frame. Ciò riduce al minimo il movimento percepito.
Configurazione dell'ambiente
A partire da creazione di un ambiente virtuale per garantire che i pacchetti installati per eseguire il programma non siano in conflitto con quelli esistenti. Quindi esegui questo comando da terminale per installare le librerie richieste:
pip installa opencv-python numpy
Questo comando installa le librerie NumPy e OpenCV. NumPy fornisce strumenti per compiti numerici mentre OpenCV si occupa di attività di visione artificiale.
Il codice sorgente completo è disponibile in a Deposito GitHub.
Importazione delle librerie richieste e definizione di tre funzioni cruciali
Crea un nuovo file Python e assegnagli un nome di tuo gradimento. Importa le librerie NumPy e OpenCV all'inizio dello script.
importare intorpidito COME np
importare cv2
L'importazione di queste librerie ti consentirà di utilizzare le loro funzioni nel tuo codice.
Successivamente, definisci tre funzioni che saranno cruciali per il processo di stabilizzazione.
La funzionecalculate_moving_average
Crea una funzione e assegnale un nome calcola_media_mobile. Questa funzione calcolerà la media mobile di una data curva utilizzando il raggio specificato. Impiega un'operazione di convoluzione con una dimensione della finestra specificata e un kernel uniforme. Questa media mobile aiuta ad appianare le fluttuazioni della traiettoria.
defcalcola_media_mobile(curva, raggio):
# Calcola la media mobile di una curva usando un dato raggio
dimensione_finestra = 2 * raggio + 1
kernel = np.ones (dimensione_finestra) / dimensione_finestra
curve_padded = np.lib.pad (curva, (raggio, raggio), 'bordo')
smoothed_curve = np.convolve (curve_padded, kernel, mode='Stesso')
curva_smussata = curva_smussata[raggio:-raggio]
ritorno curva_smussata
La funzione restituisce una curva uniforme. Aiuta a ridurre il rumore e le fluttuazioni nella curva. Lo fa calcolando la media dei valori all'interno della finestra scorrevole.
La funzione smooth_trajectory
Crea un'altra funzione e chiamala smooth_trajectory. Questa funzione applicherà la media mobile su ogni dimensione della traiettoria. Otterrà ciò creando una copia smussata della traiettoria originale. Ciò migliorerà ulteriormente la stabilità del video.
defsmooth_trajectory(traiettoria):
# Smussa la traiettoria usando la media mobile su ogni dimensione
smoothed_trajectory = np.copy (traiettoria)per io In allineare(3):
traiettoria_smussata[:, i] = calcola_media_movimento(
traiettoria[:, i],
raggio=SMOOTHING_RADIUS
)
ritorno traiettoria_smussata
IL smooth_trajectory La funzione restituisce una traiettoria smussata.
La funzione fix_border
Creare una funzione finale e nominarla fix_border. Questa funzione fisserà il bordo della cornice applicando una trasformazione di rotazione e ridimensionamento. Prende il frame di input, ne calcola la forma, costruisce una matrice di trasformazione e applica la trasformazione al frame. Infine, restituisce il frame fisso.
deffix_border(telaio):
# Correggi il bordo della cornice applicando la rotazione e la trasformazione in scala
frame_shape = frame.shape
matrice = cv2.getRotazioneMatrice2D(
(forma_telaio[1] / 2, forma_cornice[0] / 2),
0,
1.04
)
frame = cv2.warpAffine (frame, matrix, (frame_shape[1], frame_shape[0]))
ritorno telaio
IL fix_border La funzione garantisce che i fotogrammi stabilizzati non presentino artefatti sui bordi causati dal processo di stabilizzazione.
Inizializzazione della stabilizzazione video e presa dell'input
Inizia impostando il raggio che verrà utilizzato dalla funzione di arrotondamento della traiettoria.
SMOOTHING_RADIUS = 50
Quindi, passa nel percorso video del video traballante che desideri stabilizzare.
# Apri il file video di input
# Sostituisci il percorso con 0 per usare la tua webcam
cap = cv2.VideoCapture('inputvid.mp4')
Ottieni le proprietà del video traballante:
num_frame = int (cap.get (cv2.CAP_PROP_FRAME_COUNT))
larghezza = int (cap.get (cv2.CAP_PROP_FRAME_WIDTH))
altezza = int (cap.get (cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get (cv2.CAP_PROP_FPS)
Imposta il formato di output. Questo è il formato con cui il programma salverà il video stabilizzato. Puoi usare qualsiasi formato video comune ti piace.
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
Infine, inizializza il video writer:
out = cv2.VideoWriter('uscita_video.mp4', quattro cc, fps, (2 * larghezza altezza))
L'estensione del nome del file che passi al video writer dovrebbe essere la stessa che hai impostato nel formato di output.
Frame di lettura ed elaborazione
Il primo passaggio dell'elaborazione del video traballante inizia qui. Implica la lettura di fotogrammi dal video di input, il calcolo delle trasformazioni e il popolamento dell'array di trasformazioni.
Inizia leggendo il primo fotogramma.
_, prev_frame = cap.read()
prev_gray = cv2.cvtColor (prev_frame, cv2.COLOR_BGR2GRAY)
Quindi inizializzare l'array di trasformazione. Memorizzerà le informazioni per ogni fotogramma.
trasformazioni = np.zeros((num_frame - 1, 3), np.float32)
Infine, è necessario calcolare il flusso ottico tra fotogrammi consecutivi. Quindi, stimare la trasformazione affine tra i punti.
per io In intervallo (num_frame - 2):
# Calcola il flusso ottico tra fotogrammi consecutivi
prev_points = cv2.goodFeaturesToTrack(
prev_gray,
maxAngoli=200,
livello di qualità=0.01,
minDistanza=30,
dimensione blocco=3
)successo, curr_frame = cap.read()
Senon successo:
rotturacurr_gray = cv2.cvtColor (curr_frame, cv2.COLOR_BGR2GRAY)
curr_points, status, err = cv2.calcOpticalFlowPyrLK(
prev_gray,
curr_gray,
prev_points,
Nessuno
)affermare prev_points.shape == curr_points.shape
idx = np.where (stato == 1)[0]
punti_precedenti = punti_precedenti[idx]
punti_curr = punti_curr[idx]
# Stima la trasformazione affine tra i punti
matrice, _ = cv2.stimaAffine2D(prev_points, curr_points)
traduzione_x = matrice[0, 2]
traduzione_y = matrice[1, 2]
angolo_rotazione = np.arctan2(matrice[1, 0], matrice[0, 0])
trasforma[i] = [traduzione_x, traslazione_y, rotazione_angolo]
prev_gray = curr_gray
Il ciclo itera su ogni fotogramma (tranne l'ultimo fotogramma) per calcolare le trasformazioni. Calcola il flusso ottico tra fotogrammi consecutivi utilizzando il metodo Lucas-Kanade. cv2.goodFeaturesToTrack rileva i punti caratteristici nel fotogramma precedente prev_gray. Poi, cv2.calcOpticalFlowPyrLK tiene traccia di questi punti nel fotogramma corrente curr_gray.
Solo i punti con uno stato di 1 (che indica il tracciamento riuscito) aiutano a stimare una matrice di trasformazione affine. Il codice aggiorna il file prev_gray variabile con la cornice in scala di grigi corrente per l'iterazione successiva.
Levigare la traiettoria
È necessario smussare la traiettoria ottenuta dalle trasformazioni per ottenere un risultato stabile.
# Calcola la traiettoria sommando cumulativamente le trasformazioni
traiettoria = np.cumsum (trasforma, asse=0)# Leviga la traiettoria usando la media mobile
traiettoria_smussata = traiettoria_smussata (traiettoria)# Calcola la differenza tra la traiettoria smussata e quella originale
differenza = smoothed_trajectory - traiettoria
# Aggiungi la differenza alle trasformazioni originali per ottenere un risultato uniforme
# trasformazioni
transforms_smooth = trasforma + differenza
Il codice precedente calcola la traiettoria del movimento della telecamera e la uniforma.
Cornici di stabilizzazione e scrittura
Il passaggio finale è stabilizzare i fotogrammi e scrivere il video stabilizzato in un file di output.
Inizia reimpostando l'acquisizione video. Ciò garantisce che le operazioni future verranno lette dall'inizio del video.
cap.set (cv2.CAP_PROP_POS_FRAMES, 0)
Quindi stabilizzare il video elaborando ogni fotogramma.
# Elabora ogni fotogramma e stabilizza il video
per io In intervallo (num_frame - 2):
successo, frame = cap.read()Senon successo:
rotturatranslation_x = transforms_smooth[i, 0]
traduzione_y = transforms_smooth[i, 1]
angolo_rotazione = trasforma_liscio[i, 2]# Crea la matrice di trasformazione per la stabilizzazione
trasformazione_matrice = np.zeros((2, 3), np.float32)
trasformazione_matrice[0, 0] = np.cos (angolo_rotazione)
trasformazione_matrice[0, 1] = -np.sin (angolo_rotazione)
trasformazione_matrice[1, 0] = np.sin (angolo_rotazione)
trasformazione_matrice[1, 1] = np.cos (angolo_rotazione)
trasformazione_matrice[0, 2] = traduzione_x
trasformazione_matrice[1, 2] = traduzione_y# Applicare la trasformazione per stabilizzare la cornice
frame_stabilized = cv2.warpAffine(
telaio,
trasformazione_matrice,
(larghezza altezza)
)# Fissa il bordo del telaio stabilizzato
frame_stabilized = fix_border (frame_stabilized)# Concatena i fotogrammi originali e stabilizzati fianco a fianco
frame_out = cv2.hconcat([frame, frame_stabilized])# Ridimensiona la cornice se la sua larghezza supera i 1920 pixel
Se frame_out.shape[1] > 1920:
frame_out = cv2.resize(
frame_out,
(frame_out.shape[1] // 2, frame_out.shape[0] // 2)
)# Visualizza i fotogrammi prima e dopo
cv2.imshow("Prima e dopo", frame_out)
cv2.waitKey(10)
# Scrive il fotogramma nel file video di output
out.write (frame_out)
Il codice precedente stabilizza ogni fotogramma utilizzando le trasformazioni calcolate, incluse le regolazioni di traslazione e rotazione. Quindi combina i telai stabilizzati con quelli originali per fornire un confronto.
Rilascio di Video Capture e Writer
Finalizza il programma rilasciando l'acquisizione video e gli oggetti di scrittura.
# Rilascia l'acquisizione e la scrittura del video e chiudi tutte le finestre aperte
cap.rilascio()
fuori.rilascio()
cv2.destroyAllWindows()
Questo codice chiude anche tutte le finestre aperte.
Output finale del programma
L'output del programma sarà simile a questo:
Ed ecco un esempio del video stabilizzato:
L'output mostra il confronto tra il video traballante e quello stabilizzato.
Esplora le funzionalità di OpenCV
Puoi applicare OpenCV in molti campi che coinvolgono la visione artificiale. Questo perché offre una vasta gamma di funzionalità. Dovresti esplorare le sue capacità lavorando su più progetti che coinvolgono la visione artificiale. Questo ti introdurrà a nuovi concetti e ti darà nuove aree di ricerca.