【问题标题】:Operating on a vector from 4D matrix in Matlab在 Matlab 中对来自 4D 矩阵的向量进行操作
【发布时间】:2013-03-04 10:36:13
【问题描述】:

我正在尝试对图像中的每个像素进行如下操作:

A 是 x*y*4 矩阵,w 只是一个 1x9 向量。

我有一个矩阵 L,它是 200x200x4x9。

L 的前两个维度是像素的 (x,y) 位置。每个位置有 4 个不同的子像素(第三维)。每个子像素都有一个向量 m,最后一维就是我方程中的 m。

我打算得到整个图像的第一个子像素的结果,这就是我尝试的:

A (:,:,1) = w * L (:, :, 1, :)  ====> Inputs must be 2-D, or at least one input must be scalar.
A (:,:,1) = w * L (:, :, 1, :)' ====> Transpose on ND array is not defined.
A (:,:,1) = w * reshape (L (:, :, 1, :), 1, 9)' ===> To RESHAPE the number of elements must not change.

如果我只打印 L (1,1,1,:) 我会得到单个元素的值(看起来不像向量):

ans(:,:,1,1) = 0.8980
ans(:,:,1,2) = 0.8065
ans(:,:,1,3) = 0.8471
ans(:,:,1,4) = 0.7607
ans(:,:,1,5) = 0.7175
ans(:,:,1,6) = 0.9020
ans(:,:,1,7) = 0.8100
ans(:,:,1,8) = 0.7640
ans(:,:,1,9) = 0.8135

编辑:供参考,

Size(A) = [200 200 4]
Size(L) = [200 200 4 9] 
Size(w) = [1 9]

编辑:这就是我使用循环的方式

【问题讨论】:

  • 要获取矢量,请尝试squeeze(L(1,1,1,:))

标签: matlab


【解决方案1】:

与其在双 for 循环中使用带有 reshape 等的矩阵乘法,不如倒转过程并在较短的维度上循环,如下所示:

A=zeros(size(L)(1:3));
for i=1:9
    A(:,:,:)=A(:,:,:)+w(i).*L(:,:,:,i);
end

因此,您总共执行了 9 次循环,而不是通过双 for 循环执行 40000 次循环。而且我怀疑 Matlab 的 JITA 也会在这样的循环上工作,以产生更好的结果(我使用八度音阶,所以我不能确定 - 这也不值得我做任何时序测试,因为八度音阶的时序不会对matlab有效)。

也可以通过简单地使用向量索引而不是矩阵索引来纯粹以向量形式执行此操作。它的工作原理是这样的:

A=zeros(size(L)(1:3));
A(:)=reshape(L,numel(A),9)*w';

这个版本当然使用了 reshape,但它避免了 bsxfun 和挤压,我怀疑它会比其他解决方案更快,除了前面提到的 for 循环 9 个值。

(当然,如果你想将其限制为仅“第一个子像素”,则需要限制数据。对于 for 循环选项,只需在适当的位置放置一个 1 代替冒号。对于重塑和矩阵乘法选项,在出现的两个地方都用 L(:,:,1,:) 替换 L)

【讨论】:

    【解决方案2】:

    您应该使用squeeze 来获得向量形式。试试

    a=squeeze(L(1,1,1,:))
    

    【讨论】:

    • 谢谢,挤压工作。但是当我执行 A(:,:,1)= w*squeeze(L(:,:,1,:)) 时,我仍然会得到“输入必须是二维的,或者至少一个输入必须是标量的。”
    • squeeze(L(:,:,1,:)) 的结果将是一个 3D 矩阵,而不是一个向量或 2D 矩阵,因为您只保持 L 的第三维不变,其余三个维度将被压缩成一个3D 矩阵。你到底想完成什么? size(w) 是什么?
    • 我只想一次性计算所有 (x,y) 的第一个子像素的结果。这就是为什么我猜它类似于 A(:,:,1)= w*L(:,:,1,:))
    【解决方案3】:

    我最近成为bsxfun 的忠实粉丝,假设我对您的理解正确,这似乎非常适合它。我们只需要重塑w,然后利用bsxfun 自动扩展单例维度的能力,使其输入的大小匹配。

    w = reshape(w, [1, 1, 1, length(w)]);
    A = sum(bsxfun(@times, L, w), 4);
    

    【讨论】:

      【解决方案4】:

      多维乘法在 Matlab 中不起作用,这就是为什么你不能做A = L * w

      来自 Mathworks 页面 (How can I perform multi-dimensional matrix multiplication in MATLAB?):

      解决方案:

      执行多维矩阵乘法的能力 MATLAB 不可用。

      作为一种解决方法,使用 FOR 循环。

      另外,还有一个用户创建的函数叫 NDFUN 比 执行 N 维矩阵乘法。有关详细信息,请参阅 NDFUN 部分位于以下 URL:

      http://www.mit.edu/~pwb/matlab/

      带有循环的解决方案应如下所示:

      A = zeros( size(L)(1:3) );
      for i = 1:size(L,1)
          for j = 1 : size(L,2)
              A(i,j,:) = squeeze( L(i,j,:,:) ) * w';
          end
      end
      

      但如果您更喜欢简洁的解决方案而不是更快的解决方案(循环应该很快),您可以使用答案Multiply a 3D matrix with a 2D matrix 中的方法(假设size(L) == [200 200 4 9]size(w) = [1 9]):

      Ac = cellfun( @(x) squeeze(x)' * w', num2cell(L,4), 'UniformOutput', false);
      A = cell2mat( squeeze(Ac) );
      

      【讨论】:

      • 是的 A 是 xy*4。我不能简单地做 A=Lw '我得到 Inputs must be 2-D, or at least one input must be scalar.'尺寸(A) = [200 200 4],尺寸(L) = [200 200 4 9] 尺寸(w) = [1 9]
      • 你必须转置w然后做乘法...A = L * w'
      • 输入必须是二维的,或至少一个输入必须是标量
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-16
      • 1970-01-01
      • 1970-01-01
      • 2016-10-13
      • 2015-10-29
      • 2023-03-23
      • 2013-07-10
      相关资源
      最近更新 更多