我想根据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;
对于尺寸为640 * 480的垫子,它的成本约为40~70ms。
我可以使用花式索引在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-loop要快得多。
在opencv c ++ api中有这样的操作吗?
答案 0 :(得分:3)
我无法在我的机器上复制您的计时结果您的C ++代码在我的机器上运行不到1毫秒。但是,每当迭代缓慢时,at<>()
应该立即被怀疑。我推荐OpenCV有一个tutorial on iterating through images。
但是,对于您描述的操作,有一种更好的方法。 Mat::copyTo()
允许屏蔽操作:
lastDepthImg.copyTo(depthImg, depthImg == 0);
这比嵌套循环解决方案更快(大约快2倍)并且可读性更高。此外,它可能受益于SSE等硬件优化。
答案 1 :(得分:1)
在你的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;
}
}