当前位置: 首页 > 知识库问答 >
问题:

用OpenCV从图像序列中获取中值图像

司寇书
2023-03-14

我有一系列图像,我想计算中间图像(以去除运动元素)。直观地说,硬编码一个循环以遍历所有像素将有一个总的运行时间,以及相当大的内存使用量。有没有办法在OpenCV中轻松实现这一点?(我对平均值不感兴趣,我需要做一个中位数)。我是为Android写这篇文章的(使用OpenCV4Android),所以显然计算能力是有限的。

共有2个答案

罗伟志
2023-03-14

如果平均值正常:

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),在Mats上有更多的操作。

经典代码(几乎所有计算都将以原生方式进行):

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];
傅正豪
2023-03-14

据我所知,没有OpenCV函数可以从图像序列中创建中值图像。几年前我需要同样的功能,我不得不自己实现它。它相对较慢,因为对于每个像素,您需要从多个图像中提取相关像素(内存访问效率低下)并计算中值(也是一个耗时的过程)。

提高效率的可能方法是:

  • 无需从所有图像中计算中值。一小部分图像就足够了。
  • 您可以找到更有效的算法来查找一些小组的中值。例如,我使用的算法可以有效地在九个值的组中查找中值。
 类似资料:
  • 我只想弄清楚我的概念-访问CV::MAT的所有矩阵元素是否意味着我实际上访问了图像的所有像素值(灰度-1通道,颜色-3通道)?假设我的代码打印灰度矩阵的值(加载1通道图像,类型为CV_32FC1),如下所示,那么这意味着我只访问cv::mat的成员,还是我也访问图像的像素值(具有1通道灰度,类型为CV_32FC1)? 我对使用OpenCV进行图像处理还是一个新手,我想澄清一下我的想法。如果我错了,

  • 你知道这个错误的原因是什么吗?

  • 问题内容: 我已经阅读了有关如何使用OpenCV的基于HOG的行人检测器的文章: 如何使用OpenCV检测和跟踪人员? 我想使用HOG来检测图像中的其他类型的对象(不仅仅是行人)。但是, HOGDetectMultiScale 的Python绑定似乎无法提供对实际HOG功能的访问。 是否可以使用Python + OpenCV直接从任何图像中提取HOG功能? 问题答案: 如果您想要用于HOG功能的快

  • 我试图使用OpenCV和Java实现一些图像处理,从图像中提取一张卡片。 以下是我的做法: 转换为BGR图像 转换为灰度图像 应用高斯模糊 应用Canny边缘检测 扩张 查找等高线 查找最大轮廓 使用approxpolydp查找最大轮廓的角 沿最大轮廓获取裁剪图像的自上而下视图 代码如下: 寻求帮助在获得适当的角顶点...提前感谢…

  • 上面的代码从一个名为“多媒体资料”的自定义帖子中提取WordPress多媒体资料,然后存储并显示图像。是否有一种方法也可以将库的标题存储到变量中?

  • 包的类提供读取和写入图像的方法。使用OpenCV,可以读取图像并将其存储在矩阵中(如果需要,可在矩阵上执行转换)。之后可以将处理后的矩阵写入文件。 类的方法用于使用OpenCV读取图像。 以下是此方法的语法。 它接受一个参数(文件名),一个字符串类型的变量,表示要读取的文件的路径。 下面给出了使用OpenCV库读取Java图像的步骤。 第1步:加载OpenCV本机库 使用方法加载OpenCV本机库