【问题标题】:Avoiding sub2ind and ind2sub避免 sub2ind 和 ind2sub
【发布时间】:2013-04-22 10:00:32
【问题描述】:

我需要访问 3D 中某个点周围的多个索引。 例如,对于点 (x1,y1,z1),我需要获取其 3x3x3 邻域的所有索引,使得 (x1,y1,z1) 居中。对于大小为 3 的邻居,我使用

 [x,y,z] = meshgrid(-1:1,-1:1,-1:1);
 x_neighbors = bsxfun(@plus,x,x1);
 y_neighbors = bsxfun(@plus,y,y1);
 z_neighbors = bsxfun(@plus,z,z1);

在这里,我通过将 (x1,y1,z1) 到 3x3x3 中任意点的距离相加,将 x1,y1,z1 居中到 (0,0,0)盒子。

这给了我 (x1,y1,z1) 3x3x3 邻域的坐标。然后我需要将它们转换为线性索引,以便我可以访问它们:

 lin_ind = sub2ind(size(volume),y_neighbors,x_neighbors,z_neighbors);

这对我来说是昂贵的。

我的问题是,如何避免sub2ind。如果inx是(x1,y1,z1)的线性索引,

inx = sub2ind(size(volume),y1,x1,z1);

如何通过inx 的加减或任何其他简单操作找到线性索引的 3x3x3 邻域?

【问题讨论】:

  • 为什么需要线性索引?你用这个做什么操作?你不能像M(x_neighbors, y_neighbors, z_neighbors)这样的社区吗?你也可以这样做而不是网格等:M(x_neighbors-1:x_neighbors+1, y_neighbors-1:y_neighbors+...etc
  • 您总是可以自己进行array(i + rows*j + rows*cols*k) 类型的计算...只需看看sub2ind 是如何计算的,然后复制粘贴相关部分。
  • @Dan,无法访问 M(y_n,x_n,z_n) 因为我只需要 3x3x3 邻域的一部分,(我在索引上应用了掩码)所以我实际拥有的是 x_list, y_list,z_list 和访问 M(y_list,x_list,z_list) 给出了 y_list,x_list,z_list 的所有位置,而不是它们的组合......我不能使用你的其他建议,因为我有很多点(p1,...... pn) 而不仅仅是一个 (x1,y1,z1),我需要快速完成..
  • 由于 x1, y1, z1 是标量,您不必使用 bsxfun。 x_neighbors = x + x1 也可以。
  • @Alex 它们不是标量,只是在这个例子中它们是......它们实际上是一个巨大的数组,我之前在回复 Dan 时提到过

标签: matlab indexing computer-vision bsxfun


【解决方案1】:

只要您知道 3D 数组的尺寸,就可以计算 3x3x3 邻域中所有元素的线性偏移量。为了说明这一点,考虑一个 4x5 矩阵的 2D 示例。线性索引如下所示:

1 5  9 13 17
2 6 10 14 18
3 7 11 15 19
4 8 12 16 20

10 的 3x3 邻域是[5 6 7 9 10 11 13 14 15]。 15 的 3x3 邻域是 [10 11 12 14 15 16 18 19 20]。如果我们减去中心元素的索引,在这两种情况下我们都会得到[-5 -4 -3 -1 0 1 3 4 5]。更一般地,对于MxN 矩阵,我们将有[-M-1 -M -M+1 -1 0 1 M-1 M M+1][(-M+[-1 0 1]) -1 0 1 (M+[-1 0 1])]

推广到三个维度,如果数组是MxNxP,则与中心元素的线性索引偏移量将为[(-M*N+[-M-1 -M -M+1 -1 0 1 M-1 M M+1]) [-M-1 -M -M+1 -1 0 1 M-1 M M+1] (M*N+[-M-1 -M -M+1 -1 0 1 M-1 M M+1])]。如果您愿意,可以将其重新调整为 3x3x3。

请注意,这种索引不能很好地处理边缘;如果你想在数组的边缘找到一个元素的邻居,你应该首先填充数组的所有边(从而改变MNP)。

【讨论】:

  • 谢谢!!这正是我想要的。对于更大的邻域(而不仅仅是 3X3),我只需要再概括一下,所以按照你所做的,系列应该上升到 floor(neighborhood_size/2),例如,对于 5X5: floor(5/2 ) = 2,我有:[-M-2 -M-1 M -M+1 -M+2 -2 -1 0 ....] (与阳性相同)。谢谢!!!
【解决方案2】:

只需将(通用)代码添加到@nhowe 答案: 这是大小为 5X5X5 的邻域的示例,因此 r(半径)为 2:

ns = 5;
r = 2;

[M,N,D] = size(vol);
rs = (1:ns)-(r+1);
% 2d generic coordinates:
neigh2d = bsxfun(@plus, M*rs,rs');
% 3d generic coordinates:
pages = (M*N)*rs;
pages = reshape(pages,1,1,length(pages));

neigh3d = bsxfun(@plus,neigh2d,pages);

要获得 vol 的任何线性索引的任何邻域,只需将线性索引添加到 neigh3d:

new_neigh = bxsfun(@plus,neigh3d, lin_index);

【讨论】:

  • 我知道这是一个老问题,但是从neigh2d,我如何访问矩阵的值,因为neigh2d 中的坐标包含负值?我只考虑二维矩阵。
猜你喜欢
  • 2014-03-09
  • 1970-01-01
  • 2020-07-12
  • 2011-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-24
  • 2010-12-29
相关资源
最近更新 更多