获取矩阵元素的邻居

Tho*_*oth 2 matlab

我有一个矩阵,我希望得到每个元素的周围元素的索引.所有这些结果必须以下列方式存储到矩阵中.矩阵的每一行对应于矩阵元素,并且该矩阵的每列包含邻居索引.例如,对于4x4矩阵,我们将得到一个16x8结果数组.一些矩阵元素没有8个邻居.

有一个例子,我认为它有效,我有什么方法可以避免循环?:

ElementNeighbors = [];
for n = 1:numel(Matrix)
    NeighborsMask = [ n-1 n+1 n+size(matrix,1) n-size(Matrix,1) n-size(Matrix,1)-1 n-size(Matrix,1)+1 ...
        n+size(Matrix,1)-1 n+size(Matrix,1)+1 ];

    ElementNeighbors = [ElementNeighbors ; NeighborsMask ];
end
ElementNeighbors (ElementNeighbors ==0|ElementNeighbors <0) = NaN;
Run Code Online (Sandbox Code Playgroud)

Flo*_*ris 6

给定矩阵M(n,m)的线性索引,您可以说服自己元素的左上角邻居 M(i,j) = M(i-1, j-1) = M(i-1 + n * (j-2))

在"线性索引"空间中,表示该元素的偏移量

-n-1
Run Code Online (Sandbox Code Playgroud)

我们发现,为所有其他地点执行此操作

-n-1 | -1 | n-1
-n   |  x | n    => [-n-1, -n, -n+1, -1, +1, +n-1, +n, +n+1]
-n+1 | +1 | n+1     
Run Code Online (Sandbox Code Playgroud)

因此,您可以使用上述值创建向量偏移量(将n替换为第一个维度).例如,如果M是(5x4),那么

offset = [-6 -5 -4 -1 1 4 5 6];
Run Code Online (Sandbox Code Playgroud)

然后创建所有索引:

indices = bsxfun(@plus, (1:m*n), offset(:));
Run Code Online (Sandbox Code Playgroud)

bsxfun是"对这些元素执行此功能的一个很酷的简写;其中一个元素具有单个维度而另一个元素没有,相应地扩展".您可以使用repmat执行相同操作,但这会创建不必要的中间矩阵(有时可能非常大).

该命令将创建一个(8 x m*n)包含所有8个邻居的索引矩阵,包括那些可能不是真正的邻居...你需要修复的东西.

几种可能的方法:

  • 在开始之前填充矩阵
  • 不关心包装,只是摆脱掉落边缘的元素
  • 为所有"边缘"的人创建一个面具.

我更喜欢后者."边缘"意味着:

  • 在第一排上升
  • 在左栏中左转
  • 在最下面一行
  • 在右栏中右转

在这四种情况中的每一种情况中,有3个指数是"无效的".它们在上述矩阵中的位置可以确定如下:

mask = zeros(size(M));
mask(:,1) = 1;
left = find(mask == 1);
mask(:,end) = 2;
right = find(mask == 2);
mask(1,:) = 3;
top = find(mask == 3);
mask(end,:) = 4;
bottom = find(mask == 4);

edgeMask = ones(8,m*n);
edgeMask(1:3, top) = 0;
edgeMask([1 4 6], left) = 0;
edgeMask([3 5 8], right) = 0;
edgeMask(6:8, bottom) = 0;
Run Code Online (Sandbox Code Playgroud)

现在你拥有了所需的一切 - 所有指数和"无效"指数.没有循环.

如果你有野心,你可以把它变成一个单元阵列,但它会比使用完整的数组+掩码慢.例如,如果要查找值的所有邻居的平均值,则可以执行此操作

meanNeighbor = reshape(sum(M(indices).*edgeMask, 1)./sum(edgeMask, 1), size(M));
Run Code Online (Sandbox Code Playgroud)

编辑重新阅读你的问题我看到你想要一个M*N,8维.我的代码是转置的.我相信你可以弄清楚如何适应它......

ATTRIBUTION @Tin帮助建议对上述帖子进行了许多精彩的编辑,但在审核过程中被拒绝了.我不能完全解除这种不公正 - 但我想在此表示感谢.

延伸到不同的地区和多个维度

如果你有一个N维图像矩阵M,你可以找到如下的邻居:

temp = zeros(size(M));
temp(1:3,1:3,1:3) = 1;
temp(2,2,2) = 2;
offsets = find(temp==1) - find(temp==2);
Run Code Online (Sandbox Code Playgroud)

如果您想要一个大小一定半径的区域,您可以这样做

sz = size(M);
[xx yy zz] = meshgrid(1:sz(1), 1:sz(2), 1:sz(3));
center = round(sz/2);
rr = sqrt((xx - center(1)).^2 + (yy - center(2)).^2 + (zz - center(3)).^2);
offsets = find(rr < radius) - find(rr < 0.001);
Run Code Online (Sandbox Code Playgroud)

您可以弄清楚如何处理前面为2D情况显示的边缘问题.

未经测试 - 请注意您是否注意到上述任何问题.