Этот пример показывает, как создать простой инструмент, чтобы отредактировать форму ROI от руки с помощью другого объекта ROI. По умолчанию, объекты ROI От руки, images.roi. От руки, уже включайте подразумеваемые возможности, названные waypoints, для того, чтобы в интерактивном режиме отредактировать их форму. Путем перетаскивания любого из этих waypoints на ребре ROI можно настроить ребро ROI. Можно также добавить waypoints в интерактивном режиме в любую часть контура.
Другим способом отредактировать форму КОРОЛЕЙ От руки, предлагаемых многими популярными программами преобразования изображения, является инструмент 'кисти' или 'средство стирания'. Этот пример реализует один из этих инструментов, с помощью другого объекта ROI отредактировать ROI от руки.
Создайте ROI От руки, который следует за формой маски сегментации. Для получения дополнительной информации на этом процессе, смотрите Использование КОРОЛИ От руки, чтобы Совершенствовать Маски Сегментации.
Считайте данные MRI в рабочую область.
im = dicomread('knee1.dcm');
Сегментируйте изображение MRI и выберите две самых больших области рисунка маски.
segmentedLabels = imsegkmeans(im,3); boneMask = segmentedLabels==2; boneMask = bwareafilt(boneMask, 1);
Получите координаты контуров двух сегментированных областей.
blocations = bwboundaries(boneMask,'noholes');
Отобразите изображение.
figure hImage = imshow(im, []);
Преобразуйте местоположения, возвращенные bwboundaries
в x, y порядок.
pos = blocations{1}; pos = fliplr(pos);
Создайте ROI от руки в сегментированной маске.
hf = drawfreehand('Position', pos);
Создайте Круговой ROI, который будет использоваться в качестве средства стирания или инструмента редактирования ROI кисти. (Можно использовать любой из классов images.roi.*
путем создания небольшого изменения, упомянутого ниже).
he = images.roi.Circle(... 'Center', [50 50],... 'Radius', 10,... 'Parent', gca,... 'Color','r');
Сопоставьте два прослушивателя события с Круговым ROI. Каждый слушает для перемещения ROI, и другой слушает для того, когда перемещение останавливается. ROI, перемещающий функцию обратного вызова, пример убеждается, что имел свою привязку положения к пиксельным местоположениям и также изменил цвет (Красный/Зеленый), чтобы указать, удалит ли операция редактирования или добавит к целевому ROI от руки. Если ROI редактора прекращает перемещаться, мы создадим соответствующие бинарные маски для ROI редактора и целевого ROI от руки и сделаем необходимое редактирование. Наконец, мы преобразуем обновленную маску назад к объекту ROI от руки. Обеспечьте электричеством прослушиватель, чтобы реагировать каждый раз, когда этот ROI редактора перемещен
addlistener(he,'MovingROI', @(varargin)editorROIMoving(he, hf)); addlistener(he,'ROIMoved', @(varargin)editFreehand(hf, he));
Эта анимация показывает добавление, и удалите операцию редактирования.
Это - ROI, перемещающий функцию обратного вызова. Эта функция гарантирует, что привязки ROI редактора к пиксельной сетке, и изменяют цвет ROI редактора, чтобы указать, добавит ли это к ROI от руки или удалять область от ROI от руки. Если центр ROI редактора вне целевого ROI от руки, удаляет операцию, в противном случае это 'добавит'.
function editorROIMoving(he, hf) % Snap editor ROI to grid he.Position = round(he.Position); % Check if the circle ROI's center is inside or outside the freehand ROI. center = he.Center; isAdd = hf.inROI(center(1), center(2)); if isAdd % Green if inside (since we will add to the freehand). he.Color = 'g'; else % Red otherwise. he.Color = 'r'; end end
Это - редактирование коллбэк ROI от руки, который добавляет или удаляет область ROI редактора, который пересекает целевой ROI от руки.
function editFreehand(hf, he) % Create a mask for the target freehand. tmask = hf.createMask(); [m, n,~] = size(tmask); % Include the boundary pixel locations boundaryInd = sub2ind([m,n], hf.Position(:,2), hf.Position(:,1)); tmask(boundaryInd) = true; % Create a mask from the editor ROI emask = he.createMask(); boundaryInd = sub2ind([m,n], he.Position(:,2), he.Position(:,1)); emask(boundaryInd) = true; % Check if center of the editor ROI is inside the target freehand. If you % use a different editor ROI, ensure to update center computation. center = he.Center; % isAdd = hf.inROI(center(1), center(2)); if isAdd % Add the editor mask to the freehand mask newMask = tmask|emask; else % Delete out the part of the freehand which intersects the editor newMask = tmask&~emask; end % Update the freehand ROI perimPos = bwboundaries(newMask, 'noholes'); hf.Position = [perimPos{1}(:,2), perimPos{1}(:,1)]; end
addlistener
| bwareafilt
| bwboundaries
| createMask
| dicomread
| drawfreehand
| images.roi.Circle
| images.roi.Freehand
| imsegkmeans
| inROI