Performance MATLAB识别三维图像中的邻接区域

Performance MATLAB识别三维图像中的邻接区域,performance,matlab,image-processing,vectorization,adjacency-matrix,Performance,Matlab,Image Processing,Vectorization,Adjacency Matrix,我有一个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 我正在

我有一个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.05秒
——不幸的是,对于一个有32000个区域的图像,这将需要半个多小时。现在有人有更优雅的方法吗?我在下面发布当前算法:

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
imdeflate
是我想要避免的瓶颈

谢谢你的帮助

下面是我的尝试

 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;

如果它对您有效,请与我们分享运行时作为比较?我很想看看咖啡煮得是否快于半小时

我提出了一个解决方案,它结合了’和’的答案,以及我自己的修改,并将其推广到2D或3D案例

为了提高效率,我可能应该预先分配
r
c
,但同时,这是运行时:

  • 对于尺寸
    117x159x126
    32000
    独立区域的3D图像:
    0.79s
  • 对于上述2D示例:
    0.004671s
    使用此解决方案,
    0.002136s
    使用Divakar的解决方案,
    0.03995s
    使用teng的解决方案
不过,我还没有尝试过将胜利者(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;
谢谢你的帮助

@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不匹配,一直向下延伸到下边框。

MEX文件?快速照明…谢谢你的建议。不过,似乎IMDigital已经在MEX文件中实现了!谢谢似乎有效,但我仍在努力弄清楚具体的方法:)我将报告运行时!聪明,有点复杂!我结合了您的部分内容、@teng和我自己的修改,并将其扩展到一般的2D或3D情况,我将在单独的回答中发布解决方案和运行时间(
0.79s
用于高维3D图像!)
bsxfun
无疑带来了“错综复杂的本质”!哇,30分钟到0.79秒!?我想做30000次扩张手术并不是最聪明的方法:)@Lisa这正是问题所在!关于
bsxfun
,它是一种内存密集型方法,很可能使用JIT(即时)编译,这正是它性能良好的原因。但是由于同样的原因,如果你向它提供大量数据,它可能会耗尽内存。这就是为什么我急切地等待3D结果:)非常感谢!我将试用并报告。teng,我使用了您的部分解决方案作为最终工作版本,谢谢!我将我的版本和运行时报告放在一个单独的答案中,如果您感兴趣,请查看。很好的解决方案。稀疏矩阵就是要走的路!谢谢稀疏矩阵实际上是给定的,我不能以任何其他方式存储这样大小的图-为了清晰起见,我在最初的帖子中遗漏了它,因为它对该方法并不重要。已经+1了!令人兴奋的事情真的。也可以获得3D结果!:)我不太确定我是否理解正确:)你是要求我报告3D案例吗?第一个结果实际上是一个3D结果(我编辑了这篇文章,让它更清晰一些)。@Lisa所以,我想还是坚持你这里的3D案例代码吧。但别忘了
bsxfun
,它可能会派上用场的!:)