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

В этом примере показано, как использовать 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);

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

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

1. Создание экземпляра объекта ROI линии.

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

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

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

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

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

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

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

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

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

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

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

function deleteAll(src,~)

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

end

См. также

| | |

Похожие темы