Измерьте расстояния в изображении

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

Считайте изображение в рабочую область и изображение на дисплее

Считайте изображение в рабочую область.

im = imread('concordorthophoto.png');

Соберите данные вокруг изображения, такого как его размер, и храните данные в структуре, которую можно передать функциям обратного вызова.

sz = size(im);
myData.Units = 'pixels';
myData.MaxValue = hypot(sz(1),sz(2));
myData.Colormap = hot;
myData.ScaleFactor = 1;

Отобразите изображение в оси.

hIm = imshow(im);

Задайте функцию обратного вызова для ButtonDownFcn коллбэк на изображении. Передайте myData структура к функции обратного вызова. Эта функция обратного вызова создает объекты линии и начинает чертить ROI.

hIm.ButtonDownFcn = @(~,~) startDrawing(hIm.Parent,myData);

Создайте функцию обратного вызова, чтобы начать чертить ROI

Создайте функцию, используемую с ButtonDownFcn коллбэк, чтобы создать ROI линии. Эта функция:

1. Инстанцирует объекта ROI линии.

2. Настраивает прослушиватели, чтобы реагировать на нажатия кнопки и перемещение ROI.

3. Добавляет пользовательское контекстное меню к ROI, которое включает, 'Удаляют Всю' опцию.

4. Начинает чертить ROI, с помощью точки, по которой кликают в изображении как начальная точка.

function startDrawing(hAx,myData)

% Create a line ROI object. Specify the initial color of the line and
% store the |myData| structure in the |UserData| property of the ROI.
h = images.roi.Line('Color',[0, 0, 0.5625],'UserData',myData);

% Set up a listener for movement of the line ROI. When the line ROI moves,
% the |updateLabel| callback updates the text in the line ROI label and
% changes the color of the line, based on its length.
addlistener(h,'MovingROI',@updateLabel);

% Set up a listener for clicks on the line ROI. When you click on the line
% ROI, the |updateUnits| callback opens a GUI that lets you specify the
% known distance in real-world units, such as, meters or feet.
addlistener(h,'ROIClicked',@updateUnits);

% Get the current mouse location from the |CurrentPoint| property of the
% axes and extract the _x_ and _y_ coordinates.
cp = hAx.CurrentPoint;
cp = [cp(1,1) cp(1,2)];

% Begin drawing the ROI from the current mouse location. Using the
% |beginDrawingFromPoint| method, you can draw multiple ROIs.
h.beginDrawingFromPoint(cp);

% Add a custom option to the line ROI context menu to delete all existing
% line ROIs.
c = h.UIContextMenu;
uimenu(c,'Label','Delete All','Callback',@deleteAll);

end

Создайте функцию обратного вызова, чтобы обновить метку ROI и цвет

Создайте функцию, которая вызвана каждый раз, когда ROI линии перемещается, то есть, когда 'MovingROI' событие имеет место. Эта функция обновляет метку ROI с длиной линии и изменяет цвет линии на основе ее длины.

Эта функция вызывается неоднократно, когда ROI перемещается. Если вы хотите обновить ROI только, когда перемещение закончилось, прислушайтесь к 'ROIMoved' событие вместо этого.

function updateLabel(src,evt)

% Get the current line position.
pos = evt.Source.Position;

% Determine the length of the line.
diffPos = diff(pos);
mag = hypot(diffPos(1),diffPos(2));

% Choose a color from the colormap based on the length of the line. The
% line changes color as it gets longer or shorter.
color = src.UserData.Colormap(ceil(64*(mag/src.UserData.MaxValue)),:);

% Apply the scale factor to line length to calibrate the measurements.
mag = mag*src.UserData.ScaleFactor;

% Update the label.
set(src,'Label',[num2str(mag,'%30.1f') ' ' src.UserData.Units],'Color',color);

end

Создайте функцию обратного вызова, чтобы обновить модули измерения

Создайте функцию, которая вызвана каждый раз, когда вы дважды кликаете метку ROI. Эта функция открывает раскрывающееся диалоговое окно, в которое можно ввести информацию о реальном расстоянии и модулях.

Эта функция прислушивается к 'ROIClicked' событие, с помощью данных о событиях, чтобы проверять тип нажатия кнопки и часть ROI, по которому кликнули.

Раскрывающееся диалоговое окно предлагает вам вводить известное расстояние и модули для этого измерения. С этой информацией можно калибровать все измерения ROI к модулям реального мира.

function updateUnits(src,evt)

% When you double-click the ROI label, the example opens a popup dialog box
% to get information about the actual distance. Use this information to
% scale all line ROI measurements.
if strcmp(evt.SelectionType,'double') && strcmp(evt.SelectedPart,'label')

    % Display the popup dialog box.
    answer = inputdlg({'Known distance','Distance units'},...
        'Specify known distance',[1 20],{'10','meters'});

    % Determine the scale factor based on the inputs.
    num = str2double(answer{1});

    % Get the length of the current line ROI.
    pos = src.Position;
    diffPos = diff(pos);
    mag = hypot(diffPos(1),diffPos(2));

    % Calculate the scale factor by dividing the known length value by the
    % current length, measured in pixels.
    scale = num/mag;

    % Store the scale factor and the units information in the |myData|
    % structure.
    myData.Units = answer{2};
    myData.MaxValue = src.UserData.MaxValue;
    myData.Colormap = src.UserData.Colormap;
    myData.ScaleFactor = scale;

    % Reset the data stored in the |UserData| property of all existing line
    % ROI objects. Use |findobj| to find all line ROI objects in the axes.
    hAx = src.Parent;
    hROIs = findobj(hAx,'Type','images.roi.Line');
    set(hROIs,'UserData',myData);

    % Update the label in each line ROI object, based on the information
    % collected in the input dialog.
    for i = 1:numel(hROIs)

        pos = hROIs(i).Position;
        diffPos = diff(pos);
        mag = hypot(diffPos(1),diffPos(2));

        set(hROIs(i),'Label',[num2str(mag*scale,'%30.1f') ' ' answer{2}]);

    end

    % Reset the |ButtonDownFcn| callback function with the current |myData|
    % value.
    hIm = findobj(hAx,'Type','image');
    hIm.ButtonDownFcn = @(~,~) startDrawing(hAx,myData);

end

end

Создайте функцию обратного вызова, чтобы удалить все ROI

Создайте функцию, чтобы удалить все ROI. Вы добавили пользовательский элемент контекстного меню в каждый ROI линии в startDrawing функция обратного вызова. Это - коллбэк, сопоставленный с тем пользовательским контекстным меню. Этот коллбэк использует findobj функционируйте, чтобы искать Тип ROI, и удаляет любые найденные ROI.

function deleteAll(src,~)

hFig = ancestor(src,'figure');
hROIs = findobj(hFig,'Type','images.roi.Line');
delete(hROIs)

end

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

| | |

Похожие темы