2017-03-23 47 views
1

如何獲取矩陣中每個標籤的第一個和最後一個外觀(在列主要排序下)的座標?對應標籤和座標點

標籤矩陣的實施例(其中,標籤是14):

L = [  
    1 1 1 1 0 0 0 0 
    0 0 0 0 2 2 0 0 
    0 0 0 0 0 0 2 0 
    0 0 0 0 0 0 0 0 
    0 0 0 0 0 3 0 0 
    0 0 0 0 0 0 3 3 
    0 0 0 4 0 0 0 0 
    4 4 4 0 0 0 0 0 
    ]; 

對於上面的例子L,我想獲得像座標的矩陣:

M = [ 
    1 1 1 
    1 4 1 
    2 5 2 
    3 7 2 
    5 6 3 
    6 8 3 
    8 1 4 
    7 4 4 ]; 

在哪裏M的列包含水平座標,並且包含垂直座標,和3 rd列包含標籤。每個標籤應該有2行。

+1

「M」的第一行不應該是「1 1 1」嗎? –

+0

是的你對!,我編輯 –

+0

另外,您正在使用哪個版本的MATLAB? –

回答

5

隨着循環你可以做這樣的:

M=zeros(2*max(L(:)),3); 
for k=1:max(L(:)) 
    [r,c]=find(L==k); 
    s=sortrows([r c],2); 
    M(k*2-1:k*2,:)=[s(1,:) k; s(end,:) k]; 
end 

M = 
1  1  1 
1  4  1 
2  5  2 
3  7  2 
5  6  3 
6  8  3 
8  1  4 
7  4  4 

可能在某種程度上與regionprops選項,你可以不用循環...

+0

我完全同意你的建議,但我不明白爲什麼對於某些點矩陣出現在我[255 255標籤],標籤是好的,但爲什麼255爲x和y? :-o –

+1

沒關係,我找到了原因!我不是一個雙重矩陣,而是一個uint8 ^^。感謝您的幫助:-) –

0

您可以用unique來檢索矩陣的唯一值(您的標籤)。

讓他們回過頭來,您可以使用find來獲得他們的指數。

把你的矩陣放在一起。

+0

另外三個答案提供了一個全面的方法,與這個非常一般的方針相反,我建議或者擴展這個答案也給出一個總體方法,或者如果你認爲它不會增加任何價值根據其他答案,這個問題。 – Adriaan

5

如果你正在尋找一個解決方案矢量,你可以這樣做:

