2

我想从分水岭变换输出中制作训练图像,以便在每个单元格中都有一个图像片段。我怎样才能以最有效的方式做到这一点?

更多细节:假设L是分水岭分割的输出:

L =

 1     1     2
 1     0     2
 1     2     2
 0     0     2
  • 0 是背景
  • 1 是段号 1,2 是段号 2,依此类推。

我想用两个图像构建一个单元格,每个图像都包含一个段:

cell1=

1     1 
1     0 
1     0 

cell2=

0     2 
0     2 
2     2
0     2 

我知道我可以使用一些 for 循环和 if 条件来做到这一点,但是我需要一个具有最佳计算成本的解决方案。也许 Matlab 有这个任务的内置函数?

4

3 回答 3

2

可以通过以下一个衬里来完成;-)

U = regionprops(L, 'Image')

解决方案之间的比较(L 是 1200x1600 像素的图像):

>> tic;
for index=1:100
U = regionprops(L, 'Image');
end
toc;

经过的时间是20.138794秒。

>>tic;
for index=1:100
N = max(L(:)); %//number of segments
C = cell(N,1); %//create Cell Array
[height, width] = size(L); %//get dimensions of image

for target=1:N %//for each segment..

    %//search column-wise to get first and last column index
    col_start = ceil(find(L==target,1)/height);
    col_end = ceil(find(L==target,1,'last')/height);

    %//search row-wise to get first and last row index
    row_start = ceil(find(L.'==target,1)/width);
    row_end = ceil(find(L.'==target,1,'last')/width);

    T = L(row_start:row_end , col_start:col_end); %//image segment of bounding box
    T(T~=target) = 0; %//set non-targets to 0

    C{target} = T; %//add to cell array

end;
end
toc;

经过的时间是300.744868秒。

>> tic;
for index=1:100
u = unique(L(:));
B = arrayfun(@(x) removePadding(L, x)*2, u(2:end), 'UniformOutput', false);
end
toc;

经过的时间是182.193148秒。

于 2016-05-10T11:08:31.297 回答
1

我在这里写了一个干净/简短的解决方案,但我不知道它是否比林肯的解决方案更快或更慢。只需尝试使用tic/toc.

function A = removePadding(L, x) 
  A = (L==x); 
  A(all(A == 0, 2), :)=[]; 
  A(:, all(A == 0, 1))=[]; 
end

L = [1 1 2;1 0 2; 1 2 2; 0 0 2];
u = unique(L(:))
arrayfun(@(x) removePadding(L, x)*2, u(2:end), 'UniformOutput', false)

将输出:

ans =
{
  [1,1] =

     1   1
     1   0
     1   0

  [2,1] =

     0   2
     0   2
     2   2
     0   2

}

注意:该函数removePadding将删除所有仅包含零的行/列。这意味着如果一个区域不连接,它将无法工作,因为中间行/列也将被删除。但我认为这不会发生在你的情况下,因为如果区域完全连接,分水岭 (IMO) 只会返回相同的区域索引(例如区域 1 为 1)。


Speedtest:首先,定义了L和我的函数。现在测试:

>> tic; 
for i = 1:1000
  u = unique(L(:));
  B = arrayfun(@(x) removePadding(L, x)*2, u(2:end), 'UniformOutput', false);
end
>> toc
Elapsed time is 4.89563 seconds.

现在您可以复制此测试片段并对其进行修改以检查林肯计算的速度。

EDIT2:我将林肯解决方案定义为C = myFun(L),然后再次运行速度测试:

>> tic;
>> for i = 1:1000
  B = myFun(L);
end
>> toc
Elapsed time is 1.01026 seconds.

似乎要快得多:-) 即使使用 for 循环。

于 2016-05-10T10:54:59.230 回答
1

既然您要求一种有效的方法,我认为以下解决方案应该可以很好地工作。尽管它使用了 1 个 for 循环,但它只循环了分水岭转换输出中的N时间,这对于图像分割通常非常低(对于您的示例,N=2)。Nnumber of segments

N = max(L(:)); %//number of segments
C = cell(N,1); %//create Cell Array
[height, width] = size(L); %//get dimensions of image

for target=1:N %//for each segment..

    %//search column-wise to get first and last column index
    col_start = ceil(find(L==target,1)/height);
    col_end = ceil(find(L==target,1,'last')/height);

    %//search row-wise to get first and last row index
    row_start = ceil(find(L.'==target,1)/width);
    row_end = ceil(find(L.'==target,1,'last')/width);

    T = L(row_start:row_end , col_start:col_end); %//image segment of bounding box
    T(T~=target) = 0; %//set non-targets to 0

    C{target} = T; %//add to cell array

end
于 2016-05-10T10:51:12.197 回答