2015-05-03 53 views
5

我有一個圖像序列,我想要計算中值圖像(去除移動元素)。直觀地說,對一個循環進行硬編碼以遍歷所有像素將具有總體運行時間以及相當大的內存使用量。有沒有辦法在OpenCV中輕鬆做到這一點? (我對平均不感興趣,我需要做一箇中位數)。我正在爲Android編寫(使用OpenCV4Android),所以顯然計算能力是有限的。使用OpenCV從圖像序列中獲取中值圖片

+0

谷歌爲高效中位數 – Micka

+0

這是一個有趣的問題,但對於你提到的硬件類型(沒有指出通常Java比C++慢),這聽起來太具有挑戰性。你想要在中位數中包含多少圖片?圖像的分辨率是多少?順便說一下,您是否已經檢查過在每個單幀中計算中值濾波器是否已經不能提供足夠好的數據? – Antonio

+0

沒有反饋?我有一些想法,但你應該提供更多的信息(見上面我的問題) – Antonio

回答

0

如果平均是確定的:

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); 

編輯:

這種快速僞位數應使絕招:

// 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); 
} 

但是經典的人應該也不錯快速。它是O(nb^2 * w * h)其中nb是圖像的數量和w,h是它們的寬度,高度。以上是O(nb * w * h),對墊子有更多的操作。

的經典一(幾乎所有的計算將在本地進行)代碼:

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說:「我對平均不感興趣」。 – Antonio

+0

沒有看到它:/但計算中位數的代碼將會更加複雜,因爲中位數和平均值結果是封閉的我建議考慮平均值... –

+1

好吧,用兩個中值算法更新。 –

2

據我所知,有創建從圖像序列中位圖像沒有OpenCV的功能。幾年前我需要幾個相同的功能,我必須自己實現這一點。它相對較慢,因爲對於每個像素,您需要從多個圖像中提取相關像素(低效的內存訪問)並計算中位數(也是一個耗時的過程)。

可能的方式來提高效率:

  • 有沒有必要計算從所有圖像中位數。一小部分圖像就足夠了。
  • 你可以找到更有效的算法來找到一些小組的中位數。例如,我使用的算法可以有效地找到九組數值中的中位數。