セグメンテーションは私の分野ではないので、最善のアプローチが何であるかはわかりません。私が思いついたいくつかのヒューリスティックなアイデアを次に示します。
- 大きすぎたり小さすぎたりするリージョンは破棄します。
椎骨からある程度の大きさが期待できそうです。
regionIdxs = unique(L(:));
regionSizes = accumarray(L(:)+1,1);
をregionSizes
見ると、領域のサイズがピクセル単位で表示されます。
213360
919
887
810
601
695
14551
684
1515
414
749
128
173
26658
必要な領域 (行 2 ~ 6) は、500 ~ 1000 の範囲にあります。サイズが 200 未満または 2000 を超える領域は、おそらく安全に破棄できます。
goodRegionIdx = (regionSizes>200) & (regionSizes<2000);
regionIdxs = regionIdxs(goodRegionIdx);
regionSizes = regionSizes(goodRegionIdx);
- 目的の領域の画像の瞬間を見てください。
分布の共分散行列の固有値は、最も広い方向のサイズとその方向に垂直なサイズを特徴付けます。太いディスク形状を探しているので、大きな固有値と中サイズの固有値が期待できます。
[X,Y] = meshgrid(1:size(L,2),1:size(L,1));
for i = 1:length(regionIdxs)
idx = regionIdxs(i);
region = L==idx;
totalmass = sum(region(:));
Ex(i) = sum( X(1,:).*sum(region,1) ) / totalmass;
Ey(i) = sum( Y(:,1).*sum(region,2)) / totalmass;
Exy(i) = sum(sum( X.*Y.*region )) / totalmass;
Exx(i) = sum(sum( X.*X.*region )) / totalmass;
Eyy(i) = sum(sum( Y.*Y.*region )) / totalmass;
Varx(i) = Exx(i) - Ex(i)^2;
Vary(i) = Eyy(i) - Ey(i)^2;
Varxy(i) = Exy(i) - Ex(i)*Ey(i);
Cov = [Varx(i) Varxy(i); Varxy(i) Vary(i)];
eig(i,:) = eigs(Cov);
end
固有値を見るとeig
:
177.6943 30.8029
142.4484 35.9089
164.6374 26.2081
112.6501 22.7570
138.1674 24.1569
89.8082 58.8964
284.2280 96.9304
83.3226 15.9994
113.3122 33.7410
行 1 ~ 5 のみに関心があります。これらの固有値は最大で 100 ~ 200 の範囲にあり、2 番目の行は 50 未満です。これらを破棄すると、次の領域が得られます。
goodRegionIdx = (eig(:,1)>100) & (eig(:,1)<200) & (eig(:,2)<50);
regionIdxs = regionIdxs(goodRegionIdx);
論理 OR を使用して領域をプロットできます|
。
finalImage = false(size(L));
for i = 1:length(regionIdxs)
finalImage = finalImage | (L==regionIdxs(i) );
end
偽陽性が 1 つあるようです。固有値の比率を見るのも一案eig(:,1)./eig(:,2)
ですが、それも少し問題があるようです。
真の椎骨は直線または曲線に沿って空間的に整列する傾向があるため、RANSACなどの異常値検出を試して、不要な領域を排除することができます。
他に何を提案すればよいかわかりません。良いものと悪いものを区別する別の方法が見つからない場合は、機械学習などのより高度なセグメンテーション方法を検討する必要があるかもしれません. より厳密な前処理方法を持つことは、試してみるべきことの 1 つかもしれません。
それが役立つことを願っています。