我有这个表达:
M(:,[[3,6,9,12]]) = M(:,[3,6,9,12]) .* (U * ones(1,4));
我查了Matlab文档,但没有这样的例子。试图将其翻译为OpenCV C ++。这是我的代码:
cv::Mat temp(M.rows, 4, CV_64F);
M.col(2).copyTo(temp(cv::Rect(0,0,1,M.rows)));
M.col(5).copyTo(temp(cv::Rect(1,0,1,M.rows)));
M.col(8).copyTo(temp(cv::Rect(2,0,1,M.rows)));
M.col(11).copyTo(temp(cv::Rect(3,0,1,M.rows)));
temp = temp.mul(U * cv::Mat::ones(1,4,CV_64F));
temp.col(0).copyTo(M(cv::Rect(2,0,1,M.rows)));
temp.col(1).copyTo(M(cv::Rect(5,0,1,M.rows)));
temp.col(2).copyTo(M(cv::Rect(8,0,1,M.rows)));
temp.col(3).copyTo(M(cv::Rect(11,0,1,M.rows)));
这是对的吗?据我所知,我无法直接在OpenCV中更改这些列,也许可以使用Eigen。也不理解作业左侧的双括号。
答案 0 :(得分:3)
在Matlab中,您提供的代码很好地向量化,因为这是在不使用Mex的情况下获得良好性能的唯一方法。但是,在c ++中,最好将其扩展为for
循环,以实现可读性和性能。
for(int i=0; i<M.rows; ++i) {
for(int j=2; j<12; j+=3) { // start from 2 due to 0-based indexing
M.at<double>(i,j) *= U.at<double>(i);
}
}
请注意使用*=
运算符,这在Matlab中不可用。
哦,[[3,6,9,12]]
相当于[3,6,9,12]
(和3:3:12
)。
答案 1 :(得分:1)
您可以在OpenCV中以一种有点矢量化的形式简洁地编写语句:
for (int i=2; i<12; i+=3) {
Mat(M.col(i).mul(U)).copyTo(M.col(i));
}
对于它的价值,MATLAB代码也可以用广播编写:
M(:,[3 6 9 12]) = bsxfun(@times, M(:,[3 6 9 12]), U);
这可以避免在内存中复制向量U
。它与:
for i=3:3:12
M(:,i) = M(:,i) .* U;
end
类似于上面的C ++代码。
不幸的是,多年来,MATLAB因循环速度慢而声名狼借,并且应该总是更喜欢完全向量化的代码而不是循环。但是,自从JIT改进以来,在所有情况下都不再适用。
事实上,最后一个for循环非常快,甚至比bsxfun
或原始代码快一点!