2010-04-18 5 views
0

J'ai un ensemble de points que je veux propager sur le bord de la limite de la forme définie par une image binaire. La limite de forme est définie par un bord blanc large 1px.Matlab - Propager des points orthogonalement sur le bord des limites de forme

J'ai les coordonnées de ces points stockées dans une matrice de 2 rangées par n colonnes. La forme forme une limite concave sans trous à l'intérieur d'environ 2500 points. J'ai environ 80 à 150 points que je souhaite propager sur la limite de forme. Je veux lancer un rayon de chaque point de l'ensemble des points dans une direction orthogonale et détecter à quel point il coupe la limite de forme à. La direction orthogonale a déjà été déterminée. Aux fins requises, il est calculé en prenant la normale du contour calculé pour le point, en utilisant le point-1 et le point + 1.

Quelle serait la meilleure méthode pour cela? Existe-t-il une sorte d'algorithme de tracé de rayons qui pourrait être utilisé?

Merci beaucoup d'avance pour toute aide!

EDIT: J'ai essayé de clarifier la question et j'ai ajouté une image décrivant le problème. Dans l'image, la ligne grise représente le contour de la forme, les points rouges les points Je veux propager et la ligne verte un rayon orthogonal imaginaire.

alt text http://img504.imageshack.us/img504/3107/orth.png

AUTRE EDIT: Pour plus de précisions, j'ai posté le code utilisé pour calculer les Normales pour chaque point. Où les xt et yt sont des vecteurs stockant les coordonnées pour chaque point. Après avoir calculé la valeur normale, il peut être propagé en utilisant la fonction linspace et la longueur demandée de la ligne orthogonale.

%#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]; 
+0

À quoi correspond la ligne verte orthogonale? Par "La direction orthogonale a déjà été déterminée" voulez-vous dire que nous pouvons considérer cela comme une partie donnée des données? – AVB

Répondre

0

Cela dépend du nombre de vecteurs unitaires que vous souhaitez tester par rapport à une forme. Si vous avez une forme et de nombreux tests, la meilleure chose à faire est probablement de convertir vos coordonnées de forme en coordonnées polaires qui représentent implicitement déjà votre solution. Ceci peut ne pas être une solution très efficace cependant si vous avez différentes formes et seulement quelques essais pour chaque forme.

mise à jour basée sur la question éditée:

Si les rayons peuvent commencer à partir de points arbitraires, non seulement de l'origine, vous devez tester contre tous les points. Cela peut se faire facilement en transformant votre forme limite telle que votre rayon de test commence à l'origine dans les deux sens de coordonnées (x positives dans mon code exemple)

% 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 

Cela pourrait se faire d'une manière plus agréable sans doute, mais vous avez eu l'idée...

+0

Ah! Je suis vraiment désolé d'avoir mal indiqué mon problème. J'ai déjà créé une nouvelle version éditée. J'ai entre 80 et 200 points que je souhaite lancer orthogonalement et env. 2500 points à tester contre. Désolé pour le poste incorrect, je serais très intéressé par ce que vous pensez du problème. – binarycreations

+0

Après vos modifications de la question, je pense toujours que ma réponse mise à jour devrait approximativement faire ce que vous voulez (je ne l'ai pas essayé moi-même cependant ...) Comme vous avez modifié votre question, il doit y avoir quelque chose qui me manque . Pourriez-vous clarifier ce qui ne fonctionne pas? – groovingandi

+0

Désolé pour la grande quantité de montage. Je trouve difficile d'énoncer un problème qui m'est inconnu. J'ai ajouté comment les normales sont calculées et un diagramme. Je ne pense pas que votre solution fonctionne car elle ne repose que sur un seul axe. J'espère que cela aidera, merci pour votre persévérance! – binarycreations

0

Si je comprends bien votre problème (projet chaque point sur le point le plus proche de la limite de forme), vous pouvez

  1. utilisation sub2ind pour convertir la description « 2 ligne par matrice colonne n » à un BW image avec des pixels blancs, quelque chose comme

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

  2. utilisation imfill pour remplir le extérieur de t la limite

  3. exécutez [D,L] = bwdist(BW) sur l'image résultante, et lisez simplement les réponses de L.

Devrait être assez simple.

+0

Il ne peut pas parier techniquement le point fermé de la limite de forme. J'ai ajouté un diagramme pour donner plus de sens au problème ... – binarycreations

+0

@Graham: et la ligne verte est orthogonale à quoi exactement? – AVB

Questions connexes