В этом примере показано, как использовать 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);
Создайте функцию, используемую с 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 линии перемещается, то есть, когда '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 линии в startDrawing
функция обратного вызова. Это - коллбэк, сопоставленный с тем пользовательским контекстным меню. Этот коллбэк использует findobj
функционируйте, чтобы искать Тип ROI, и удаляет любые найденные ROI.
function deleteAll(src,~) hFig = ancestor(src,'figure'); hROIs = findobj(hFig,'Type','images.roi.Line'); delete(hROIs) end
addlistener
| beginDrawingFromPoint
| Line
| drawline