简体   繁体   English

3D矩阵到2D矩阵Matlab

[英]3d Matrix to 2d Matrix matlab

I am using Matlab R2014a. 我正在使用Matlab R2014a。

I have a 3-dimensional M x N x M matrix A. I would like a vectorized way to extract a 2 dimensional matrix B from it, such that for each i,j I have 我有一个3维M x N x M矩阵A。我想采用向量化的方式从中提取2维矩阵B,这样对于每个i,j

B(i,j)=A(i,j,g(i,j)) B(I,J)= A(I,J,G(I,J))

where g is a 2-dimensional index matrix of size M x N, ie with integral values in {1,2,...,M}. 其中g是大小为M x N的二维索引矩阵,即在{1,2,...,M}中具有整数值。

The context is that I am representing a function A(k,z,k') as a 3-dimensional matrix, the function g(k,z) as a 2-dimensional matrix, and I would like to compute the function 上下文是我将函数A(k,z,k')表示为3维矩阵,将函数g(k,z)表示为2维矩阵,并且我想计算该函数

h(k,z)=f(k,z,g(k,z)) H(K,Z)= F(K,Z,G(K,Z))

This seems like a simple and common thing to try to do but I really can't find anything online. 这似乎是一件简单而又常见的事情,但是我真的在网上找不到任何东西。 Thank you so much to whoever can help! 非常感谢任何可以帮助的人!

My first thought was to try something like B = A(:,:,g) or B=A(g) but neither of these works, unsurprisingly. 我的第一个想法是尝试尝试类似B = A(:,:,g)或B = A(g)的方法,但这两种方法都不奇怪。 Is there something similar? 有类似的东西吗?

You can employ the best tool for vectorization, bsxfun here - 您可以在此处使用最佳的矢量化工具bsxfun

B = A(bsxfun(@plus,[1:M]',M*(0:N-1)) + M*N*(g-1))

Explanation: Breaking it down to two steps 说明:将其分为两个步骤

Step #1: Calculate the indices corresponding to the first two dimensions (rows and columns) of A - 步骤#1:计算对应于所述第一二维(行和列)的索引A -

bsxfun(@plus,[1:M]',M*(0:N-1))

Step #2: Add the offset needed to include the dim-3 indices being supplied by g and index into A with those indices to get our desired output - 步骤#2:将包含g提供的dim-3索引和包含这些索引的索引添加到A中所需的偏移量,以获得所需的输出-

A(bsxfun(@plus,[1:M]',M*(0:N-1)) + M*N*(g-1))

Benchmarking 标杆

Here's a quick benchmark test to compare this bsxfun based approach against the ndgrid + sub2ind based solution as presented in Luis's solution with M and N as 100 . 这是一个快速的基准测试,用于将这种基于bsxfun的方法与基于ndgrid + sub2ind的解决方案MN100 Luis解决方案)进行比较。

The benchmarking code using tic-toc would look something like this - 使用tic-toc的基准测试代码如下所示-

M = 100;
N = 100;
A = rand(M,N,M);
g = randi(M,M,N);

num_runs = 5000; %// Number of iterations to run each approach

%// Warm up tic/toc.
for k = 1:50000
    tic(); elapsed = toc();
end

disp('-------------------- With BSXFUN')
tic
for iter = 1:num_runs
    B1 = A(bsxfun(@plus,[1:M]',M*(0:N-1)) + M*N*(g-1));  %//'
end
toc, clear B1

disp('-------------------- With NDGRID + SUB2IND')
tic
for iter = 1:num_runs
    [ii, jj] = ndgrid(1:M, 1:N);
    B2 = A(sub2ind([M N M], ii, jj, g));
end
toc

Here's the runtime results - 这是运行时结果-

-------------------- With BSXFUN
Elapsed time is 2.090230 seconds.
-------------------- With NDGRID + SUB2IND
Elapsed time is 4.133219 seconds.

Conclusions 结论

As you can see bsxfun based approach works really well, both as a vectorized approach and good with performance too. 如您所见,基于bsxfun的方法非常有效,既可以作为矢量化方法使用,又可以兼顾性能。

Why is bsxfun better here - 为什么bsxfun在这里更好-

  • bsxfun does replication of offsetted elements and adding them, both on-the-fly . bsxfun确实抵消元素的复制和加入他们,无论在即时

  • In the other solution, ndgrid internally makes two function calls to repmat , thus incurring the function call overheads. 在另一种解决方案中, ndgrid内部对repmat进行两个函数调用,从而导致函数调用开销。 At the next step, sub2ind spends time in adding the offsets to get the linear indices, bringing in another function call overhead. 在下一步中, sub2ind花费时间来添加偏移量以获得线性索引,从而带来另一个函数调用开销。

Try using sub2ind . 尝试使用sub2ind This assumes g is defined as an M x N matrix with possible values 1 , ..., M : 假设g被定义为M x N矩阵,可能值为1 ,..., M

[ii, jj] = ndgrid(1:M, 1:N);
B = A(sub2ind([M N M], ii, jj, g));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM