在大型矩阵中获取后续ID的最有效方法

时间:2017-01-18 05:24:11

标签: matlab performance matrix image-segmentation watershed

在执行3D CT的分水岭后,我只选择小于某个值且大于另一个的粒子。然而,作为最终输出,我需要一个仅包含连续ID的矩阵。我的实现如下:

% Get unique IDs
grain_id = unique(L);

% Get rid of artefacts
% Compute histogram for each ID
% and compare volume numv with thresholds

% Reject grains smaller or larger than threshold
reject = grain_id(or(numv<vmin,numv>vmax));

% Keep 0s (boundaries) and 1 (voids)
reject = reject(3:end);        

% Rejected become void
L(ismember(L,reject))=1;

% Get number of grains
grain_id = unique(L);
numgrains = numel(grain_id);

% Consecutive IDs
idx = false(size(L));
for i=1:numel(reject)
    idx = L>reject(numel(reject)+1-i);
    L = L-uint16(idx);
end

我有一个1226x1226x3600矩阵,因此性能非常重要。一个循环大约需要。 5秒。它很可能不是实现目标的最有效方式,但目前我没有更好的想法。你呢?

1 个答案:

答案 0 :(得分:1)

如果我正确理解您的问题陈述,这正是third output of the unique函数的用途。它会检查您的数据,对于每个元素,第三个输出提供了一个映射,告诉您相应元素所需的unique输出中的哪个索引。巧合的是,这提供了一个新的整数映射,从1连续到输入中的唯一标签。

但是,这会作为列向量展开的向量返回,而不是向量作为unique的输入,因此您需要reshape将此回复到与输入相同的维度最后。

因此,您需要的只是:

[~,~,id] = unique(L);
id = reshape(id, size(L));

id将是您用作L输入的L大小的矩阵。

这是一个玩具示例,以确保我们在同一页面上:

>> rng(123); L = randi(50, 10, 10)

L =

    35    18    32     5    32     7    34     5    16    36
    15    37    43    22     6    42    30    45    35    50
    12    22    37    22    16    31    32    32    28    18
    28     3    31    25    21    28    34    37    20    39
    36    20    37    22    44    18    43     1    47    30
    22    37    17    16    13    16     5    30    43    35
    50    10    19    22    25    21    39    28    18     8
    35     9    12    45    50    35    13     8     3    20
    25    27    15    48    26    44    10     8    16    13
    20    27    32    26    31    26    29    35    20    18

这里我创建了一个10 x 10的不连续的随机数矩阵。我们可以通过查看此矩阵中的所有唯一数字来看到这一点:

>> unique(L).'

ans =

  Columns 1 through 19

     1     3     5     6     7     8     9    10    12    13    15    16    17    18    19    20    21    22    25

  Columns 20 through 38

    26    27    28    29    30    31    32    34    35    36    37    39    42    43    44    45    47    48    50

注意从1跳到3,或从13跳到15。通过执行上面编写的代码,我们现在得到:

>> id

id =

    28    14    26     3    26     5    27     3    12    29
    11    30    33    18     4    32    24    35    28    38
     9    18    30    18    12    25    26    26    22    14
    22     2    25    19    17    22    27    30    16    31
    29    16    30    18    34    14    33     1    36    24
    18    30    13    12    10    12     3    24    33    28
    38     8    15    18    19    17    31    22    14     6
    28     7     9    35    38    28    10     6     2    16
    19    21    11    37    20    34     8     6    12    10
    16    21    26    20    25    20    23    28    16    14

正如您在此处所见,标签3变为标签2以确保标签是连续的。同样,标签13和15变为10和11,以确保您需要的连续订单等。为了绝对确定,这里是输出中所有唯一值的列表:

>> unique(id).'

ans =

  Columns 1 through 19

     1     2     3     4     5     6     7     8     9    10    11    12    13    14    15    16    17    18    19

  Columns 20 through 38

    20    21    22    23    24    25    26    27    28    29    30    31    32    33    34    35    36    37    38