Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

ポリラインを使用した角度測定ツールの作成

この例では、ポリライン ROI の 3 つの頂点がなす角度を表示する対話型ツールの作成方法を説明します。

角度を変更するには、ポリラインの頂点をクリックしてドラッグします。ROI が移動すると、MovingROI という名前のイベントがブロードキャストされます。このイベントのリスナー、およびイベントの発生時に実行するコールバック関数を追加すると、このツールによって角度の変化をリアル タイムで測定して表示することができます。

イメージとポリライン ROI の表示

イメージを読み取って表示します。

im = imread('gantrycrane.png');
imshow(im)

イメージのサイズを取得します。

[y,x,~] = size(im);

イメージの中心の座標を取得します。この例では、角度測定ツールの頂点をイメージの中心に配置します。

midy = ceil(y/2);
midx = ceil(x/2);

ポリライン ROI の最初の点の座標を指定します。この例では、ポリラインの最初の点をイメージの中心の真上に配置します。

firstx = midx;
firsty = midy - ceil(y/4);

ポリライン ROI の 3 番目の点の座標を指定します。この例では、ポリラインの 3 番目の点をイメージの中心のまっすぐ右に配置します。

lastx = midx + ceil(x/4);
lasty = midy;

既定のメニューを置き換える空のコンテキスト メニューを作成します。

c = uicontextmenu;

イメージ上に赤いポリラインを描画します。3 つの頂点の座標を指定し、ポリラインを対話形式で操作するための説明が付いたラベルを追加します。

h = drawpolyline("Parent",gca, ...
    "Position",[firstx,firsty;midx,midy;lastx,lasty], ...
    "Label","Modify angle to begin...", ...
    "Color",[0.8,0.2,0.2], ...
    "UIContextMenu",c);

ROI の移動をリッスンするリスナーを追加します。リスナーによって移動が検出されると、カスタム コールバック関数 updateAngle が呼び出されます。このカスタム関数は、「コールバック関数を使用した角度ラベルの更新」の節で定義されています。

addlistener(h,'MovingROI',@(src,evt) updateAngle(src,evt));

ポリライン ROI は、対話形式による頂点の追加と削除もサポートしています。ただし、角度測定ツールでは常に 3 つの頂点が必要であるため、ROI の頂点の追加や削除は望ましい操作ではありません。頂点の追加または削除をリッスンするリスナーを追加します。頂点の数を変更しようとすると、該当するリスナーによってカスタム コールバック関数が呼び出されて変更が中断されます。カスタム関数 storePositionInUserData および recallPositionInUserData は、「コールバック関数を使用した頂点の追加または削除の防止」の節で定義されています。

addlistener(h,'AddingVertex',@(src,evt) storePositionInUserData(src,evt));
addlistener(h,'VertexAdded',@(src,evt) recallPositionInUserData(src,evt));
addlistener(h,'DeletingVertex',@(src,evt) storePositionInUserData(src,evt));
addlistener(h,'VertexDeleted',@(src,evt) recallPositionInUserData(src,evt));

コールバック関数を使用した角度ラベルの更新

ポリライン ROI が動いたときに実行するコールバック関数を定義します。この関数は、3 つの頂点の現在の位置を取得し、それらの頂点がなす角度を度単位で計算し、ラベルを更新して現在の回転角度を表示します。

function updateAngle(src,evt)
    % Get the current position
    p = evt.CurrentPosition;

    % Find the angle
    v1 = [p(1,1)-p(2,1), p(1,2)-p(2,2)];
    v2 = [p(3,1)-p(2,1), p(3,2)-p(2,2)];
    theta = acos(dot(v1,v2)/(norm(v1)*norm(v2)));

    % Convert the angle to degrees
    angleDegrees = (theta * (180/pi));

    % Update the label to display the angle
    src.Label = sprintf('(%1.0f) degrees',angleDegrees);
end

コールバック関数を使用した頂点の追加または削除の防止

リスナーが 'AddingVertex' イベントまたは 'DeletingVertex' イベントを検出したときに実行されるコールバック関数を定義します。これらのイベントは、対象の頂点がポリラインに追加されるかポリラインから削除される直前に発生します。ポリラインの 3 つの頂点の現在の位置を UserData プロパティに格納します。

function storePositionInUserData(src,~)
    src.UserData = src.Position;
end

リスナーが 'VertexAdded' イベントまたは 'VertexDeleted' イベントを検出したときに実行されるコールバック関数を定義します。これらのイベントは、対象の頂点がポリラインに追加されるかポリラインから削除された直後に発生します。UserData プロパティに格納されているポリラインの 3 つの頂点の位置のセットを復元します。

function recallPositionInUserData(src,~)
    src.Position = src.UserData;
end

参考

| |

関連するトピック