我有一系列图片,想要计算中位数图像(以去除移动元素)。直觉上,硬编码循环遍历所有像素会有很大的运行时间和相当大的内存使用。在OpenCV中是否有一种简单的方法来实现这一点?(我不感兴趣的是平均值,我需要进行中位数计算)。我正在为Android编写此代码(使用OpenCV4Android),因此计算能力有限。
我有一系列图片,想要计算中位数图像(以去除移动元素)。直觉上,硬编码循环遍历所有像素会有很大的运行时间和相当大的内存使用。在OpenCV中是否有一种简单的方法来实现这一点?(我不感兴趣的是平均值,我需要进行中位数计算)。我正在为Android编写此代码(使用OpenCV4Android),因此计算能力有限。
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是它们的宽度和高度。上述方法中使用了更多的Mats操作,其时间复杂度为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];
clone
之后考虑使用min max,可能会有一个高效的向量化(SSE/Neon)实现。cv::min(listImages[i],listImages[j],listImages[i]);
cv::max(listImages[j],tmp,listImages[j]);
(当然,您不需要计算cmp
)。 - Antonio