2015-05-03 4 views
5

Ho una sequenza di immagini per cui voglio calcolare l'immagine mediana (come rimuovere elementi in movimento). Intuitivamente, l'hard-coding di un loop per passare attraverso tutti i pixel avrebbe un tempo di esecuzione lordo e un utilizzo della memoria abbastanza grande. C'è un modo per farlo facilmente in OpenCV? (Non sono interessato a fare la media, ho bisogno di fare una mediana). Sto scrivendo questo per Android (usando OpenCV4Android), quindi ovviamente la potenza di calcolo è limitata.Ottenere un'immagine mediana dalla sequenza di immagini con OpenCV

+0

google per mediana efficiente – Micka

+0

Questo è un problema interessante, ma sembra troppo impegnativo per il tipo di hardware che si menziona (senza contare che in generale Java è più lento di C++). Quante immagini vuoi coinvolgere nella mediana? Qual è la risoluzione delle immagini? A proposito, hai già verificato se il calcolo di un filtro mediano all'interno di ogni singolo fotogramma non fornisse già dati sufficienti? – Antonio

+0

Nessun feedback? Ho alcune idee ma dovresti fornire maggiori informazioni (vedi le mie domande sopra) – Antonio

risposta

0

Se la media è ok:

Mat result(CV_64FC3, listImages[0].size()); 
for(int i = 0; i < listImages.size(); i++) { 
    result += listImages[i]; 
} 
result /= listImages.size(); 
result.convertTo(result, CV_8UC3); 

EDIT:

Questo rapido pseudo-mediana dovrebbe fare il trucco:

// Following algorithm will retain the pixel which is the closest to the mean 
// Computing Mean 
Mat tmpResult = Mat.zeros(listImages[0].size(), CV_64FC3); 
for(int i = 0; i < listImages.size(); i++) { 
    tmpResult += listImages[i]; 
} 
tmpResult /= listImages.size(); 
tmpResult.convertTo(tmpResult, CV_8UC3); 
// We will now, for each pixel retain the closest to the mean 
// Initializing result with the first image 
Mat result(listImages[0].clone()); 
Mat diff1, diff2, minDiff; 
for(int i = 1; i < listImages.size(); i++) { 
    // Computing diff between mean/newImage and mean/lastResult 
    absdiff(tmpResult, listImages[i], diff1); 
    absdiff(tmpResult, result, diff2); 
    // If a pixel of the new image is closer to the mean, it replaces the old one 
    min(diff1, diff2, minDiff); 
    // Get the old pixels that are still ok 
    result = result & ~(minDiff - diff2); 
    // Get the new pixels 
    result += listImages[i] & (minDiff - diff2); 
} 

Tuttavia quella classica dovrebbe essere anche abbastanza veloce. È O (nb^2 * w * h) dove nb è il numero di immagini e w, h la loro larghezza, altezza. Quanto sopra è O (nb * w * h) con più operazioni su Mats.

Il codice per quello classico (quasi tutti i calcoli saranno effettuati in nativo):

Mat tmp; 
// We will sorting pixels where the first mat will get the lowest pixels and the last one, the highest 
for(int i = 0; i < listImages.size(); i++) { 
    for(int j = i + 1; j < listImages.size(); j++) { 
     listImages[i].copyTo(tmp); 
     min(listImages[i], listImages[j], listImages[i]); 
     max(listImages[j], tmp, listImages[j]); 
    } 
} 
// We get the median 
Mat result = listImages[listImages.size()/2]; 
+1

OP dice "Non sono interessato a fare la media". – Antonio

+0

Non l'ho visto:/Ma il codice per calcolare la mediana sarà molto più complesso e dato che i risultati medi e medi sono chiusi ho suggerito di considerare il mezzo ... –

+1

Ok, aggiornato con due algos mediani. –

2

Per quanto ne so, non vi alcuna funzione OpenCV che crea un'immagine mediano dalla sequenza di immagini. Avevo bisogno della stessa funzionalità un paio di anni fa e ho dovuto implementarlo da solo. È relativamente lento perché per ogni pixel è necessario estrarre i pixel pertinenti da più immagini (accesso inefficiente alla memoria) e calcolare la mediana (anche un processo che richiede tempo).

possibili modi per aumentare l'efficienza sono:

  • Non c'è bisogno di calcolare mediana da tutte le immagini. Un piccolo sottoinsieme di immagini sarà sufficiente.
  • È possibile trovare algoritmi più efficienti per trovare la mediana di alcuni piccoli gruppi. Ad esempio, ho usato un algoritmo che può trovare in modo efficiente la mediana in un gruppo di nove valori.