3d 矩阵:如何在 MATLAB 中使用(行,列)对与 3 维通配符?
3d matrix: how to use (row, column) pairs with 3rd dimension wildcard in MATLAB?
我有一个 3 维矩阵和一个(行,列)对列表。我想提取与那些位置的元素相对应的二维矩阵,通过矩阵的深度进行投影。例如,假设,
>> a = rand(4, 3, 2)
a(:,:,1) =
0.5234 0.7057 0.0282
0.6173 0.2980 0.9041
0.7337 0.9380 0.9639
0.0591 0.8765 0.1693
a(:,:,2) =
0.8803 0.2094 0.5841
0.7151 0.9174 0.6203
0.7914 0.7674 0.6194
0.2009 0.2542 0.3600
>> rows = [1 4 2 1];
>> cols = [1 2 1 3];
我想得到的是,
0.5234 0.8765 0.6173 0.0282
0.8803 0.2542 0.7151 0.5841
也许有一些维度的排列。另外,虽然这个例子在最后一个维度中有通配符,但我也有它在第一个或第二个维度中的情况。
我天真地尝试了 a(rows, cols, :)
并得到了一个 3d 矩阵,其中对角线平面就是我想要的。我还找到了 sub2ind
,它将从 a(:,:,1)
平面中提取所需的元素。我可以使用其中之一来达到我想要的效果,但我想知道是否有我缺少的更规范、更优雅或更有效的方法?
更新
这是我使用的解决方案,基于下面发布的答案,
sz = size(a);
subs = [repmat(rows, [1, sz(3)]);
repmat(cols, [1, sz(3)]);
repelem([1:sz(3)], length(rows))];
result = a(sub2ind(sz, subs(1,:), subs(2,:), subs(3,:)));
sub2ind
几乎是您在这里必须使用的将下标转换为线性索引的方法(除了您自己手动计算线性索引)。您可以执行如下操作,将 rows
和 cols
转换为线性索引(在二维切片中),然后添加偏移量(等于二维切片中的元素数)对这些索引进行采样,以对三维中的所有元素进行采样。
sz = size(a);
inds = sub2ind(sz(1:2), rows, cols);
inds = bsxfun(@plus, inds, (0:(sz(3)-1)).' * prod(sz(1:2)));
result = a(inds);
并亲自实际计算线性指数
inds = (cols - 1) * sz(1) + rows;
inds = bsxfun(@plus, inds, (0:(sz(3) - 1)).' * prod(sz(1:2)));
result = a(inds);
另一种选择是置换初始矩阵以将第三维带到第一维,将其重塑为二维矩阵,然后使用线性索引作为第二个下标
% Create a new temporary matrix
anew = reshape(permute(a, [3, 1, 2]), size(a, 3), []);
% Grab all rows (the 3rd dimension) and compute the columns to grab
result = anew(:, (cols - 1) * size(a, 1) + rows);
我有一个 3 维矩阵和一个(行,列)对列表。我想提取与那些位置的元素相对应的二维矩阵,通过矩阵的深度进行投影。例如,假设,
>> a = rand(4, 3, 2)
a(:,:,1) =
0.5234 0.7057 0.0282
0.6173 0.2980 0.9041
0.7337 0.9380 0.9639
0.0591 0.8765 0.1693
a(:,:,2) =
0.8803 0.2094 0.5841
0.7151 0.9174 0.6203
0.7914 0.7674 0.6194
0.2009 0.2542 0.3600
>> rows = [1 4 2 1];
>> cols = [1 2 1 3];
我想得到的是,
0.5234 0.8765 0.6173 0.0282
0.8803 0.2542 0.7151 0.5841
也许有一些维度的排列。另外,虽然这个例子在最后一个维度中有通配符,但我也有它在第一个或第二个维度中的情况。
我天真地尝试了 a(rows, cols, :)
并得到了一个 3d 矩阵,其中对角线平面就是我想要的。我还找到了 sub2ind
,它将从 a(:,:,1)
平面中提取所需的元素。我可以使用其中之一来达到我想要的效果,但我想知道是否有我缺少的更规范、更优雅或更有效的方法?
更新
这是我使用的解决方案,基于下面发布的答案,
sz = size(a);
subs = [repmat(rows, [1, sz(3)]);
repmat(cols, [1, sz(3)]);
repelem([1:sz(3)], length(rows))];
result = a(sub2ind(sz, subs(1,:), subs(2,:), subs(3,:)));
sub2ind
几乎是您在这里必须使用的将下标转换为线性索引的方法(除了您自己手动计算线性索引)。您可以执行如下操作,将 rows
和 cols
转换为线性索引(在二维切片中),然后添加偏移量(等于二维切片中的元素数)对这些索引进行采样,以对三维中的所有元素进行采样。
sz = size(a);
inds = sub2ind(sz(1:2), rows, cols);
inds = bsxfun(@plus, inds, (0:(sz(3)-1)).' * prod(sz(1:2)));
result = a(inds);
并亲自实际计算线性指数
inds = (cols - 1) * sz(1) + rows;
inds = bsxfun(@plus, inds, (0:(sz(3) - 1)).' * prod(sz(1:2)));
result = a(inds);
另一种选择是置换初始矩阵以将第三维带到第一维,将其重塑为二维矩阵,然后使用线性索引作为第二个下标
% Create a new temporary matrix
anew = reshape(permute(a, [3, 1, 2]), size(a, 3), []);
% Grab all rows (the 3rd dimension) and compute the columns to grab
result = anew(:, (cols - 1) * size(a, 1) + rows);