5

我有一個3D圖像,分爲連續區域,其中每個體素具有相同的值。分配給該區域的值對該區域是唯一的,並用作標籤。下面的例子描述了圖像與2D情況:MATLAB在3D圖像中識別相鄰區域

 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 

我想創建描述這些區域之間adjaciency的曲線圖。在上述情況下,這將是:

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是我想避免的瓶頸。

謝謝你的幫助!

+0

MEX文件?快速照明.... – kkuilla

+1

感謝您的建議。不過,似乎imdilate已經在MEX文件中實現了! – Lisa

回答

3

我想出了一個解決方案,它是Divakarteng的答案的組合,以及我自己的修改,並將其推廣到2D或3D情況。

爲了使之更有效率,我也許應該預先分配的rc,但在此期間,這是運行時:

  • 有關尺寸117x159x1263D圖像和32000獨立的區域:0.79s
  • 對於上述2D例如: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; 

感謝您的幫助!

+0

偉大的解決方案。稀疏矩陣是要走的路! – teng

+1

謝謝!稀疏矩陣實際上是一個給定的,我不能以任何其他方式存儲這種大小的圖表 - 爲了清晰起見,我將其留在了最初的文章中,因爲它對於該方法並不重要。 – Lisa

+0

已經爲此+1!令人興奮的東西真的。獲得3D結果! :) – Divakar

2

以下是我的嘗試。

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 
+0

非常感謝!我會嘗試一下並報告。 – Lisa

+1

滕,我用你的解決方案的一部分爲最終的工作版本,謝謝!我將我的版本和運行時報告放在一個單獨的答案中,如果感興趣,請查看它。 – Lisa

2

嘗試了這一點 -

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; 

如果你的作品,與我們分享的運行時間作爲比較?很想看看咖啡是否會比半小時更快釀造出來!

+0

謝謝!似乎工作,但我仍然試圖弄清楚究竟如何:)我會報告運行時! – Lisa

+0

聰明,稍微複雜!我組合了你的部分,@teng和我自己的修改,並將其擴展到一般的2D或3D情況,我將發佈解決方案並運行時間(用於高維3D圖像的'0.79s!)一個單獨的答案! – Lisa

+1

'bsxfun'確實帶來了「複雜的性質」!哇,30分鐘到0.79秒!? – Divakar

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不匹配,並一直延伸到較低的邊界。