ドキュメンテーション

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

フリーハンド ROI のサブサンプリングまたは簡略化

この例では、フリーハンド ROI オブジェクト内の点をサブサンプリングする、つまり点の数を削減する方法を説明します。

はじめに

関数 drawfreehand は、滑らかな外観を持つフリーハンド関心領域 (ROI) を作成します。しかし実際には、エッジは境界全体に分布する離散点で構成されています。フリーハンド ROI の外観の滑らかさに影響する要因は、1) 点の密度、および 2) フリーハンド ROI オブジェクトの Smoothing プロパティの 2 つです。

対話形式で描画する際には、マウスの動きによって点の密度が決まります。大きくて複雑な ROI の場合、使用される点の数がかなり多くなることがあります。

Smoothing プロパティは、境界の外観を制御します。既定では、フリーハンド オブジェクトにはシグマ値が 1 でフィルター サイズが 5 のガウス平滑化カーネルが使用されます。この値を変更すると境界の外観のみが変更され、オブジェクトの基となる Position プロパティは変更されません。

点の既定の密度

点の密度を低下させると、ROI データの格納に必要な領域を減らすのに役立ちます。また、これらの点の数に依存する計算を高速化できます。点の密度を低下させる方法の 1 つは、点をサブサンプリングすることです。たとえば、点を 1 つおきに選択します。

マスクを ROI に変換して、フリーハンド ROI のサンプルを作成します。それぞれの境界ピクセルが ROI の 1 つの点に対応するため、ROI は高密度になります。

im = imread('football.jpg');
bw = im(:,:,1)>200;
bw = bwareafilt(bw, 1);
bloc = bwboundaries(bw,'noholes');
roipos = fliplr(bloc{1});
imshow(im);
hfh = drawfreehand('Position', roipos);

密度を可視化するには、ROI 内のそれぞれの位置を中間点に変換します。

hfh.Waypoints(:) = true;

title('Original density');
snapnow

% Zoom in
xlim([80 200]);
ylim([70 160]);
snapnow

位置の点のサブサンプリング

フリーハンド ROI の Position プロパティを構成する点をサブサンプリングします。フリーハンド ROI は高密度であるため、サブサンプリングによって、忠実度を損なうことなくサイズを大幅に小さくできます。初期の完全な (細かな) 位置をクエリします。

fpos = hfh.Position;

位置を 4 つおきに選択して、サブサンプリングします。

cpos = fpos(1:2:end,:);

ROI を更新します。

hfh.Position = cpos;

すべての点を中間点に変換します。

hfh.Waypoints(:) = true;
title('Simple Subsample (factor of 4)');
snapnow

サブサンプリング - 変化率の使用

点のサブサンプリングには、"曲率" が低い点から選択的に点の削除を開始する方法がより適しています。ROI の曲線に近い部分ではなく、ややまっすぐ部分にある点を削除する方が理にかなっています。曲率値を定義する簡単な方法の 1 つは、位置の変化率を測定することです。

変化率を測定します。最初の点の近傍点は最後の点です。

dfpos = diff([fpos(end,:); fpos]);

シンプルなローパス フィルターに基づいて曲率の一時的な測定値を定義します。

cm = sum(abs(conv2(dfpos, ones(3,2),'same')),2);

曲率で並べ替えます。

[~, cmInds] = sort(cm);

曲率値が低い 3/4 の点を選択し、ROI から削除します。

numPointsToCull = round(0.25*size(fpos,1));

これらの位置を削除します。

cpos = fpos;
cpos(cmInds(1:numPointsToCull),:) = [];

ROI を更新し、すべての中間点を有効にして影響を確認します。

hfh.Position = cpos;
hfh.Waypoints(:) = true;
title('Curvature Based Subsample (factor of 4)');
snapnow

対話型のサブサンプリング

サブサンプリングを行うもう 1 つの方法は、イベントを使用してこのプロセスを容易にすることです。まず、フリーハンド ROI で使用する点の数を対話形式で変更するリスナーを作成します。フリーハンド オブジェクトの UserData プロパティを使用して、完全な解像度の Position データとその曲率値をキャッシュします。次に、新しい uimenu を作成し、それをフリーハンド オブジェクトの UIContextMenu の親にすることによって、カスタム コンテキスト メニューを ROI オブジェクトに追加します。このメニュー オプションを使用して、ROI を "ファイナライズ" することで、一時的なキャッシュが削除されます。

% Restore original ROI, and cache the original position along with its
% curvature measure in UserData
hfh.Position = fpos;
hfh.Waypoints(:) = true;
hfh.UserData.fpos = fpos;
hfh.UserData.cmInds = cmInds;

マウスのスクロールに応答します。

h = gcf;
h.WindowScrollWheelFcn = @(h, evt) changeSampleDensity(hfh, evt);

コンテキスト メニューを追加して ROI をファイナライズし、必要なクリーンアップを実行します。

uimenu(hfh.UIContextMenu, 'Text','Finalize',...
    'MenuSelectedFcn', @(varargin)finalize(hfh));

title('Scroll to change density interactively');

対話型のサブサンプリングのアニメーション

コールバック関数 - マウスのスクロールに基づくサンプルの密度の変更

この関数はスクロール操作に対して呼び出されます。上にスクロールすると密度が上昇し、下にスクロールすると密度が低下します。これにより、保持する点の数を対話形式で選択できます。

function changeSampleDensity(hfh, evt)
currentNumPoints = size(hfh.Position,1);
% 5% of original for each scroll.
numChangePoints = round(size(hfh.UserData.fpos,1)*0.05);

newNumPoints = currentNumPoints + evt.VerticalScrollCount*numChangePoints;
newNumPoints = max(3, min(size(hfh.UserData.fpos,1), newNumPoints));

numPointsToCull = size(hfh.UserData.fpos,1) - newNumPoints;

% Pick the full resolution cached position
cpos = hfh.UserData.fpos;
cmInds = hfh.UserData.cmInds;
% cull that to get the coarse position
cpos(cmInds(1:numPointsToCull),:) = [];

% Update the ROI and show all the points used
hfh.Position = cpos;
hfh.Waypoints(:) = true;
end

コールバック関数 - フリーハンド ROI のファイナライズ

フリーハンド ROI を削除して、サブサンプリングされた点を使用して新しいフリーハンド ROI を作成し、領域に保存します。

function finalize(hfh)
h = ancestor(hfh, 'figure');
% Reset the mouse scroll wheel callback
h.WindowScrollWheelFcn = [];
% Save finalized set of points
pos = hfh.Position;
% Delete and create a new Freehand ROI
delete(hfh);
drawfreehand(gca, 'Position', pos);
end

参考

| | |

関連するトピック