2

各セルに単一の画像セグメントが存在するように、流域変換出力からトレーニング画像を作成したいと考えています。これを最も効率的な方法で行うにはどうすればよいですか?

詳細:L流域セグメンテーションの出力であると仮定します:

L =

 1     1     2
 1     0     2
 1     2     2
 0     0     2
  • 0 は背景です
  • 1 はセグメント番号 1、2 はセグメント番号 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

次の1つのライナーで実行できます;-)

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

効率的な方法を求められたので、次の解決策がうまく機能すると思います。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 に答える
1

ここにクリーンで短い解決策を1 つ書きましたが、Lincoln のものより速いか遅いかはわかりません。を使ってみてください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は、ゼロのみを含むすべての行/列を削除します。つまり、中間の行/列も削除されるため、1 つの領域が接続されていないと機能しません。しかし、地域が完全に接続されている場合、流域(IMO)は同じ地域インデックス(たとえば、地域1の場合は1)のみを返すため、これはあなたの場合には起こらないと思います。


Speedtest: まず、L と my 関数を定義します。今テスト:

>> 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.

これで、このテスト スニペットをコピーして変更し、Lincolns の計算速度も確認できます。

EDIT2: Lincolns ソリューションを次のように定義して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 に答える