В этом примере показано, как подпробовать или уменьшить количество точек в Freehand Объект окупаемости инвестиций.
drawfreehand создает гладкую, свободную область интересов (ROI). Однако кромка ROI фактически выполнена из дискретных точек, распределенных по всей границе. Два фактора способствуют тому, как гладко выглядит окупаемость инвестиций: 1) плотность точек и 2) Smoothing свойство объекта ROI freehand.
При рисовании в интерактивном режиме движение мыши определяет плотность точек. Для больших комплексных ROI количество используемых точек может быть довольно большим.
Smoothing свойство управляет внешним видом границы. По умолчанию Freehand объект использует гауссово сглаживающее ядро со значением sigma 1 и размером фильтра 5. Изменение этого значения только изменяет внешний вид границы, но не изменяет нижележащую Position свойства объекта.
Уменьшение плотности точек может помочь уменьшить пространство, необходимое для хранения данных 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);

Чтобы визуализировать плотность точек, превратите каждую точку в окупаемости инвестиций в ППМ.
hfh.Waypoints(:) = true; title('Original density'); snapnow % Zoom in. xlim([80 200]); ylim([70 160]); snapnow


Поднабор точек, составляющих Position собственность свободного владения ROI. Так как свободная окупаемость инвестиций очень плотная. Субдискретизация может существенно уменьшить размер без потери точности. Запрос начального, полного, мелкозернистого положения.
fpos = hfh.Position;
Поднабор, выбор каждой другой точки.
cpos = fpos(1:2:end,:);
Обновите свойство Position ROI.
hfh.Position = cpos;

Чтобы увидеть плотность, превратите все точки в ППМ.
hfh.Waypoints(:) = true;
title('Simple Subsample');
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),:) = [];
Обновите окупаемость инвестиций, включив все ППМ, чтобы увидеть воздействие.
hfh.Position = cpos;
hfh.Waypoints(:) = true;
title('Curvature Based Subsample (factor of 4)');
snapnow

reduce метод для объектов с произвольной окупаемостью инвестицийЕще лучшим подходом к подсистеме пунктов было бы использовать 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 freehand. Используйте UserData свойство объекта Freehand для кэширования полного разрешения Position данные вместе с текущим значением допуска. Затем добавьте пользовательское контекстное меню к объекту окупаемости инвестиций путем создания нового и воспитание его у uimenuUIContextMenu объекта Freehand. Этот пункт меню позволяет завершить окупаемость инвестиций, которая удаляет временный кэш.
Восстановление исходной окупаемости инвестиций и кэширование исходной позиции вместе с измерением кривизны в UserData.
hfh.Waypoints(:) = true; hfh.UserData.fpos = fpos; hfh.UserData.tol = 0;

Ответьте на прокрутку мыши.
h = gcf; h.WindowScrollWheelFcn = @(h, evt) changeSampleDensity(hfh, evt);
Добавьте контекстное меню, чтобы завершить окупаемость инвестиций и выполнить необходимую очистку.
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 Freehand с субдискретизированными точками для экономии места.
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
bwareafilt | bwboundaries | drawfreehand | Freehand