【问题标题】:OpenCV mask operation, elementwise assignment in c++OpenCV掩码操作,C++中的元素赋值
【发布时间】:2014-08-02 05:59:42
【问题描述】:

我想根据matB 的值将matA 的每个像素分配给某个值,我的代码是一个嵌套的for循环:

clock_t begint=clock();
for(size_t i=0; i<depthImg.rows; i++){
    for(size_t j=0; j<depthImg.cols; j++){
        datatype px=depthImg.at<datatype>(i, j);
        if(px==0)
            depthImg.at<datatype>(i, j)=lastDepthImg.at<datatype>(i, j);
    }
}
cout<<"~~~~~~~~time: "<<clock()-begint<<endl;

对于尺寸为 640*480 的垫子,大约需要 40~70 毫秒。

我可以在 python numpy 中使用精美的索引轻松做到这一点:

In [18]: b=np.vstack((np.ones(3), np.arange(3)))

In [19]: b
Out[19]: 
array([[ 1.,  1.,  1.],
       [ 0.,  1.,  2.]])

In [22]: a=np.vstack((np.arange(3), np.zeros(3)))

In [23]: a=np.tile(a, (320, 160))

In [24]: a.shape
Out[24]: (640, 480)

In [25]: b=np.tile(b, (320, 160))

In [26]: %timeit a[a==0]=b[a==0]
100 loops, best of 3: 2.81 ms per loop

这比我手写for循环要快得多。

那么opencv c++ api中有这样的操作吗?

【问题讨论】:

标签: python c++ opencv numpy


【解决方案1】:

我无法在我的机器上复制您的计时结果您的 C++ 代码在我的机器上运行时间不到 1 毫秒。但是,每当您的迭代速度较慢时,应该立即怀疑at&lt;&gt;()。 OpenCV 有一个tutorial on iterating through images,我推荐它。

但是,对于您描述的操作,有更好的方法。 Mat::copyTo() 允许屏蔽操作:

lastDepthImg.copyTo(depthImg, depthImg == 0);

这比嵌套循环解决方案更快(大约快 2 倍)且可读性更强。此外,它可能会受益于 SSE 等硬件优化。

【讨论】:

  • copyTo 正是我所需要的,它每帧只运行 1~3 毫秒——快了几十倍!!我很好奇为什么它在你的框架上只有 2 倍的速度?
  • @zhangxaochen 我怀疑这部分是时间问题。 clock() 不保证具有高分辨率,因此您可能会得到不精确的时间。
【解决方案2】:

在您的 C++ 代码中,您在每个像素处进行函数调用,并传入两个索引,这些索引将被转换为平面索引,执行类似i*depthImageCols + j 的操作。

我的 C++ 技能大多缺乏,但使用 this 作为模板,我想你可以尝试类似的东西,这应该可以消除大部分开销:

MatIterator_<datatype> it1 = depthImg.begin<datatype>(),
                       it1_end = depthImg.end<datatype>();
MatConstIterator_<datatype> it2 = lastDepthImg.begin<datatype>();

for(; it1 != it1_end; ++it1, ++it2) {
    if (*it1 == 0) {
        *it1 = *it2;
    }
}

【讨论】:

  • 感谢您的提示,但这在我的机器上花费更多(大约 150 毫秒)。你是怎么尝试的?
  • 您的时间似乎不太可能:您不应该看到任何这些方法之间的数量级差异,例如参见here。可能是您没有正确计算时间吗? clock时钟滴答 为单位测量时间,因此将其转换为毫秒的正确方法是 (clock() - begint) * 1000 / CLOCKS_PER_SEC
  • 我在时间上看到了同样的趋势。 -O3 与 GCC 4.8.2 为我尝试过的每种 opencv 方法提供 5-12 毫秒。 numpy 给出 1-2 毫秒。
  • @Jaime CLOCKS_PER_SEC 在我的机器上是 1000。无论如何,它显然在变慢,即使clock()-begint不是msec,它也是一个时间度量。
  • @Jaime 遗憾的是,使用迭代器和其他方法之间存在数量级的差异。我同意clock() 可能不是最好的时间测量。使用高分辨率计时器会更好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-07
  • 2021-05-20
  • 1970-01-01
相关资源
最近更新 更多