简体   繁体   English

OpenCV掩码操作,c ++中的元素赋值

[英]OpenCV mask operation, elementwise assignment in c++

I'd like to assign each pixel of a mat matA to some value according to values of matB , my code is a nested for-loop: 我想垫的每个像素分配matA根据的值有一些价值matB ,我的代码是一个嵌套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;

and it costs about 40~70ms for a mat of size 640*480. 对于尺寸为640 * 480的垫子,它的成本约为40~70ms。

I could do this easily in python numpy using fancy indexing: 我可以使用花式索引在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

and this is much faster than my hand writing for-loop. 这比我写的for-loop要快得多。

So is there such operation in opencv c++ api? 那么在opencv c ++ api中有这样的操作吗?

I am unable to replicate your timing results on my machine Your C++ code runs in under 1ms on my machine. 我无法在我的机器上复制您的计时结果您的C ++代码在我的机器上运行不到1毫秒。 However, whenever you have slow iteration, at<>() should be immediately suspect. 但是,每当迭代速度很慢时, at<>()应该立即被怀疑。 OpenCV has a tutorial on iterating through images , which I recommend. OpenCV有一个迭代图像教程 ,我推荐。

However, for the operation you describe, there is a better way. 但是,对于您描述的操作,有一种更好的方法。 Mat::copyTo() allows masked operations: Mat::copyTo()允许屏蔽操作:

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

This is both faster (about 2x as fast) and far more readable than your nested-loop solution. 这比嵌套循环解决方案更快(大约快2倍)并且可读性更高。 In addition, it may benefit from hardware optimizations like SSE. 此外,它可能受益于SSE等硬件优化。

In your C++ code, at every pixel you are making a function call, and passing in two indices which are getting converted into a flat index doing something like i*depthImageCols + j . 在你的C ++代码中,你正在进行函数调用的每个像素,并传入两个索引,这些索引被转换为平面索引,类似于i*depthImageCols + j

My C++ skills are mostly lacking, but using this as a template, I guess you could try something like, which should get rid of most of that overhead: 我的C ++技能大多缺乏,但是使用作为模板,我想你可以尝试类似的东西,它应该摆脱大部分的开销:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM