web-dev-qa-db-fra.com

Comment connecter des lignes brisées dans une image binaire en utilisant Python / Opencv

Comment puis-je connecter ces lignes aux points cibles? L'image est le résultat d'un processus de squelettisation.

Resulting Image From Skeletonization

Points That I Need To Connect

J'essaie de segmenter chaque ligne en tant que région à l'aide de la transformation du bassin versant.

10
Thiago Resende

MikeE la réponse est assez bonne: l'utilisation des opérations morphologiques de dilatation et d'érosion peut être très utile dans ce contexte.
Je veux suggérer une petite amélioration, en profitant de la structure spécifique de l'image à portée de main. Au lieu d'utiliser la dilatation/l'érosion avec un noyau général, je suggère d'utiliser un noyau horizontal qui reliera les extrémités des lignes horizontales, mais ne se connectera pas adjacent lignes les unes aux autres.

Voici une esquisse de code (en supposant que l'image d'entrée est stockée dans bw numpy 2D array):

import cv2, numpy as np

kernel = np.ones((1,20), np.uint8)  # note this is a horizontal kernel
d_im = cv2.dilate(bw, kernel, iterations=1)
e_im = cv2.erode(d_im, kernel, iterations=1) 

Ce que vous obtenez est l'image dilatée:
enter image description here

Notez comment les espaces sont fermés, tout en conservant les lignes horizontales distinctes

Et l'image érodée:
enter image description here

Pour supprimer les artefacts créés par dilater/éroder, je suggère d'extraire à nouveau le squelette.
Si vous appliquez une opération morphologique du squelette à l'image érodée, vous pouvez obtenir ce résultat:
enter image description here

Une fois les courbes connectées, vous n'avez pas besoin d'utiliser la segmentation des bassins versants, mais plutôt d'utiliser des composants connectés pour étiqueter chaque courbe.

12
Shai

Étant donné que l'image est déjà monochromatique, vous pouvez utiliser des transformations morphologiques pour fermer les lignes brisées.

Si vous avez besoin d'un exemple, vous pouvez le trouver dans la documentation ici: http://docs.opencv.org/2.4/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.html#closing

Cela fonctionne en dilatant d'abord les zones blanches de l'image, puis en les érodant de la même quantité. Fermer efficacement tous les trous dans les zones blanches. Plus de détails et d'exemples peuvent être trouvés ici: http://docs.opencv.org/2.4/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.html

Cette stratégie nécessite que l'écart dans la ligne brisée soit inférieur à la distance entre les lignes voisines.

Cela ne fonctionnera pas si les lignes se croisent ou si les lignes sont trop proches les unes des autres. Cependant, je pense que cela fonctionnera très bien dans votre exemple.

Vous pouvez également supprimer les artefacts sous la troisième ligne à l'aide de la fonction d'érosion.

4
Mike E

Je travaille sur un problème similaire mais il est plus complexe et à certains endroits les lignes sont très proches donc les transformations morphologiques finissent par les fusionner. Si quelqu'un connaît un autre moyen, veuillez le suggérer. Merci d'avance!

Venant à votre problème. Je pense que vous n'avez même pas besoin d'opérations morphologiques. Comme vous avez déjà squeletté l'image, vous pouvez simplement concevoir un noyau pour détecter les points où les lignes se cassent et rejoindre ces points en utilisant la distance et la pente (dérivée) comme critères. Je ne sais pas si cela fonctionnera à 100% mais vous pouvez l'essayer.

0
Devansh Sharma