通信标签和坐标'点

时间:2017-03-23 10:24:54

标签: matlab matrix coordinates subset matrix-indexing

如何获取矩阵中每个标签的第一个和最后一个出现的坐标(在列主要排序下)?

标签矩阵示例(标签为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的1 st 列包含水平坐标,2 nd 包含垂直坐标,3 rd 列包含标签。每个标签应该有2行。

4 个答案:

答案 0 :(得分:5)

使用for循环,您可以这样做:

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选项,你可以在没有循环的情况下完成...

答案 1 :(得分: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

答案 2 :(得分: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的循环解决方案看起来最好,我的解决方案位于他和Dev-iL之间。对于更大尺寸或更多数量的标签,我的解决方案开始起带头作用。

答案 3 :(得分:0)

您可以使用unique检索矩阵的uniqe值(标签)。

让他们重新启动后,您可以使用find来获取他们的索引。

将矩阵与它放在一起。