2011-10-14 7 views
7

Desidero implementare un metodo di calcolo del background. Ho 50 fotogrammi di immagini scattate in un secondo e alcuni dei fotogrammi contengono un fulmine che voglio estrarre come primo piano. I fotogrammi sono presi con una fotocamera fissa ei fotogrammi sono presi come scale di grigio. Quello che voglio fare è:Sottrazione dello sfondo in OpenCV (C++)

  1. ottenere il modello di sfondo
  2. Dopo, confrontare ogni fotogramma al modello sfondo per determinare se v'è l'illuminazione in quel lasso oppure no.

Ho letto alcuni documenti su come questo può possibile essere fatto utilizzando cvAcc(), ma sto avendo una difficoltà a capire come questo può essere fatto. Gradirei un pezzo di codice che mi guida e collega a documenti che possono aiutarmi a capire come posso implementarlo.

Grazie in anticipo.

risposta

18

Abbiamo avuto lo stesso compito in uno dei nostri progetti.

Per ottenere il modello di sfondo, creiamo semplicemente una classe BackgroundModel, acquisiamo il primo (diciamo) 50 fotogrammi e calcoliamo il fotogramma medio per evitare errori di pixel nel modello di sfondo.

Ad esempio, se si ottiene un'immagine in scala di grigi a 8 bit (CV_8UC1) dalla fotocamera, si inizializza il modello con CV_16UC1 per evitare il ritaglio.

cv::Mat model = cv::Mat(HEIGHT, WIDTH, CV_16UC1, cv::Scalar(0)); 

Ora, in attesa dei primi telai per calcolare il vostro modello, basta aggiungere ogni fotogramma al modello e contare il numero di frame ricevuti.

void addFrame(cv::Mat frame) { 
    cv::Mat convertedFrame; 
    frame.convertTo(convertedFrame, CV_16UC1); 
    cv::add(convertedFrame, model, model); 
    if (++learnedFrames >= FRAMES_TO_LEAN) { // FRAMES_TO_LEARN = 50 
     createMask(); 
    } 
} 

La funzione createMask() calcola il frame medio che usiamo per il modello.

void createMask() { 
    cv::convertScaleAbs(model, mask, 1.0/learnedFrames); 
    mask.convertTo(mask, CV_8UC1); 
} 

Ora, è sufficiente inviare tutti i fotogrammi il percorso attraverso la classe BackgroundModel a una funzione di sottrazione(). Se il risultato è un cv :: Mat vuoto, la maschera viene comunque calcolata. Altrimenti, ottieni una cornice sottratta.

cv::Mat subtract(cv::Mat frame) { 
    cv::Mat result; 
    if (++learnedFrames >= FRAMES_TO_LEAN) { // FRAMES_TO_LEARN = 50 
     cv::subtract(frame, mask, result); 
    } 
    else { 
     addFrame(frame); 
    } 
    return result; 
} 

Ultimo ma non meno importante, è possibile utilizzare somma scalare (const Mat & MTX) per calcolare la somma dei pixel e decidere se si tratta di una cornice con le luci su di esso.

+0

Grazie mille ping (",) – user854576

+3

@ user854576 Se questa è una risposta corretta, si dovrebbe essere gentili e accettarlo. Vedere [questa pagina] (http://stackoverflow.com/faq#howtoask) nel FAQ come accettare le risposte. –