4

好吧,我不知道如何用标题来描述我的问题,我希望我得到的那个是正确的。

我有一个矩阵(M在下面的示例中),它是一个 3D 图像,在这种情况下,由11x11x11体素组成(我将其设为逻辑只是为了方便,大小也只是一个示例)。

在我的代码中,我需要到达一些体素的 26 个邻居,为此我使用了一些花哨的线性索引: http: //www.mathworks.com/matlabcentral/answers/86900-how-to-find-all -n维矩阵中元素的邻居

问题是,如果尝试访问某些超出范围的值point的“边界” ,那将产生错误。M

为了解决这个问题,一个好的方法是M在每个维度上创建一个边界,使其大小为 +2,并用零填充,但是我真的想避免更改M,因为我的代码比这个例子。

我找不到任何方法,我有点卡在这里。有什么建议吗?

编辑: @Dan 回答有效,但是我想看看是否有使用这种线性索引方法的可能解决方案。

% Example data
M=round(randn(11,11,11))~=0;

% Fancy way of storing 26 neigh indices for good accesing 
s=size(M);
N=length(s);
[c1{1:N}]=ndgrid(1:3);
c2(1:N)={2};
neigh26=sub2ind(s,c1{:}) - sub2ind(s,c2{:});

point=[5 1 6];

% This will work unless the point is in the boundary (like in this example)
neighbours=M(sub2ind(s,point(1),point(2),point(3))+neigh26) 
4

2 回答 2

3

那线性索引的东西是必不可少的吗?因为处理边界条件非常容易,所以您使用下标索引,min并且max像这样:

p = [5, 1, 6];

neighbourhood = M(max(1,p(1)-1)):min(p(1)+1,end),
                  max(1,p(2)-1)):min(p(2)+1,end),
                  max(1,p(3)-1)):min(p(3)+1,end))

%// Get rid of the point it self (i.e. the center)
neighbours = neighbourhood([1:13, 15:end])

这样,如果您想要更广泛的社区,您也可以轻松地概括这一点:

p = [5, 1, 6];
n = 2;
neighbourhood = M(max(1,p(1)-n)):min(p(1)+n,end),
                  max(1,p(2)-n)):min(p(2)+n,end),
                  max(1,p(3)-n)):min(p(3)+n,end))

%// Get rid of the point it self (i.e. the center)
mid = ceil(numel(neigbourhood)/2);
neighbours = neighbourhood([1:mid-2, mid+1:end])

或者如果您喜欢保持立方体形状,那么也许:

neighbours = neighbourhood;
neighbours(mid) = NaN;

如果您想在代码中多次使用它,最好将其重构为仅返回索引的 m 文件函数:

function ind = getNeighbours(M,p,n)
    M = zeros(size(M));
    M(max(1,p(1)-n)):min(p(1)+n,end), max(1,p(2)-n)):min(p(2)+n,end), max(1,p(3)-n)):min(p(3)+n,end)) = 1;
    M(p(1), p(2), p(3)) = 0;
    ind = find(M);
end
于 2014-10-17T11:36:09.593 回答
1

基本理论:将输入数组扩展为left-right, up-down, one more on each sides of the third dimensionNaNs这将允许我们使用统一的3x3x3网格,然后使用它们NaNs来检测超出输入数组边界的元素,因此将被丢弃。

代码

%// Initializations
sz_ext = size(M)+2; %// Get size of padded/extended input 3D array
M_ext = NaN(sz_ext); %// Initialize extended array
M_ext(2:end-1,2:end-1,2:end-1) = M; %// Insert values from M into it

%// Important stuff here : Calculate linear offset indices within one 3D slice
%// then for neighboring 3D slices too
offset2D = bsxfun(@plus,[-1:1]',[-1:1]*sz_ext(1)); %//'
offset3D = bsxfun(@plus,offset2D,permute([-1:1]*sz_ext(1)*sz_ext(2),[1 3 2]));

%// Get linear indices for all points
points_linear_idx = sub2ind(size(M_ext),point(:,1)+1,point(:,2)+1,point(:,3)+1);
%// Linear indices for all neighboring elements for all points; index into M_ext
neigh26 = M_ext(bsxfun(@plus,offset3D,permute(points_linear_idx,[4 3 2 1])))

如何使用:4th因此,维度中的每个切片将27元素(相邻元素加上元素本身)表示为3x3x3数组。因此,neigh26将是一个3x3x3xN数组,其中N是点数组中的点数。

示例:作为示例,让我们假设MPoint-

M=rand(11,11,11);
point = [
    1 1 4;
    1 7 1]

在使用这些输入运行较早的代码时,我得到这样的结果 -

neigh26(:,:,1,1) =
       NaN       NaN       NaN
       NaN    0.5859    0.4917
       NaN    0.6733    0.6688
neigh26(:,:,2,1) =
       NaN       NaN       NaN
       NaN    0.0663    0.5544
       NaN    0.3440    0.3664
neigh26(:,:,3,1) =
       NaN       NaN       NaN
       NaN    0.3555    0.1257
       NaN    0.4424    0.9577
neigh26(:,:,1,2) =
   NaN   NaN   NaN
   NaN   NaN   NaN
   NaN   NaN   NaN
neigh26(:,:,2,2) =
       NaN       NaN       NaN
    0.7708    0.3712    0.2866
    0.7088    0.3743    0.2326
neigh26(:,:,3,2) =
       NaN       NaN       NaN
    0.4938    0.5051    0.9416
    0.1966    0.0213    0.8036
于 2014-10-17T16:44:56.497 回答