在Matlab中对4D矩阵的矢量进行操作

时间:2013-03-15 16:08:04

标签: matlab

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

equation

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]

编辑:这是我使用循环

的方式

loop

4 个答案:

答案 0 :(得分:2)

不是在double for循环中使用带有reshape等的矩阵乘法,而是颠倒过程并在较短的维度上循环可能更好,如下所示:

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

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

通过简单地使用向量索引而不是矩阵索引,也可以纯粹以矢量形式进行。它的工作原理如下:

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

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

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

答案 1 :(得分:1)

您应该使用squeeze来获取矢量表单。尝试

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

多维乘法在Matlab中不起作用,这就是你不能做A = L * w 的原因!

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

  

解决方案:

     

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

     

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

     

此外,还有一个名为NDFUN的用户创建函数   执行N-D矩阵乘法。有关更多信息,请参阅   关于NDFUN的部分,请访问以下网址:

     

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