Используйте ломаную линию, чтобы создать угловой инструмент измерения

В этом примере показано, как создать интерактивный инструмент, который отображает угол между тремя вершинами в полилинейном ROI.

Можно изменить угол путем перетаскивания полилинейных вершин. Когда 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. Этот пример помещает третью точку в ломаную линию непосредственно справа от центра изображения.

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

Создайте пустое контекстное меню, чтобы заменить меню по умолчанию.

c = uicontextmenu;

Чертите ломаную линию красного цвета по изображению. Задайте координаты этих трех вершин и добавьте метку с инструкциями взаимодействовать с ломаной линией.

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. Эта пользовательская функция задана в разделе "Update Angle Label Using Callback Function".

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

Полилинейные ROI также поддерживают интерактивное сложение и удаление вершин. Однако угловой инструмент измерения требует точно трех вершин в любое время, таким образом, сложение и удаление вершин являются нежелательными взаимодействиями с ROI. Добавьте прослушиватели, которые прислушиваются к сложению или удалению вершин. Когда вы пытаетесь изменить количество вершин, соответствующий прослушиватель вызывает пользовательскую функцию обратного вызова, чтобы подавить изменение. Эти пользовательские функции, storePositionInUserData и recallPositionInUserData, заданы в разделе "Prevent Addition or Deletion of Vertices Using Callback Functions".

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 перемещается. Эта функция получает текущее положение этих трех вершин, вычисляет угол в градусах между вершинами и обновляет метку, чтобы отобразить текущий угол поворота.

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'. Эти события сразу имеют место, прежде чем вершина интереса добавлена к или удалена из ломаной линии. Сохраните текущие три полилинейных вершины в UserData свойство.

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

Задайте функцию обратного вызова, которая выполняется, когда прослушиватели обнаруживают события 'VertexAdded' или 'VertexDeleted'. Эти события сразу имеют место после того, как вершина интереса добавлена к или удалена из ломаной линии. Восстановите сохраненный набор трех полилинейных вершин в UserData свойство.

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

Смотрите также

| |

Похожие темы