nTags = max(L(:)); 
whois = bsxfun(@eq,L,reshape(1:nTags,1,1,[])); 
% whois = L == reshape(1:nTags,1,1,[]); % >=R2016b syntax. 
[X,Y,Z] = ind2sub(size(whois), find(whois)); 
tmp = find(diff([0; Z; nTags+1])); tmp = reshape([tmp(1:end-1) tmp(2:end)-1].',[],1); 
M = [X(tmp), Y(tmp), repelem(1:nTags,2).']; 

或者極端變量重用:

nTags = max(L(:)); 
Z = bsxfun(@eq,L,reshape(1:nTags,1,1,[])); 
[X,Y,Z] = ind2sub(size(Z), find(Z)); 
Z = find(diff([0; Z; nTags+1])); 
Z = reshape([Z(1:end-1) Z(2:end)-1].',[],1); 
M = [X(Z), Y(Z), repelem(1:nTags,2).']; 

這裏是我的基準測試代碼:

function varargout = b42973322(isGPU,nLabels,lMat) 
if nargin < 3 
    lMat = 1000; 
end 
if nargin < 2 
    nLabels = 20; % if nLabels > intmax('uint8'), Change the type of L to some other uint. 
end 
if nargin < 1 
    isGPU = false; 
end 
%% Create L: 
if isGPU 
    L = sort(gpuArray.randi(nLabels,lMat,lMat,'uint8'),2); 
else 
    L = sort(randi(nLabels,lMat,lMat,'uint8'),2); 
end 
%% Equality test: 
M{3} = DeviL2(L); 
M{2} = DeviL1(L); 
M{1} = Adiel(L); 
assert(isequal(M{1},M{2},M{3})); 
%% Timing: 
% t(3) = timeit(@()DeviL2(L)); % This is always slower, so it's irrelevant. 
t(2) = timeit(@()DeviL1(L)); 
t(1) = timeit(@()Adiel(L)); 
%% Output/Print 
if nargout == 0 
    disp(t); 
else 
    varargout{1} = t; 
end 

end 

function M = Adiel(L) 
    M=[]; 
    for k=1:max(L(:)) 
    [r,c]=find(L==k); 
    s=sortrows([r c],2); 
    M=[M;s(1,:) k; s(end,:) k]; 
    end 
end 

function M = DeviL1(L) 
    nTags = max(L(:)); 
    whois = L == reshape(1:nTags,1,1,[]); % >=R2016b syntax. 
    [X,Y,Z] = ind2sub(size(whois), find(whois)); 
    tmp = find(diff([0; Z; nTags+1])); tmp = reshape([tmp(1:end-1) tmp(2:end)-1].',[],1); 
    M = [X(tmp), Y(tmp), repelem(1:nTags,2).']; 
end 

function M = DeviL2(L) 
    nTags = max(L(:)); 
    Z = L == reshape(1:nTags,1,1,[]); 
    [X,Y,Z] = ind2sub(size(Z), find(Z)); 
    Z = find(diff([0; Z; nTags+1])); 
    Z = reshape([Z(1:end-1) Z(2:end)-1].',[],1); 
    M = [X(Z), Y(Z), repelem(1:nTags,2).']; 
end 
+0

+1爲創造力!但除了複雜的閱讀代碼之外,我不確定速度會更快......有時'bsxfun'會以這種方式變得糟糕。 – Adiel

+0

哇哦,我完全沒有用這種寫法,但謝謝你,它會讓我明白矢量化--D。謝謝! –

+0

謝謝你們! @Adiel謹慎地用一個基準(使用更大的數據集......)來支持這些聲明? :) –

5

我剛剛和accumarray嘗試一下:

R = size(L, 1); 
[rowIndex, colIndex, values] = find(L); % Find nonzero values 
index = (colIndex-1).*R+rowIndex;  % Create a linear index 
labels = unique(values);     % Find unique values 
nLabels = numel(labels); 
minmax = zeros(2, nLabels); 
minmax(1, :) = accumarray(values, index, [nLabels 1], @min); % Collect minima 
minmax(2, :) = accumarray(values, index, [nLabels 1], @max); % Collect maxima 
temp = ceil(minmax(:)/R); 
M = [minmax(:)-R.*(temp-1) temp repelem(labels, 2, 1)]; % Convert index to subscripts 

M = 

    1  1  1 
    1  4  1 
    2  5  2 
    3  7  2 
    5  6  3 
    6  8  3 
    8  1  4 
    7  4  4 

這就是我得到了定時Dev-iL's scriptAdiel's newest code注該號碼由於Adiel的代碼如何使用uint8值作爲索引),因此標籤不能超過127:

     | Adiel | Dev-iL | gnovice 
-----------------------+---------+---------+--------- 
    20 labels, 1000x1000 | 0.0753 | 0.0991 | 0.0889 
20 labels, 10000x10000 | 12.0010 | 10.2207 | 8.7034 
120 labels, 1000x1000 | 0.1924 | 0.3439 | 0.1387 

所以,標籤和(相對)尺寸較小的中等數量,Adiel的循環解決方案看起來像它最好的,我的解決方案之間他和開發金正日的撒謊。對於更大尺寸或更大數量的標籤,我的解決方案開始佔據領先地位。

+0

幹得好!矢量化FTW :) –