() 运算符的这种特殊用途是啥意思?

Posted

技术标签:

【中文标题】() 运算符的这种特殊用途是啥意思?【英文标题】:What does this particular use of the () operator mean?() 运算符的这种特殊用途是什么意思? 【发布时间】:2014-10-20 06:17:20 【问题描述】:

我有这样的表达方式:

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 可以。也不明白作业左边的双括号。

【问题讨论】:

我假设 U 是一个标量(即,size 1×1)?还是size(M,1) 的列向量(即与M 具有相同的行数)? @Shai U 的大小必须为 size(M,1) x 1.* 才能工作; (U * ones(1,4)) 基本上是repmat(U, 1,4),我想。 U是列向量size(2*N, 1),和M的行大小一样,不清楚的地方见谅。 【参考方案1】:

在 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)。

【讨论】:

谢谢,看起来很棒。一个澄清:我认为Matlab从索引1开始,所以在C++中它宁愿是索引:2,5,8,11? 最后一个问题:如果方括号的两种用法是等价的,你能猜到为什么开发者同时使用了这两种方法吗? @aledalgrande 不知道 @aledalgrande:这里使用的双方括号是多余的,所以你创建一个像[1 2; 3 4][[1 2]; [3 4]]这样的矩阵,结果是一样的。【参考方案2】:

OpenCV

您可以在 OpenCV 中以某种矢量化的形式简洁地编写语句:

for (int i=2; i<12; i+=3) 
    Mat(M.col(i).mul(U)).copyTo(M.col(i));


MATLAB

不管怎样,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 或原始代码还要快!

【讨论】:

以上是关于() 运算符的这种特殊用途是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章

c语言中num是啥意思

TypeScript 管道运算符与字符串一起使用时是啥意思?

“类型”是啥意思,ECMA 6 中的问号有啥特殊用途吗?

Python - 列表上*运算符的用途是啥[重复]

nan是啥意思

“*”在各种指针场景中是啥意思?