[英]MATLAB identify adjacient regions in 3D image
我有一个3D图像,分为连续区域,每个体素具有相同的值。 分配给该区域的值对于该区域是唯一的,并用作标签。 下面的示例图片描述了2D案例:
1 1 1 1 2 2 2
1 1 1 2 2 2 3
Im = 1 4 1 2 2 3 3
4 4 4 4 3 3 3
4 4 4 4 3 3 3
我想创建一个描述这些区域之间相互关系的图表。 在上面的例子中,这将是:
0 1 0 1
A = 1 0 1 1
0 1 0 1
1 1 1 0
我正在寻找一个快速的解决方案来在MATLAB中为大型3D图像执行此操作。 我想出了遍历所有区域,需要一个解决方案0.05s
每次迭代-不幸的是,这将花费超过一个半小时的图像以32'000地区。 现在有人有更优雅的方式吗? 我发布了下面的当前算法:
labels = unique(Im); % assuming labels go continuously from 1 to N
A = zeros(labels);
for ii=labels
% border mask to find neighbourhood
dil = imdilate( Im==ii, ones(3,3,3) );
border = dil - (Im==ii);
neighLabels = unique( Im(border>0) );
A(ii,neighLabels) = 1;
end
imdilate
是我想避免的瓶颈。
谢谢您的帮助!
我提出了一个解决方案,它结合了Divakar和Teng的答案,以及我自己的修改,并将其推广到2D或3D案例。
为了提高效率,我应该预先分配r
和c
,但在此期间,这是运行时:
117x159x126
和32000
单独区域的3D图像: 0.79s
0.004671s
用此溶液, 0.002136s
与Divakar溶液, 0.03995s
与腾的溶液。 不过,我没有尝试将胜利者(Divakar)扩展到3D案例!
noDims = length(size(Im));
validim = ones(size(Im))>0;
labels = unique(Im);
if noDims == 3
Im = padarray(Im,[1 1 1],'replicate', 'post');
shifts = {[-1 0 0] [0 -1 0] [0 0 -1]};
elseif noDims == 2
Im = padarray(Im,[1 1],'replicate', 'post');
shifts = {[-1 0] [0 -1]};
end
% get value of the neighbors for each pixel
% by shifting the image in each direction
r=[]; c=[];
for i = 1:numel(shifts)
tmp = circshift(Im,shifts{i});
r = [r ; Im(validim)];
c = [c ; tmp(validim)];
end
A = sparse(r,c,ones(size(r)), numel(labels), numel(labels) );
% make symmetric, delete diagonal
A = (A+A')>0;
A(1:size(A,1)+1:end)=0;
谢谢您的帮助!
以下是我的尝试。
Im = [1 1 1 1 2 2 2;
1 1 1 2 2 2 3;
1 4 1 2 2 3 3;
4 4 4 4 3 3 3;
4 4 4 4 3 3 3];
% mark the borders
validim = zeros(size(Im));
validim(2:end-1,2:end-1) = 1;
% get value of the 4-neighbors for each pixel
% by shifting the images 4 times in each direction
numNeighbors = 4;
adj = zeros([prod(size(Im)),numNeighbors]);
shifts = {[0 1] [0 -1] [1 0] [-1 0]};
for i = 1:numNeighbors
tmp = circshift(Im,shifts{i});
tmp(validim == 0) = nan;
adj(:,i) = tmp(:);
end
% mark neighbors where it does not eq Im
imDuplicates = repmat(Im(:),[1 numNeighbors]);
nonequals = adj ~= imDuplicates;
% neglect the border
nonequals(isnan(adj)) = 0;
% get these neighbor values and the corresponding Im value
compared = [imDuplicates(nonequals == 1) adj(nonequals == 1)];
% construct your 'A' % possibly could be more optimized here.
labels = unique(Im);
A = zeros(numel(labels));
for i = 1:size(compared,1)
A(compared(i,1),compared(i,2)) = 1;
end
试试这个 -
Im = padarray(Im,[1 1],'replicate');
labels = unique(Im);
box1 = [-size(Im,1)-1 -size(Im,1) -size(Im,1)+1 -1 1 size(Im,1)-1 size(Im,1) size(Im,1)+1];
mat1 = NaN(numel(labels),numel(labels));
for k2=1:numel(labels)
a1 = find(Im==k2);
for k1=1:numel(labels)
a2 = find(Im==k1);
t1 = bsxfun(@plus,a1,box1);
t2 = bsxfun(@eq,t1,permute(a2,[3 2 1]));
mat1(k2,k1) = any(t2(:));
end
end
mat1(1:size(mat1,1)+1:end)=0;
如果它适合您,请与我们分享运行时作为比较? 很想看看咖啡是否超过半小时酿造!
@Lisa你的推理是优雅的,虽然它显然给边缘标签的错误答案。 试试这个简单的标签矩阵:
Im =
1 2 2
3 3 3
3 4 4
根据您的代码生成的邻接矩阵是:
A =
0 1 1 0
1 0 1 1
1 1 0 1
0 1 1 0
声称标签“2”和“4”之间的邻接:显然是错误的。 发生这种情况的原因很简单,因为您正在阅读基于“validim”索引的填充Im标签,这些索引现在与新的Im不匹配并且一直向下到下边界。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.