Main Content

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

フリーハンド ROI 編集ツールの作成

この例では、別の ROI オブジェクトを使用してフリーハンド ROI の形状を編集するシンプルなツールの作成方法を説明します。既定では、Freehand ROI オブジェクトには、クリック アンド ドラッグして ROI の形状を調整できる中間点が含まれています。また、境界の任意の部分に中間点を対話形式で追加することもできます。

フリーハンド ROI の形状を編集する別の方法として、多くの一般的なイメージ操作プログラムは '消しゴム' または 'ブラシ' ツールを提供しています。この例では、これらのツールのいずれかを実装し、別の ROI オブジェクトを使用してフリーハンド ROI を編集します。

フリーハンド ROI の作成

セグメンテーション マスクの形状に従うフリーハンド ROI を作成します。このプロセスの詳細は、フリーハンド ROI を使用したセグメンテーション マスクの調整を参照してください。

MRI データをワークスペースに読み取ります。

im = dicomread('knee1.dcm');

MRI イメージをセグメント化し、マスクから最も大きい 2 つの領域を選択します。

segmentedLabels = imsegkmeans(im,3);
boneMask = segmentedLabels==2;
boneMask = bwareafilt(boneMask, 1);

セグメント化された 2 つの領域の境界の座標を取得します。

blocations = bwboundaries(boneMask,'noholes');

bwboundaries によって返される位置を x、y の順に変換します。

pos = blocations{1};
pos = fliplr(pos);

イメージを表示します。

figure
hImage = imshow(im,[]);

セグメント化されたマスク内にフリーハンド ROI を作成します。

hf = drawfreehand('Position', pos);

フリーハンド ROI 編集ツールの作成

円 ROI を作成し、消しゴムまたはブラシの機能を持つ ROI 編集ツールとして使用します (以下のように、いずれかの images.roi.* クラスに少し変更を加えて使用できます)。

he = images.roi.Circle(...
    'Center', [50 50],...
    'Radius', 10,...
    'Parent', gca,...
    'Color','r');

2 つのイベント リスナーを円 ROI に関連付けます。1 つは ROI の移動をリッスンし、もう 1 つは移動の停止をリッスンします。この ROI 移動コールバック関数の例は、その位置をピクセル位置にスナップし、さらに色の変化 (赤/緑) によって、編集操作でターゲット フリーハンド ROI に対する削除または追加が行われるかどうかを示します。エディター ROI が移動を停止したら、エディター ROI に対応するバイナリ マスクとターゲット フリーハンド ROI を作成し、必要な編集を行います。最後に、更新されたマスクを変換してフリーハンド ROI オブジェクトに戻します。リスナーを有効にして、このエディター ROI が移動するたびに応答するようにします。

addlistener(he,'MovingROI', @(varargin)editorROIMoving(he, hf));
addlistener(he,'ROIMoved', @(varargin)editFreehand(hf, he));

フリーハンド ROI の対話形式での編集

次のアニメーションは、追加および削除を行う編集操作を示します。

これは ROI 移動コールバック関数です。この関数は、エディター ROI をピクセル グリッドにスナップし、エディター ROI の色の変化によってフリーハンド ROI への領域の追加やフリーハンド ROI からの領域の削除が行われるかどうかを示します。エディター ROI の中心がターゲット フリーハンド ROI の外側にある場合、操作が削除されます。そうでない場合は、'追加' が行われます。

function editorROIMoving(he, hf)
% Snap editor ROI to grid
he.Position = round(he.Position);

% Check if the circle ROI's center is inside or outside the freehand ROI.
center = he.Center;
isAdd = hf.inROI(center(1), center(2));
if isAdd
    % Green if inside (since we will add to the freehand).
    he.Color = 'g';
else
    % Red otherwise.
    he.Color = 'r';
end
end

これは、ターゲット フリーハンド ROI と交差するエディター ROI の領域を追加または削除する、フリーハンド ROI 編集コールバックです。

function editFreehand(hf, he)

% Create a mask for the target freehand.
tmask = hf.createMask();
[m, n,~] = size(tmask);
% Include the boundary pixel locations
boundaryInd = sub2ind([m,n], hf.Position(:,2), hf.Position(:,1));
tmask(boundaryInd) = true;

% Create a mask from the editor ROI
emask = he.createMask();
boundaryInd = sub2ind([m,n], he.Position(:,2), he.Position(:,1));
emask(boundaryInd) = true;

% Check if center of the editor ROI is inside the target freehand. If you
% use a different editor ROI, ensure to update center computation.
center = he.Center; %
isAdd = hf.inROI(center(1), center(2));
if isAdd
    % Add the editor mask to the freehand mask
    newMask = tmask|emask;
else
    % Delete out the part of the freehand which intersects the editor
    newMask = tmask&~emask;
end

% Update the freehand ROI
perimPos = bwboundaries(newMask, 'noholes');
hf.Position = [perimPos{1}(:,2), perimPos{1}(:,1)];

end

参考

| | | | | | | | |

関連するトピック