2014-05-20 14 views
5

Sto creando un programma per stabilizzare il flusso video. Al momento, il mio programma funziona in base all'algoritmo di correlazione di fase. Sto calcolando un offset tra due immagini: base e corrente. Quindi correggo l'immagine corrente in base alle nuove coordinate. Questo programma funziona, ma il risultato non è soddisfacente. I link correlati che potresti scoprire che il video trattato appare indesiderabile e scuotere l'intero video stanno peggiorando.
Orininal video
Unshaked video
C'è la mia realizzazione corrente:
Calcolo di offset tra le immagini:Miglior algoritmo per la stabilizzazione video

Point2d calculate_offset_phase_optimized(Mat one, Mat& two) { 

    if(two.type() != CV_64F) { 
    cvtColor(two, two, CV_BGR2GRAY); 
    two.convertTo(two, CV_64F); 
    } 

    cvtColor(one, one, CV_BGR2GRAY); 
    one.convertTo(one, CV_64F); 

    return phaseCorrelate(one, two); 

} 

spostamento dell'immagine secondo questa coordinata:

void move_image_roi_alt(Mat& img, Mat& trans, const Point2d& offset) { 

    trans = Mat::zeros(img.size(), img.type()); 
    img(
    Rect(
     _0(static_cast<int>(offset.x)), 
     _0(static_cast<int>(offset.y)), 
     img.cols-abs(static_cast<int>(offset.x)), 
     img.rows-abs(static_cast<int>(offset.y)) 
    ) 
).copyTo(trans(
    Rect(
     _0ia(static_cast<int>(offset.x)), 
     _0ia(static_cast<int>(offset.y)), 
     img.cols-abs(static_cast<int>(offset.x)), 
     img.rows-abs(static_cast<int>(offset.y)) 
    ) 
)); 
} 

int _0(const int x) { 
    return x < 0 ? 0 : x; 
} 

int _0ia(const int x) { 
    return x < 0 ? abs(x) : 0; 
} 

stavo guardando attraverso gli autori del documento stabilizzatore di YouTube e l'algoritmo basato sul rilevamento degli angoli sembrava interessante, ma non sono del tutto chiaro come funziona. Quindi la mia domanda è come risolvere efficacemente questo problema. Una delle condizioni - il programma verrà eseguito su computer più lenti, quindi algoritmi pesanti potrebbero non essere adatti.
Grazie!
P.S. Mi scuso per eventuali errori nel testo - si tratta di una traduzione automatica.

+0

Che tipo di video stai prendendo di mira? Solo immagini artificiali (dove la scena è di fatto un piano) o video reali in cui i pixel possono essere a diversa profondità? E quali movimenti vuoi correggere? I movimenti lisci sono per lo più desiderati, ma i movimenti con un'elevata accelerazione sono solitamente rumori. –

+0

Esiste un esempio di video di destinazione: http://www.youtube.com/watch?v=Ta8w_nzuMkU E il mio risultato del mio attuale stabilizzatore: http://www.youtube.com/watch?v=-0p -uJEacVI La priorità più alta è l'eliminazione degli scuotimenti nel movimento della telecamera planare. La rotazione e la scala sono opzionali. – iRomul

+1

Potrei immaginare che la profondità della scena potrebbe essere un problema reale (i pixel lontani non si muoveranno tanto quanto vicino ai pixel).Non ho idea di come sia fatto di solito, ma ecco come lo farei: stimare la posizione 3D di ogni punto usando due o più immagini. Valuta anche il movimento della camera 3D. Smooth il percorso della telecamera (ad esempio utilizzando un filtro box) e ri-rendering della scena, riempiendo eventuali fori che potrebbero venire. Non sono sicuro che le traduzioni pure saranno sufficienti. –

risposta

2

È possibile utilizzare i descrittori di immagine come SIFT in ciascun frame e calcolare robustmatches tra i frame. Quindi puoi calcolare homography tra i frame e usarli per allinearli. L'utilizzo di funzionalità sparse può portare a un'implementazione più rapida rispetto all'utilizzo di una correlazione densa.

In alternativa, se si conosce il camera parameters è possibile calculate 3D positions dei punti e delle telecamere e riproffare le immagini su un piano di proiezione stabile. Nel risultato, si ottiene anche uno sparse 3D reconstruction della scena (un po 'impreciso, di solito deve essere optimized utilizzabile). Questo è ciò ad es. Autostitch farebbe, ma è piuttosto difficile da implementare, tuttavia.

Si noti che i parametri della telecamera possono anche essere calculated, ma che è ancora più difficile.

+0

Grazie per la tua risposta! Sono nuovo in questa sfera, quindi ho riscontrato alcune incomprensioni su alcune cose. C'è il mio codice: 'detector.detect (base_frame, keypoints_base); detector.detect (current_frame, keypoints_cur); extractor.compute (..., keypoints_base, descriptors_base); extractor.compute (..., keypoints_cur, descriptors_cur); matcher.knnMatch (description_base, description_cur, matches, 2); ' Quindi sto filtrando le corrispondenze migliori e faccio questo: ' homography = findHomography (k_base, k_cur, CV_RANSAC); ' Ma quale passo successivo dovrei fare? warpAffine non accetta questa omografia 3x3, solo 2x3. – iRomul

+0

Usa invece 'warpPerspective' (vedi http://docs.opencv.org/modules/imgproc/doc/geometric_transformations.html#warpperspective). –

+0

Ho provato a implementare questo algoritmo, ma i risultati non sono stati soddisfacenti: [video] (http://www.youtube.com/watch?v=DUZ7wDplDHQ&feature=youtu.be) Ti ricordo che i frame sono confrontati con il frame fisso . In questo caso, è il primo fotogramma video. [Codice completo] (http://pastebin.com/9rNeXf2t) – iRomul

2

OpenCV può fare per voi in 3 linee di codice (è sicuramente via più breve, può essere anche il migliore):

t = estimateRigidTransform(newFrame, referenceFrame, 0); // 0 means not all transformations (5 of 6) 
if(!t.empty()){  
    warpAffine(newFrame, stableFrame, t, Size(newFrame.cols, newFrame.rows)); // stableFrame should be stable now 
} 

È possibile disattivare un qualche tipo di trasformazioni modificando matrice T, è può portare a risultati più stabili. È solo un'idea di base, quindi puoi modificarla nel modo desiderato: cambia riferimentoFrame, set regolare di parametri di trasformazione dalla matrice t ecc.