4

我希望我的问题有一个非常简单的解决方案。我只是找不到它:

假设您有两个向量(一个是列向量,一个是行向量)A、B:

A = [1,2,3]
B = [4;5;6]

如果我们将它们相乘如下,我们得到一个矩阵:

>> B*A
ans =
 4     8    12
 5    10    15
 6    12    18

现在我的问题是:我有两个大小的 3D 矩阵m × n × pm × n × q

想象沿着维度mn我们有像素,并且对于每个像素我们有一个向量(长度 p 或 q)。现在我想要的是为每个相应的像素乘以两个图像的向量,这样对于每个像素,我得到一个矩阵,因此最终得到一个 4D 矩阵。

我如何有效地做到这一点?

4

3 回答 3

4

Matlab 中的循环不再是值得害怕或避免的事情

当然,在使用它们时应该非常小心,但是,JIT 可以处理多种循环,甚至可以在内置函数之外提高性能。

考虑以下测试用例:

clc

m = 512;   n = 384;
p = 5;     q = 3;

A = rand(m,n,p); % some sample data
B = rand(m,n,q); % some sample data

%% non-loop approach

tic
A2 = reshape(A,[],p);
B2 = reshape(B,[],q);
C2 = arrayfun(@(ii) A2(ii,:)'*B2(ii,:),1:m*n,'uni',false);
C0 = permute(reshape(cell2mat(C2),p,q,m,n),[3 4 1 2]);
toc

%% looped approach, simplest

tic
C = zeros(m,n,p,q);
for mm = 1:m
    for nn = 1:n        
        C(mm,nn,:,:) = ...
            squeeze(A(mm,nn,:))*squeeze(B(mm,nn,:)).';
    end
end
toc

% check for equality
all(C0(:) == C(:))

%% looped approach, slightly optimized

tic
C = zeros(m,n,p,q);
pp = zeros(p,1);
qq = zeros(1,q);
for mm = 1:m
    for nn = 1:n
        pp(:) = A(mm,nn,:);
        qq(:) = B(mm,nn,:);
        C(mm,nn,:,:) = pp*qq;
    end
end
toc

% check for equality
all(C0(:) == C(:))

%% looped approach, optimized

tic
C  = zeros(p,q,m*n);
A2 = reshape(A,[],p);
B2 = reshape(B,[],q);
for mn = 1:m*n
    C(:,:,mn) = A2(mn,:).'*B2(mn,:);
end
C = permute(reshape(C, p,q,m,n), [3,4,1,2]);
toc

% check for equality
all(C0(:) == C(:))

结果:

Elapsed time is 3.955728 seconds.
Elapsed time is 21.013715 seconds.
ans =
     1
Elapsed time is 1.334897 seconds.
ans =
     1
Elapsed time is 0.573624 seconds.
ans =
     1

无论性能如何,我还发现最后一个案例比非循环案例更直观和可读。

于 2012-07-28T05:46:17.937 回答
3

通过一些重塑arrayfunpermute

m=5;
n=4;
p=3;
q=2;
A=randi(10,m,n,p); %some sample data
B=randi(10,m,n,q); %some sample data

A2=reshape(A,[],p);
B2=reshape(B,[],q);
C2=arrayfun(@(ii) A2(ii,:)'*B2(ii,:),1:m*n,'uni',false);

C=permute(reshape(cell2mat(C2),p,q,m,n),[3 4 1 2]);

分解:

  • 前两个 reshape 将 A 和 Bmxnx(p or q)矩阵更改为(m*n)x(p or q)格式
  • 这样arrayfun 可以轻松地循环遍历它们以计算行的向量积
  • 然后 cell2mat,reshape 和 permute 将结果改回mxnxpxq格式
于 2012-07-27T16:29:22.520 回答
0

我使用rody_o的解决方案并对其进行了修改以摆脱重塑和置换:

C  = zeros(m*n, p, q);
A2 = reshape(A,[],p);
B2 = reshape(B,[],q);
for mn = 1:m*n
    C(mn,:,:) = A2(mn,:).' * B2(mn,:);
end
于 2012-07-30T07:37:58.077 回答