web-dev-qa-db-fra.com

étiquetage des composants connectés en python

Comment implémenter l'étiquetage des composants connectés dans python avec cv ouvert? Ceci est un exemple d'image:

J'ai besoin d'un étiquetage de composant connecté pour séparer les objets sur une image en noir et blanc.

10
Willy Andika Putra

Les doc OpenCV 3.0 pour connectedComponents() ne mentionnent pas Python mais il est en fait implémenté. Voir par exemple this SO question . Sur OpenCV 3.4.0 et supérieur, les documents incluent les signatures Python, comme on peut le voir sur les documents maîtres actuels) .

L'appel de fonction est simple: retval, labels = cv2.connectedComponents(img) et vous pouvez spécifier un paramètre connectivity pour vérifier la connectivité à 4 ou 8 voies (par défaut). La différence est que la connectivité à 4 voies vérifie simplement les pixels supérieur, inférieur, gauche et droit et voit s'ils se connectent; 8 voies vérifie si l'un des huit pixels voisins se connecte. Si vous avez des connexions diagonales (comme vous le faites ici), vous devez spécifier connectivity=8. Notez qu'il numérote simplement chaque composant et leur donne des étiquettes entières croissantes commençant à 0. Ainsi, tous les zéros sont connectés, tous ceux sont connectés, etc. Si vous souhaitez les visualiser, vous pouvez mapper ces nombres à des couleurs spécifiques. J'aime les mapper sur différentes teintes, les combiner en une image HSV, puis les convertir en BGR pour les afficher. Voici un exemple avec votre image:

import cv2
import numpy as np

img = cv2.imread('eGaIy.jpg', 0)
img = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)[1]  # ensure binary
ret, labels = cv2.connectedComponents(img)

def imshow_components(labels):
    # Map component labels to hue val
    label_hue = np.uint8(179*labels/np.max(labels))
    blank_ch = 255*np.ones_like(label_hue)
    labeled_img = cv2.merge([label_hue, blank_ch, blank_ch])

    # cvt to BGR for display
    labeled_img = cv2.cvtColor(labeled_img, cv2.COLOR_HSV2BGR)

    # set bg label to black
    labeled_img[label_hue==0] = 0

    cv2.imshow('labeled.png', labeled_img)
    cv2.waitKey()

imshow_components(labels)

Labeled image

35
alkasm

Mon adaptation du CCL en 2D est:

1) Convertissez l'image en image 1/0, 1 étant les pixels de l'objet et 0 étant les pixels d'arrière-plan.

2) Créez un algorithme CCL 2 passes en implémentant l'algorithme Union-Find avec compression passe. Vous pouvez voir plus ici .

Dans la première passe de cette implémentation CCL, vous vérifiez les pixels voisins, dans le cas où votre pixel cible est un pixel objet, et comparez leur étiquette entre eux afin de pouvoir générer des équivalences entre eux. Vous affectez le moins d'étiquette, de ces pixels voisins qui sont des pixels d'objets (étiquette> 0) à votre pixel cible. De cette façon, vous affectez non seulement une étiquette d'objet à votre pixesl cible (étiquette> 0), mais vous créez également une liste d'équivalences.

2) Dans la deuxième passe, vous parcourez tous les pixels et modifiez leur étiquette précédente par l'étiquette de son étiquette parent en regardant simplement la table équivalente stockée dans votre classe Union-Find.

3) J'ai implémenté une passe supplémentaire pour que les étiquettes suivent un ordre séquentiel (1,2,3,4 ....) au lieu d'un ordre aléatoire (23,45,1, ...). Cela implique de changer les étiquettes "nom" juste à des fins esthétiques.

0
pedro_galher