Matlab - Распространять точки, ортогонально расположенные к краю границ формы - PullRequest
0 голосов
/ 19 апреля 2010

У меня есть набор точек, которые я хочу распространить по краю границы формы, определенной двоичным изображением. Граница формы определяется белым краем шириной 1 пиксель.

У меня есть координаты этих точек, хранящиеся в матрице из 2 строк по n столбцов. Форма образует вогнутую границу без отверстий внутри себя, состоящую из около 2500 точек. У меня есть приблизительно от 80 до 150 точек, которые я хочу размножить на границе формы.

Я хочу навести луч из каждой точки из набора точек в ортогональном направлении и определить, в какой точке он пересекает границу формы в. Ортогональное направление уже определено. Для требуемых целей он рассчитывается по нормали контура, рассчитанной для точки, с использованием точки-1 и точки + 1.

Какой лучший способ сделать это? Существуют ли какие-либо алгоритмы трассировки лучей, которые можно использовать?

Большое спасибо заранее за любую помощь!

РЕДАКТИРОВАТЬ: я попытался сделать вопрос намного яснее и добавил изображение, описывающее проблему. На изображении серая линия представляет контур фигуры, красная - точки Я хочу размножить и зеленую линию воображаемым ортогональным лучом.

альтернативный текст http://img504.imageshack.us/img504/3107/orth.png

ДРУГОЕ РЕДАКТИРОВАНИЕ: Для пояснения я разместил код, используемый для вычисления нормалей для каждой точки. Где xt и yt - векторы, хранящие координаты для каждой точки. После вычисления нормального значения его можно распространить с помощью функции linspace и запрошенной длины ортогональной линии.

%#derivaties of contour
dx=[xt(2)-xt(1) (xt(3:end)-xt(1:end-2))/2 xt(end)-xt(end-1)];
dy=[yt(2)-yt(1) (yt(3:end)-yt(1:end-2))/2 yt(end)-yt(end-1)];

%#normals of contourpoints
l=sqrt(dx.^2+dy.^2);
nx = -dy./l; 
ny =  dx./l;

normals = [nx,ny];

Ответы [ 2 ]

0 голосов
/ 19 апреля 2010

Если я правильно понимаю вашу проблему (спроецируйте каждую точку на ближайшую точку границы формы), вы можете

  1. используйте sub2ind для преобразования описания "матрица из 2 строк на n столбцов" в черно-белое изображение с белыми пикселями, что-то вроде

    myimage=zeros(imagesize); myimage(imagesize, x_coords, y_coords) = 1

  2. используйте imfill для заполнения за пределами границы

  3. запустите [D,L] = bwdist(BW) на полученном изображении и просто прочитайте ответы из L.

Должно быть довольно простым.

0 голосов
/ 19 апреля 2010

Это зависит от того, сколько единичных векторов вы хотите проверить по одной фигуре. Если у вас есть одна форма и много тестов, проще всего, вероятно, преобразовать координаты вашей формы в полярные координаты, которые уже неявно представляют ваше решение. Однако это может быть не очень эффективным решением, если у вас разные фигуры и только несколько тестов для каждой фигуры.

Обновление на основе отредактированного вопроса:

Если лучи могут начинаться от произвольных точек, а не только от источника, вы должны проверить все точки. Это можно легко сделать, преобразовав границу вашей формы так, чтобы ваш луч для проверки начинался в начале координат в любом направлении координат (положительный x в моем примере кода)

% vector of shape boundary points (assumed to be image coordinates, i.e. integers)
shapeBoundary = [xs, ys];

% define the start point and direction you want to test
startPoint = [xsp, ysp];
testVector = unit([xv, yv]);

% now transform the shape boundary
shapeBoundaryTrans(:,1) = shapeBoundary(:,1)-startPoint(1);
shapeBoundaryTrans(:,2) = shapeBoundary(:,2)-startPoint(2);
rotMatrix = [testVector(2), testVector(1); ...
             testVector(-1), testVector(2)];
% somewhat strange transformation to keep it vectorized
shapeBoundaryTrans = shapeBoundaryTrans * rotMatrix';

% now the test is easy: find the points close to the positive x-axis
selector = (abs(shapeBoundaryTrans(:,2)) < 0.5) & (shapeBoundaryTrans(:,1) > 0);
shapeBoundaryTrans(:,2) = 1:size(shapeBoundaryTrans, 1)';
shapeBoundaryReduced = shapeBoundaryTrans(selector, :);
if (isempty(shapeBoundaryReduced))
    [dummy, idx] = min(shapeBoundaryReduced(:, 1));
    collIdx = shapeBoundaryReduced(idx, 2);
    % you have a collision with point collIdx of your shapeBoundary
else
    % no collision
end

Возможно, это можно сделать более приятным способом, но вы поняли ...

...