Этот пример показывает, как подвыбрать или уменьшать число точек в объекте Freehand ROI.
Функция drawfreehand создает сглаженно выглядящую видимую область (ROI) от руки. Однако ребро на самом деле сделано из дискретных точек, распределенных все время по контуру. Два фактора способствуют тому, как сглаженный ROI от руки смотрит: 1) плотность точек и 2) свойство Smoothing
объекта ROI от руки.
При рисовании в интерактивном режиме, движение мыши определяет плотность точек. Для крупных комплексных КОРОЛЕЙ используемое число точек может быть довольно большим.
Свойство Smoothing
управляет, как контур смотрит. По умолчанию объект от руки использует Гауссово ядро сглаживания со значением сигмы 1 и размером фильтра 5. Изменение этого значения только изменяется, как контур смотрит, это не изменяет базовое свойство Position
объекта.
Сокращение плотности точек может помочь уменьшать пробел, требуемый хранить данные о ROI, и может также ускорить любое вычисление, которое зависит от количества этих точек. Один способ уменьшать плотность точек состоит в том, чтобы подвыбрать точки, например, выберите любую точку.
Создайте демонстрационный ROI от руки путем преобразования маски в ROI. ROI является очень плотным, поскольку каждый граничный пиксель будет соответствовать точке в ROI.
im = imread('football.jpg'); bw = im(:,:,1)>200; bw = bwareafilt(bw, 1); bloc = bwboundaries(bw,'noholes'); roipos = fliplr(bloc{1}); imshow(im); hfh = drawfreehand('Position', roipos);
Чтобы визуализировать плотность, поверните каждое местоположение в ROI в Waypoint.
hfh.Waypoints(:) = true; title('Original density'); snapnow % Zoom in xlim([80 200]); ylim([70 160]); snapnow
Подвыберите точки, которые составляют свойство Position
ROI от руки. Поскольку ROI от руки является очень плотным. Подвыборка может существенно уменьшать размер, не освобождая точность. Запросите начальное полное/мелкомодульное положение.
fpos = hfh.Position;
Подвыборка, выбирая каждое 4-е положение только.
cpos = fpos(1:2:end,:);
Обновите ROI.
hfh.Position = cpos;
Превратите все точки в Waypoints.
hfh.Waypoints(:) = true;
title('Simple Subsample (factor of 4)');
snapnow
Лучший подход, чтобы подвыбрать точки должен был бы выборочно начать удалять точки, которые имеют низкое искривление. Имеет больше смысла удалять точку, которая приезжает относительно прямой фрагмент ROI, а не одной близости кривая. Один простой подход, чтобы задать значение искривления должен измерить уровень изменения в местоположениях положения.
Измерьте скорость изменения. Сосед первой точки является последней точкой.
dfpos = diff([fpos(end,:); fpos]);
Задайте оперативную меру искривления на основе простого фильтра нижних частот.
cm = sum(abs(conv2(dfpos, ones(3,2),'same')),2);
Сортировка искривлением.
[~, cmInds] = sort(cm);
Выберите 3/4 точек с более низкими значениями искривления, чтобы удалить из ROI.
numPointsToCull = round(0.25*size(fpos,1));
Удалите те положения.
cpos = fpos; cpos(cmInds(1:numPointsToCull),:) = [];
Обновите ROI, включив весь Waypoints, чтобы видеть влияние.
hfh.Position = cpos;
hfh.Waypoints(:) = true;
title('Curvature Based Subsample (factor of 4)');
snapnow
Другой способ подвыбрать состоит в том, чтобы использовать события, чтобы сделать этот процесс легче. Сначала создайте прослушиватель, чтобы в интерактивном режиме изменить число точек, которое использует ROI от руки. Используйте свойство UserData
объекта Freehand кэшировать полное разрешение данные Position
, наряду с его значениями искривления. Затем добавьте пользовательское контекстное меню в объект ROI путем создания нового uimenu и порождения его к UIContextMenu
объекта Freehand. Этот пункт меню позволит нам завершать ROI, который удаляет временный кэш.
% Restore original ROI, and cache the original position along with its % curvature measure in UserData hfh.Position = fpos; hfh.Waypoints(:) = true; hfh.UserData.fpos = fpos; hfh.UserData.cmInds = cmInds;
Ответьте на прокрутку мыши
h = gcf; h.WindowScrollWheelFcn = @(h, evt) changeSampleDensity(hfh, evt);
Добавьте, что контекстное меню, чтобы завершить ROI и выполнить любого моется необходимый
uimenu(hfh.UIContextMenu, 'Text','Finalize',... 'MenuSelectedFcn', @(varargin)finalize(hfh)); title('Scroll to change density interactively');
К этой функции обращаются действие прокрутки. Прокрутка повышает плотность и прокручивающие вниз уменьшения это. Это позволяет нам в интерактивном режиме выбирать число точек, чтобы сохранить.
function changeSampleDensity(hfh, evt) currentNumPoints = size(hfh.Position,1); % 5% of original for each scroll. numChangePoints = round(size(hfh.UserData.fpos,1)*0.05); newNumPoints = currentNumPoints + evt.VerticalScrollCount*numChangePoints; newNumPoints = max(3, min(size(hfh.UserData.fpos,1), newNumPoints)); numPointsToCull = size(hfh.UserData.fpos,1) - newNumPoints; % Pick the full resolution cached position cpos = hfh.UserData.fpos; cmInds = hfh.UserData.cmInds; % cull that to get the coarse position cpos(cmInds(1:numPointsToCull),:) = []; % Update the ROI and show all the points used hfh.Position = cpos; hfh.Waypoints(:) = true; end
Удалите и создайте новый ROI От руки с подвыбранными точками, чтобы экономить на пробеле.
function finalize(hfh) h = ancestor(hfh, 'figure'); % Reset the mouse scroll wheel callback h.WindowScrollWheelFcn = []; % Save finalized set of points pos = hfh.Position; % Delete and create a new Freehand ROI delete(hfh); drawfreehand(gca, 'Position', pos); end
bwareafilt
| bwboundaries
| drawfreehand
| images.roi.Freehand