我有一个矩阵,对于每个元素,我想得到它周围元素的索引。所有这些结果必须以下列方式存储到矩阵中。矩阵的每一行对应于矩阵元素,并且该矩阵的每列包含邻居索引。例如,对于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;
答案 0 :(得分:6)
给定矩阵M(n,m)的线性索引,你可以说服自己,元素M(i,j) = M(i-1, j-1) = M(i-1 + n * (j-2))
的左上角邻居
在“线性索引”空间中,表示此元素的偏移量为
-n-1
为所有其他地点执行此操作,我们找到了
-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
因此,您可以使用上述值创建向量偏移量(将n替换为第一个维度)。例如,如果M是(5x4),那么
offset = [-6 -5 -4 -1 1 4 5 6];
然后创建所有索引:
indices = bsxfun(@plus, (1:m*n), offset(:));
bsxfun是“对这些元素执行此功能的一个很酷的简写;其中一个元素具有单个维度而另一个元素没有,相应地扩展”。您可以使用repmat执行相同操作,但这会创建不必要的中间矩阵(有时可能非常大)。
该命令将为所有8个邻居创建一个(8 x m*n)
索引矩阵,包括那些可能不是真正邻居的索引...你需要修复的东西。
几种可能的方法:
我更喜欢后者。 “离开边缘”意味着:
在这四种情况中,有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;
现在你拥有了所需的一切 - 所有指数和“无效”指数。没有循环。
如果你有野心,你可以把它变成一个单元阵列,但它会比使用完整的数组+掩码慢。例如,如果要查找值的所有邻居的平均值,可以执行
meanNeighbor = reshape(sum(M(indices).*edgeMask, 1)./sum(edgeMask, 1), size(M));
编辑重新阅读你的问题我看到你想要一个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);
如果你想要一个大小一定半径的区域,你可以做
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);
你可以弄清楚如何处理前面为2D情况显示的边缘问题。
未经测试 - 请注意您是否发现上述任何问题。