Basic theory: Extend input array to left-right
, up-down
, one more on each sides of the third dimension
with NaNs
. This would allow us to use a uniform 3x3x3
grid and then later on use those NaNs
to detect elements that go beyond the boundaries of input array and as such are to be discarded.
Code
%// 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])))
How to use: Thus, each slice in the 4th
dimension represent the 27
elements (neighboring plus the element itself) as 3x3x3
array. Hence, neigh26
would be a 3x3x3xN
array where N
is the number of points in point array.
Example: As an example, let's assume some random values in M
and Point
-
M=rand(11,11,11);
point = [
1 1 4;
1 7 1]
On running the earlier code with these inputs, I get something like this -
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