exponenta event banner

Создать инструмент редактирования окупаемости инвестиций

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

Еще одним способом редактирования формы свободных ROI, предлагаемым многими популярными программами манипулирования изображениями, является инструмент «ластик» или «кисть». В этом примере реализован один из этих инструментов с использованием другого объекта ROI для редактирования ROI произвольной структуры.

Создание окупаемости инвестиций

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

Считывайте данные МРТ в рабочее пространство.

im = dicomread('knee1.dcm');

Сегментируйте изображение МРТ и выберите две самые большие области маски.

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 Freehand

Создайте ROI круга, который будет использоваться в качестве инструмента редактирования ROI ластика или кисти. (Вы можете использовать любой из images.roi.* классы путем внесения небольшого изменения, упомянутого ниже).

he = images.roi.Circle(...
    'Center', [50 50],...
    'Radius', 10,...
    'Parent', gca,...
    'Color','r');

Свяжите два прослушивателя событий с ROI круга. Один слушает движение окупаемости инвестиций, а другой - когда движение прекращается. Функция обратного вызова с перемещением ROI, в примере, обеспечивает привязку позиции к местоположениям пикселей, а также изменение цвета (красный/зеленый), чтобы указать, будет ли операция редактирования удалена или добавлена к целевой ROI. Как только ROI редактора прекратит движение, мы создадим соответствующие двоичные маски для ROI редактора и целевого ROI freehand и внесем необходимые правки. Подключение прослушивателя для реагирования при каждом перемещении ROI этого редактора

addlistener(he,'MovingROI', @(varargin)editorROIMoving(he, hf));
addlistener(he,'ROIMoved', @(varargin)editFreehand(hf, he));

Интерактивное редактирование ROI Freehand

Эта анимация показывает операцию добавления и удаления редактирования.

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

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

Это обратный вызов для редактирования и окупаемости инвестиций, который добавляет или удаляет область окупаемости инвестиций редактора, пересекающую целевую окупаемость инвестиций.

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

См. также

| | | | | | | | |

Связанные темы