Passer au contenu

Isolation des objets de segmentation

Après avoir effectué la tâche de segmentation, il est parfois souhaitable d'extraire les objets isolés des résultats de l'inférence. Ce guide fournit une recette générique sur la façon d'y parvenir en utilisant le mode de prédiction Ultralytics.

Exemple de segmentation d'objet isolé

Procédure pas à pas de la recette

  1. Consultez la section Installation rapide d'Ultralytics pour une présentation rapide de l'installation des bibliothèques requises.


  2. Charger un modèle et l'exécuter predict() méthode sur une source.

    from ultralytics import YOLO
    
    # Load a model
    model = YOLO("yolo11n-seg.pt")
    
    # Run inference
    results = model.predict()
    

    Aucun argument de prédiction ?

    Si aucune source n'est spécifiée, les exemples d'images de la bibliothèque seront utilisés :

    'ultralytics/assets/bus.jpg'
    'ultralytics/assets/zidane.jpg'
    

    Ceci est utile pour des tests rapides avec le predict() méthode.

    Pour plus d'informations sur les modèles de segmentation, consultez le Tâche Segment page. Pour en savoir plus sur predict() méthode, voir Mode de prédiction section de la documentation.


  3. Maintenant, itérez sur les résultats et les contours. Pour les flux de travail qui souhaitent enregistrer une image dans un fichier, l'image source base-name et la détection class-label sont récupérées pour une utilisation ultérieure (facultatif).

    from pathlib import Path
    
    import numpy as np
    
    # (2) Iterate detection results (helpful for multiple images)
    for r in res:
        img = np.copy(r.orig_img)
        img_name = Path(r.path).stem  # source image base-name
    
        # Iterate each object contour (multiple detections)
        for ci, c in enumerate(r):
            # (1) Get detection class name
            label = c.names[c.boxes.cls.tolist().pop()]
    
    1. Pour en savoir plus sur l'utilisation des résultats de détection, consultez la Section Boîtes pour le mode Predict.
    2. Pour en savoir plus sur predict() résultats voir Travailler avec les résultats pour le mode Predict
    Boucle For

    Une seule image n'itérera la première boucle qu'une seule fois. Une seule image avec une seule détection n'itérera chaque boucle qu'une seule fois.


  4. Commencez par générer un masque binaire à partir de l'image source, puis dessinez un contour rempli sur le masque. Cela permettra d'isoler l'objet des autres parties de l'image. Un exemple de bus.jpg pour l'un des éléments détectés person les objets de classe sont affichés à droite.

    Image de masque binaire

    import cv2
    
    # Create binary mask
    b_mask = np.zeros(img.shape[:2], np.uint8)
    
    # (1) Extract contour result
    contour = c.masks.xy.pop()
    # (2) Changing the type
    contour = contour.astype(np.int32)
    # (3) Reshaping
    contour = contour.reshape(-1, 1, 2)
    
    
    # Draw contour onto mask
    _ = cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)
    
    1. Pour plus d'informations sur c.masks.xy voir Section des masques du mode de prédiction.

    2. Ici, les valeurs sont converties en np.int32 pour la compatibilité avec drawContours() fonction de module DNN d'OpenCV.

    3. OpenCV drawContours() la fonction attend que les contours aient une forme de [N, 1, 2] développer la section ci-dessous pour plus de détails.

    Développer pour comprendre ce qui se passe lors de la définition du contour variable.

    - c.masks.xy :: Fournit les coordonnées des points de contour du masque au format (x, y). Pour plus de détails, consultez la section Section des masques du mode de prédiction. - .pop() :: En tant que masks.xy est une liste contenant un seul élément, cet élément est extrait en utilisant le pop() méthode. - .astype(np.int32) :: En utilisant masks.xy renverra un type de données de float32, mais cela ne sera pas compatible avec OpenCV drawContours() fonction, cela changera donc le type de données en int32 pour la compatibilité. - .reshape(-1, 1, 2) :: Reformate les données dans la forme requise de [N, 1, 2]N est le nombre de points de contour, chaque point étant représenté par une seule entrée 1, et l'entrée est composée de 2 valeurs. Le -1 indique que le nombre de valeurs le long de cette dimension est flexible.

    Développer pour une explication du drawContours() configuration.

    - Encapsulation du contour variable entre crochets, [contour], s'est avéré efficace pour générer le masque de contour souhaité pendant les tests. - La valeur -1 spécifié pour le drawContours() paramètre indique à la fonction de dessiner tous les contours présents dans l'image. - Le tuple (255, 255, 255) représente la couleur blanche, qui est la couleur souhaitée pour dessiner le contour dans ce masque binaire. - L'ajout de cv2.FILLED coloriera tous les pixels enfermés par la limite du contour de la même couleur, dans ce cas, tous les pixels enfermés seront blancs. - Voir Documentation OpenCV sur drawContours() pour plus d'informations.


  5. Ensuite, il existe 2 options quant à la manière de traiter l'image à partir de ce point, ainsi qu'une option subséquente pour chacune.

    Options d'isolation d'objets

    Exemple

    # Create 3-channel mask
    mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
    
    # Isolate object with binary mask
    isolated = cv2.bitwise_and(mask3ch, img)
    
    Comment cela fonctionne-t-il ?
    • Tout d'abord, le masque binaire est d'abord converti d'une image à canal unique en une image à trois canaux. Cette conversion est nécessaire pour l'étape suivante où le masque et l'image originale sont combinés. Les deux images doivent avoir le même nombre de canaux pour être compatibles avec l'opération de fusion.

    • L'image originale et le masque binaire à trois canaux sont fusionnés à l'aide de la fonction OpenCV bitwise_and(). Cette opération conserve seulement valeurs de pixel supérieures à zéro (> 0) des deux images. Puisque les pixels du masque sont supérieurs à zéro (> 0) seulement dans la région du contour, les pixels restants de l'image originale sont ceux qui chevauchent le contour.

    Isoler avec des pixels noirs : Sous-options

    Image en taille réelle

    Aucune étape supplémentaire n'est requise si vous conservez l'image en taille réelle.

    Exemple d'image d'objet isolé en taille réelle avec fond noir
    Exemple de sortie en taille réelle

    Image de l'objet rogné

    Étapes supplémentaires nécessaires pour recadrer l'image afin d'inclure uniquement la région de l'objet.

    Exemple d'image d'objet isolé recadrée Fond noir

    # (1) Bounding box coordinates
    x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
    # Crop image to object region
    iso_crop = isolated[y1:y2, x1:x2]
    

    1. Pour plus d'informations sur les résultats des boîtes englobantes, consultez la Section Boîtes du Mode Predict.
    Que fait ce code ?
    • L'argument c.boxes.xyxy.cpu().numpy() l'appel récupère les boîtes englobantes sous forme de tableau NumPy dans le xyxy format, où xmin, ymin, xmax, et ymax représentent les coordonnées du rectangle de la boîte englobante. Voir Section Boîtes du mode Prédiction pour plus de détails.

    • L'argument squeeze() supprime toutes les dimensions inutiles du tableau NumPy, garantissant ainsi qu'il a la forme attendue.

    • Conversion des valeurs de coordonnées à l'aide de .astype(np.int32) modifie le type de données des coordonnées de la boîte de float32 à int32, les rendant compatibles pour le recadrage d'images à l'aide de tranches d'index.

    • Enfin, la région de la boîte englobante est recadrée à partir de l'image en utilisant le découpage d'index. Les limites sont définies par le [ymin:ymax, xmin:xmax] coordonnées de la boîte englobante de détection.

    # Isolate object with transparent background (when saved as PNG)
    isolated = np.dstack([img, b_mask])
    
    Comment cela fonctionne-t-il ?
    • Utilisation de NumPy dstack() fonction (empilement de tableaux le long de l'axe de profondeur) en conjonction avec le masque binaire généré, créera une image avec quatre canaux. Cela permet à tous les pixels en dehors du contour de l'objet d'être transparents lors de l'enregistrement en tant que PNG .

    Isoler avec des pixels transparents : Sous-options

    Image en taille réelle

    Aucune étape supplémentaire n'est requise si vous conservez l'image en taille réelle.

    Exemple d'image d'objet isolé en taille réelle sans arrière-plan
    Exemple de sortie en taille réelle + arrière-plan transparent

    Image de l'objet rogné

    Étapes supplémentaires nécessaires pour recadrer l'image afin d'inclure uniquement la région de l'objet.

    Exemple d'image recadrée d'un objet isolé sans arrière-plan

    # (1) Bounding box coordinates
    x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
    # Crop image to object region
    iso_crop = isolated[y1:y2, x1:x2]
    

    1. Pour plus d'informations sur les résultats des boîtes englobantes, consultez la Section Boîtes du Mode Predict.
    Que fait ce code ?
    • Lors de l'utilisation c.boxes.xyxy.cpu().numpy(), les boîtes englobantes sont retournées sous forme de tableau NumPy, en utilisant le xyxy format des coordonnées de la boîte, qui correspondent aux points xmin, ymin, xmax, ymax pour le cadre de délimitation (rectangle), voir Section Boîtes du mode Prédiction pour plus d'informations.

    • Ajout de squeeze() garantit que toutes les dimensions superflues sont supprimées du tableau NumPy.

    • Conversion des valeurs de coordonnées à l'aide de .astype(np.int32) modifie le type de données des coordonnées de la boîte de float32 à int32 qui sera compatible lors du recadrage de l'image à l'aide de tranches d'index.

    • Enfin, la région de l'image pour la boîte englobante est recadrée à l'aide du découpage d'index, où les limites sont définies à l'aide du [ymin:ymax, xmin:xmax] coordonnées de la boîte englobante de détection.

    Que faire si je veux l’objet recadré y compris l’arrière-plan ?

    Il s'agit d'une fonctionnalité intégrée à la bibliothèque Ultralytics. Voir le save_crop argument pour Arguments d'inférence du mode de prédiction pour plus de détails.


  6. Ce qu’il faut faire ensuite vous est entièrement laissé en tant que développeur. Un exemple de base d’une prochaine étape possible (enregistrer l’image dans un fichier pour une utilisation future) est présenté.

    • REMARQUE : cette étape est facultative et peut être ignorée si elle n’est pas requise pour votre cas d’utilisation spécifique.
    Exemple d'étape finale
    # Save isolated object to file
    _ = cv2.imwrite(f"{img_name}_{label}-{ci}.png", iso_crop)
    
    • Dans cet exemple, le img_name est le nom de base du fichier image source, label est le nom de la classe détectée, et ci est l'indice du détection d'objets (en cas d'instances multiples avec le même nom de classe).

Code d'exemple complet

Ici, toutes les étapes de la section précédente sont combinées en un seul bloc de code. Pour une utilisation répétée, il serait optimal de définir une fonction pour exécuter tout ou partie des commandes contenues dans le for-boucles, mais c'est un exercice laissé au lecteur.

from pathlib import Path

import cv2
import numpy as np

from ultralytics import YOLO

m = YOLO("yolo11n-seg.pt")  # (4)!
res = m.predict()  # (3)!

# Iterate detection results (5)
for r in res:
    img = np.copy(r.orig_img)
    img_name = Path(r.path).stem

    # Iterate each object contour (6)
    for ci, c in enumerate(r):
        label = c.names[c.boxes.cls.tolist().pop()]

        b_mask = np.zeros(img.shape[:2], np.uint8)

        # Create contour mask (1)
        contour = c.masks.xy.pop().astype(np.int32).reshape(-1, 1, 2)
        _ = cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)

        # Choose one:

        # OPTION-1: Isolate object with black background
        mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
        isolated = cv2.bitwise_and(mask3ch, img)

        # OPTION-2: Isolate object with transparent background (when saved as PNG)
        isolated = np.dstack([img, b_mask])

        # OPTIONAL: detection crop (from either OPT1 or OPT2)
        x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
        iso_crop = isolated[y1:y2, x1:x2]

        # TODO your actions go here (2)
  1. La ligne de remplissage contour est combiné en une seule ligne ici, alors qu'il était divisé en plusieurs ci-dessus.
  2. Ce qui se trouve ici dépend de vous !
  3. Consultez le mode Predict pour plus d'informations.
  4. Consultez la tâche Segment pour plus d'informations.
  5. En savoir plus sur l'utilisation des résultats
  6. En savoir plus sur les résultats des masques de segmentation

FAQ

Comment isoler des objets à l’aide d’Ultralytics YOLO11 pour les tâches de segmentation ?

Pour isoler des objets à l'aide d'Ultralytics YOLO11, suivez ces étapes :

  1. Charger le modèle et exécuter l'inférence :

    from ultralytics import YOLO
    
    model = YOLO("yolo11n-seg.pt")
    results = model.predict(source="path/to/your/image.jpg")
    
  2. Générer un masque binaire et dessiner les contours :

    import cv2
    import numpy as np
    
    img = np.copy(results[0].orig_img)
    b_mask = np.zeros(img.shape[:2], np.uint8)
    contour = results[0].masks.xy[0].astype(np.int32).reshape(-1, 1, 2)
    cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)
    
  3. Isoler l'objet à l'aide du masque binaire :

    mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
    isolated = cv2.bitwise_and(mask3ch, img)
    

