1

J'ai une image squelettisée (montrée ci-dessous).Recherche d'intersections d'une image squelettisée dans python opencv

Skeleton Image

Je voudrais obtenir les intersections des lignes. J'ai essayé la méthode suivante ci-dessous, skeleton est une image opencv et l'algorithme retourne une liste de coordonnées:

def getSkeletonIntersection(skeleton): 
    image = skeleton.copy(); 
    image = image/255; 
    intersections = list(); 
    for y in range(1,len(image)-1): 
     for x in range(1,len(image[y])-1): 
      if image[y][x] == 1: 
       neighbourCount = 0; 
       neighbours = neighbourCoords(x,y); 
       for n in neighbours: 
        if (image[n[1]][n[0]] == 1): 
         neighbourCount += 1; 
       if(neighbourCount > 2): 
        print(neighbourCount,x,y); 
        intersections.append((x,y)); 
    return intersections; 

On trouve les coordonnées des pixels blancs où il y a plus de deux pixels adjacents. Je pensais que cela ne ferait que renvoyer des virages mais ce n'est pas le cas - cela rapporte beaucoup plus de points.

Skeleton with marked coordinates

C'est la sortie avec les points qu'il détecte marqué sur l'image. C'est parce qu'il détecte certains des exemples ci-dessous qui ne sont pas des intersections.

0 0 0 1 1 0 0 1 1 
1 1 1 0 1 0 1 1 0 
0 0 1 0 0 1 0 0 0 

Et beaucoup d'autres exemples. Y a-t-il une autre méthode que je devrais examiner pour détecter les intersections? Toutes les contributions et les idées appréciées, merci.

+0

peut-être augmenter le nombre à 4 ou 6 pour filtrer les points dans cette ligne 'if (neighbourCount> 2):'. –

Répondre

2

Je ne suis pas sûr de OpenCV fonctionnalités, mais vous devriez peut-être essayer en utilisant hasardeux morphologie qui est décrit here.

Lire sur ligne Jonctions et voir les 12 modèles dont vous avez besoin pour tester:

enter image description here

+0

Bravo pour ça. Terminé les tests à partir d'une grande liste de jonctions de ligne. –

1

Il pourrait aider si, quand pour un pixel donné, au lieu de compter le nombre du total 8 voisins (= voisins avec une connectivité 8), on compte le nombre de 8-voisins qui ne sont pas 4-voisins les uns aux autres

donc, dans votre exemple de faux positifs

0 0 0 1 1 0 0 1 1 
1 1 1 0 1 0 1 1 0 
0 0 1 0 0 1 0 0 0 

Pour chaque cas, vous avez 3 voisins, mais chaque fois, 2 d'entre eux sont connectés en 4. (Pixels marqués « 2 » dans le prochain extrait)

0 0 0 2 2 0 0 2 2 
1 1 2 0 1 0 1 1 0 
0 0 2 0 0 1 0 0 0 

Si vous considérez que l'un de ces derniers pour vos comptes (au lieu de deux dans votre code en ce moment), vous avez en effet que 2 au total nouvellement défini " voisins »et les points considérés ne sont pas considérés comme des intersections. D'autres « intersections réelles » seraient toujours tenus, comme ce qui suit

0 1 0 0 1 0 0 1 0 
1 1 1 0 1 0 1 1 0 
0 0 0 1 0 1 0 0 1 

qui ont encore 3 voisins nouvellement définis.

Je n'ai pas vérifié sur votre image si elle fonctionne parfaitement, mais je l'avais mis en œuvre quelque chose comme ça pour ce problème un certain temps ...

1

J'ai reçu un courriel demandant récemment pour ma solution éventuelle au problème . Il est posté ci-dessous de telle sorte qu'il pourrait informer les autres. Je ne prétends pas que ce code est particulièrement rapide ou stable - seulement que c'est ce qui a fonctionné pour moi!La fonction inclut également le filtrage des doublons et des intersections détectées trop rapprochées, ce qui suggère qu'elles ne sont pas de véritables intersections et qu'elles ont plutôt introduit du bruit à partir du processus de squelettisation.

def getSkeletonIntersection(skeleton): 
    """ Given a skeletonised image, it will give the coordinates of the intersections of the skeleton. 

    Keyword arguments: 
    skeleton -- the skeletonised image to detect the intersections of 

    Returns: 
    List of 2-tuples (x,y) containing the intersection coordinates 
    """ 
    # A biiiiiig list of valid intersections    2 3 4 
    # These are in the format shown to the right   1 C 5 
    #             8 7 6 
    validIntersection = [[0,1,0,1,0,0,1,0],[0,0,1,0,1,0,0,1],[1,0,0,1,0,1,0,0], 
         [0,1,0,0,1,0,1,0],[0,0,1,0,0,1,0,1],[1,0,0,1,0,0,1,0], 
         [0,1,0,0,1,0,0,1],[1,0,1,0,0,1,0,0],[0,1,0,0,0,1,0,1], 
         [0,1,0,1,0,0,0,1],[0,1,0,1,0,1,0,0],[0,0,0,1,0,1,0,1], 
         [1,0,1,0,0,0,1,0],[1,0,1,0,1,0,0,0],[0,0,1,0,1,0,1,0], 
         [1,0,0,0,1,0,1,0],[1,0,0,1,1,1,0,0],[0,0,1,0,0,1,1,1], 
         [1,1,0,0,1,0,0,1],[0,1,1,1,0,0,1,0],[1,0,1,1,0,0,1,0], 
         [1,0,1,0,0,1,1,0],[1,0,1,1,0,1,1,0],[0,1,1,0,1,0,1,1], 
         [1,1,0,1,1,0,1,0],[1,1,0,0,1,0,1,0],[0,1,1,0,1,0,1,0], 
         [0,0,1,0,1,0,1,1],[1,0,0,1,1,0,1,0],[1,0,1,0,1,1,0,1], 
         [1,0,1,0,1,1,0,0],[1,0,1,0,1,0,0,1],[0,1,0,0,1,0,1,1], 
         [0,1,1,0,1,0,0,1],[1,1,0,1,0,0,1,0],[0,1,0,1,1,0,1,0], 
         [0,0,1,0,1,1,0,1],[1,0,1,0,0,1,0,1],[1,0,0,1,0,1,1,0], 
         [1,0,1,1,0,1,0,0]]; 
    image = skeleton.copy(); 
    image = image/255; 
    intersections = list(); 
    for x in range(1,len(image)-1): 
     for y in range(1,len(image[x])-1): 
      # If we have a white pixel 
      if image[x][y] == 1: 
       neighbours = zs.neighbours(x,y,image); 
       valid = True; 
       if neighbours in validIntersection: 
        intersections.append((y,x)); 
    # Filter intersections to make sure we don't count them twice or ones that are very close together 
    for point1 in intersections: 
     for point2 in intersections: 
      if (((point1[0] - point2[0])**2 + (point1[1] - point2[1])**2) < 10**2) and (point1 != point2): 
       intersections.remove(point2); 
    # Remove duplicates 
    intersections = list(set(intersections)); 
    return intersections; 

Ceci est également disponible sur github here.