В этом примере показано, как создать простой инструмент, чтобы отредактировать форму ROI от руки с помощью другого объекта ROI. По умолчанию,
Объекты ROI включают waypoints, который можно перетащить, чтобы отрегулировать форму ROI. Можно также добавить waypoints в интерактивном режиме в любую часть контура.Freehand
Другим способом отредактировать форму ROI от руки, предлагаемых многими популярными программами преобразования изображения, является инструмент 'кисти' или 'средство стирания'. Этот пример реализует один из этих инструментов, с помощью другого объекта ROI отредактировать ROI от руки.
Создайте ROI От руки, который следует за формой маски сегментации. Для получения дополнительной информации об этом процессе смотрите Использование ROI От руки, чтобы Совершенствовать Маски Сегментации.
Считайте данные MRI в рабочую область.
im = dicomread('knee1.dcm');
Сегментируйте изображение MRI и выберите две самых больших области маски.
segmentedLabels = imsegkmeans(im,3); boneMask = segmentedLabels==2; boneMask = bwareafilt(boneMask, 1);
Получите координаты контуров двух сегментированных областей.
blocations = bwboundaries(boneMask,'noholes');
Преобразуйте местоположения, возвращенные bwboundaries
к x, y порядок.
pos = blocations{1}; pos = fliplr(pos);
Отобразите изображение.
figure hImage = imshow(im,[]);
Создайте 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 от руки object.Wire прослушиватель, чтобы реагировать каждый раз, когда этот 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
dicomread
| imsegkmeans
| bwareafilt
| bwboundaries
| drawfreehand
| Freehand
| Circle
| addlistener
| inROI
| createMask