Consultez le guide sur le mode de prédiction et la tâche de segmentation pour plus d'informations.

Quelles options sont disponibles pour enregistrer les objets isolés après la segmentation ?

Ultralytics YOLO11 offre deux options principales pour enregistrer les objets isolés :

  1. Avec un arrière-plan noir :

    mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
    isolated = cv2.bitwise_and(mask3ch, img)
    
  2. Avec un arrière-plan transparent :

    isolated = np.dstack([img, b_mask])
    

Pour plus de détails, consultez la section Mode Predict.

Comment puis-je recadrer les objets isolés sur leurs boîtes englobantes à l'aide d'Ultralytics YOLO11 ?

Pour recadrer les objets isolés sur leurs boîtes englobantes :

  1. Récupérer les coordonnées des boîtes englobantes :

    x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32)
    
  2. Rogner l'image isolée :

    iso_crop = isolated[y1:y2, x1:x2]
    

En savoir plus sur les résultats des boîtes englobantes dans la documentation du mode Prédiction.

Pourquoi devrais-je utiliser Ultralytics YOLO11 pour l'isolation d'objets dans les tâches de segmentation ?

Ultralytics YOLO11 fournit :

  • Haute vitesse de détection et de segmentation d'objets en temps réel.
  • Génération précise de boîtes englobantes et de masques pour un isolement précis des objets.
  • Documentation complète et API facile à utiliser pour un développement efficace.

Explorez les avantages de l'utilisation de YOLO dans la documentation Segment Task.

Puis-je enregistrer des objets isolés, y compris l'arrière-plan, en utilisant Ultralytics YOLO11 ?

Oui, il s'agit d'une fonctionnalité intégrée à Ultralytics YOLO11. Utilisez l'argument save_crop argument dans le predict() méthode. Par exemple :

results = model.predict(source="path/to/your/image.jpg", save_crop=True)

En savoir plus sur le save_crop argument dans le Arguments d'inférence du mode de prédiction section.



📅 Créé il y a 1 an ✏️ Mis à jour il y a 2 mois

Commentaires