获取矩阵元素的邻居 [英] Get the neighbors of a matrix element
问题描述
我有一个矩阵,我想为每个元素获取其周围元素的索引.所有这些结果都必须按以下方式存储到矩阵中.矩阵的每一行都对应一个矩阵元素,并且该矩阵的每一列都包含s个邻居索引.例如,对于4x4矩阵,我们将获得16x8结果数组.一些矩阵元素没有8个邻居.
I have a matrix and for each element I want to get the index of its surrounding elements. All these results have to be stored into a matrix in the following way. Each row of the matrix corresponds to a matrix element and each of the columns of this matrix contain s the neighbor indexes. For example, for a 4x4 matrix we will get a 16x8 result array. Some of the matrix elements do not have 8 neighbors.
有一个例子,我认为它正在工作,我有什么办法可以避免for循环?:
There is an example, I think it is working, I there any way to avoid for loop?:
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;
推荐答案
给定矩阵M(n,m)的线性索引,您可以说服自己元素M(i,j) = M(i-1, j-1) = M(i-1 + n * (j-2))
的左上邻居
Given the linear indices of a matrix M(n,m), you can convince yourself that the top left neighbor of element M(i,j) = M(i-1, j-1) = M(i-1 + n * (j-2))
在线性索引"空间中,这意味着该元素的偏移量是
In "linear index" space that means the offset of this element is
-n-1
我们在其他所有地方都这样做
Doing this for all other locations, we find
-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),则
Thus you can create a vector offset with the above values (replacing n with the first dimension). For example, if M is (5x4), then
offset = [-6 -5 -4 -1 1 4 5 6];
然后创建所有索引:
indices = bsxfun(@plus, (1:m*n), offset(:));
bsxfun是在这些元素上执行此功能;一个元素具有单例尺寸,而另一个元素则没有,请相应地扩展"的简写形式.您可以对repmat进行相同的操作,但是会创建不必要的中间矩阵(有时可能非常大).
bsxfun is a cool shorthand for "do this function on these elements; where one element has a singleton dimension and the other doesn't, expand accordingly". You could do the same with repmat, but that creates unnecessary intermediate matrices (which can sometimes be very large).
该命令将创建所有8个邻居的索引的(8 x m*n)
索引矩阵,包括那些可能不是真正的邻居的索引...您需要解决的问题.
That command will create a (8 x m*n)
matrix of indices of all 8 neighbors, including ones that may not really be the neighbors... something you need to fix.
几种可能的方法:
- 在开始之前填充矩阵
- 不在乎包装,只去除掉边缘掉的元素
- 为所有边缘"对象创建一个遮罩.
我更喜欢后者. 边缘"表示:
I prefer the latter. "Off the edge" means:
- 上排
- 在左列中左移
- 下一行
- 在右列中右移
在这四种情况中的每种情况下,都有3个无效"索引.它们在上述矩阵中的位置可以确定如下:
In each of these four cases there are 3 indices that are 'invalid'. Their position in the above matrix can be determined as follows:
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;
现在,您拥有了所需的一切-所有索引和无效"索引.没有循环.
Now you have everything you need - all the indices, and the "invalid" ones. Without loops.
如果您有雄心壮志,可以将其变成单元格阵列,但是比使用完整的阵列+面罩要慢.例如,如果要查找某个值的所有邻居的平均值,则可以
If you were feeling ambitious you could turn this into a cell array but it will be slower than using the full array + mask. For example if you want to find the average of all the neighbors of a value, you can do
meanNeighbor = reshape(sum(M(indices).*edgeMask, 1)./sum(edgeMask, 1), size(M));
编辑重新阅读您的问题,我看到您想要一个M * N,8维.我的代码已转置.我相信您可以弄清楚如何适应它...
EDIT re-reading your question I see you wanted a M*N, 8 dimension. My code is transposed. I'm sure you can figure out how to adapt it...
属性 @Tin有益地建议对上述帖子进行许多出色的修改,但在审核过程中被拒绝.我不能完全消除这种不公正-但想在这里表示我的感谢.
ATTRIBUTION @Tin helpfully suggested many great edits to the above post, but they were rejected in the review process. I cannot totally undo that injustice - but would like to record my thanks here.
扩展到不同区域和多个维度
如果您有一个N维图像矩阵M,则可以找到邻居,如下所示:
If you have an N-dimensional image matrix M, you could find the neighbors as follows:
temp = zeros(size(M));
temp(1:3,1:3,1:3) = 1;
temp(2,2,2) = 2;
offsets = find(temp==1) - find(temp==2);
如果您想要一个半径一定的区域,可以这样做
If you want a region that is a certain radius in size, you could do
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情况下沿前面显示的线的边缘问题.
You can probably figure out how to deal with the problem of edges along the lines shown earlier for the 2D case.
未经测试-请检查您是否发现上述问题.
Untested - please see if you notice any problems with the above.
这篇关于获取矩阵元素的邻居的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!