В этом примере показано, как подпроизвести или уменьшать число точек в Freehand
Объект ROI.
drawfreehand
функция создает сглаженно выглядящий, от руки, видимую область (ROI). Однако ребро ROI на самом деле сделано из дискретных точек, распределенных все время по контуру. Два фактора способствуют тому, как сглаженный ROI от руки смотрит: 1) плотность точек и 2) Smoothing
свойство объекта ROI от руки.
При рисовании в интерактивном режиме, движение мыши определяет плотность точек. Для больших комплексных ROI используемое число точек может быть довольно большим.
Smoothing
свойство управляет, как контур смотрит. По умолчанию, Freehand
возразите использует Гауссово ядро сглаживания со значением сигмы 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;
Подвыборка, выбирая любую точку.
cpos = fpos(1:2:end,:);
Обновите свойство Position ROI.
hfh.Position = cpos;
Чтобы видеть плотность, превратите все точки в waypoints.
hfh.Waypoints(:) = true;
title('Simple Subsample');
snapnow
Лучший подход, чтобы подпроизвести точки должен был бы выборочно начать удалять точки, которые имеют низкое искривление. Имеет больше смысла удалять точку, которая приезжает относительно прямой фрагмент ROI, а не одной близости кривая. Один простой подход, чтобы задать значение искривления должен измерить уровень изменения в местоположениях положения.
Измерьте скорость изменения. Сосед первой точки является последней точкой.
dfpos = diff([fpos(end,:); fpos]);
Задайте оперативную меру искривления на основе простого фильтра lowpass.
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
reduce
метод на объектах ROI от рукиЕще лучший подход, чтобы подпроизвести точки должен был бы использовать reduce
метод на объекте ROI. reduce
метод работает непосредственно с Position
свойство объекта ROI. Можно влиять на число точек, удаленное путем определения значения допуска между [0 1.0] как дополнительный входной параметр. Значение по умолчанию допуска 0.01.
Сбросьте Position
свойство и вызов reduce
на объекте ROI.
hfh.Position = fpos; reduce(hfh); % View the updated ROI, turning all the points into waypoints to see the % impact. hfh.Waypoints(:) = true; title('Subsampling using reduce method'); snapnow
Другой способ подпроизвести состоит в том, чтобы использовать события, чтобы сделать этот процесс легче. Сначала создайте прослушиватель, чтобы в интерактивном режиме изменить число точек, которое использует ROI от руки. Используйте UserData
свойство объекта Freehand кэшировать полное разрешение Position
данные, наряду с текущим значением допуска. Затем добавьте пользовательское контекстное меню в объект ROI путем создания нового
и порождение его к uimenu
UIContextMenu
из объекта Freehand. Этот пункт меню позволяет вам завершать ROI, который удаляет временный кэш.
Восстановите исходный ROI и кэшируйте исходное положение наряду с его мерой по искривлению в UserData.
hfh.Waypoints(:) = true; hfh.UserData.fpos = fpos; hfh.UserData.tol = 0;
Ответьте на прокрутку мыши.
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) % Restore Position property of ROI. hfh.Position = hfh.UserData.fpos; % Change tolerance by a fixed amount based on the direction of the scroll. % This code changes the tolerance by 0.01 for every scroll increment. tol = hfh.UserData.tol + 0.01 * (evt.VerticalScrollCount); % Restrict the range of tolerance values to be from 0 to 0.15, which is the % useful range. tol = max(min(tol, 0.15), 0); % Call |reduce| with the specified tolerance. reduce(hfh,tol); hfh.UserData.tol = tol; % Update the ROI and turn all the points into waypoints to show the % density. 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 with the new |Position| value. delete(hfh); drawfreehand(gca, 'Position', pos); end
Freehand
| bwareafilt
| bwboundaries
| drawfreehand