Isoler des objets de segmentation
Après avoir exécuté la tâche de segmentation, il est parfois souhaitable d'extraire les objets isolés des résultats d'inférence. Ce guide fournit une méthode générique pour y parvenir en utilisant le Mode Predict d'Ultralytics.
Watch: How to Remove Background and Isolate Objects with Ultralytics YOLO Segmentation & OpenCV in Python 🚀
Procédure pas à pas
-
Consulte la section Installation rapide d'Ultralytics pour obtenir un guide rapide sur l'installation des bibliothèques nécessaires.
-
Charge un modèle et exécute la méthode
predict()sur une source.from ultralytics import YOLO # Load a model model = YOLO("yolo26n-seg.pt") # Run inference results = model.predict()
Si aucune source n'est spécifiée, les images d'exemple de la bibliothèque seront utilisées :
'ultralytics/assets/bus.jpg'
'ultralytics/assets/zidane.jpg'Ceci est utile pour effectuer des tests rapides avec la méthode predict().
Pour plus d'informations sur les modèles de segmentation, visite la page Tâche de segmentation. Pour en savoir plus sur la méthode predict(), consulte la section Mode Predict de la documentation.
***
Maintenant, itère sur les résultats et les contours. Pour les flux de travail qui nécessitent d'enregistrer une image dans un fichier, le base-name de l'image source et le class-label de la détection sont récupérés pour une utilisation ultérieure (optionnel).
```{ .py .annotate }
from pathlib import Path
import numpy as np
# (2) Iterate detection results (helpful for multiple images)
for r in results:
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. To learn more about working with detection results, see [Boxes Section for Predict Mode](../modes/predict.md#boxes).
2. To learn more about `predict()` results see [Working with Results for Predict Mode](../modes/predict.md#working-with-results)Boucle For
Une seule image ne fera itérer la première boucle qu'une seule fois. Une seule image contenant une seule détection fera itérer chaque boucle uniquement une fois.
-
Commence par générer un masque binaire à partir de l'image source, puis dessine un contour rempli sur le masque. Cela permettra d'isoler l'objet des autres parties de l'image. Un exemple à partir de
bus.jpgpour l'un des objets détectés de la classepersonest affiché sur la droite.{ width="240", align="right" }
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)-
Pour plus d'informations sur
c.masks.xy, consulte la section Masques du Mode Predict. -
Ici, les valeurs sont converties en
np.int32pour une compatibilité avec la fonctiondrawContours()d'OpenCV. -
La fonction
drawContours()d'OpenCV attend que les contours aient une forme de[N, 1, 2]. Développe la section ci-dessous pour plus de détails.
Expand to understand what is happening when defining the
contourvariable.- `c.masks.xy` :: Provides the coordinates of the mask contour points in the format `(x, y)`. For more details, refer to the [Masks Section from Predict Mode](../modes/predict.md#masks). - `.pop()` :: As `masks.xy` is a list containing a single element, this element is extracted using the `pop()` method. - `.astype(np.int32)` :: Using `masks.xy` will return with a data type of `float32`, but this won't be compatible with the OpenCV `drawContours()` function, so this will change the data type to `int32` for compatibility. - `.reshape(-1, 1, 2)` :: Reformats the data into the required shape of `[N, 1, 2]` where `N` is the number of contour points, with each point represented by a single entry `1`, and the entry is composed of `2` values. The `-1` denotes that the number of values along this dimension is flexible.
Expand for an explanation of the
drawContours()configuration.- Encapsulating the `contour` variable within square brackets, `[contour]`, was found to effectively generate the desired contour mask during testing. - The value `-1` specified for the `drawContours()` parameter instructs the function to draw all contours present in the image. - The `tuple` `(255, 255, 255)` represents the color white, which is the desired color for drawing the contour in this binary mask. - The addition of `cv2.FILLED` will color all pixels enclosed by the contour boundary the same, in this case, all enclosed pixels will be white. - See [OpenCV Documentation on `drawContours()`](https://docs.opencv.org/4.8.0/d6/d6e/group__imgproc__draw.html#ga746c0625f1781f1ffc9056259103edbc) for more information.
-
-
Ensuite, il existe 2 options pour savoir comment avancer avec l'image à partir de ce point, ainsi qu'une option ultérieure pour chacune d'elles.
Options d'isolation d'objet
# 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 converti d'une image à canal unique vers 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 uniquement les valeurs de pixels supérieures à zéro(> 0)des deux images. Comme les pixels du masque sont supérieurs à zéro(> 0)uniquement dans la région du contour, les pixels conservés de l'image originale sont ceux qui se chevauchent avec le contour.
Isoler avec des pixels noirs : sous-options
Image pleine taille
Aucune étape supplémentaire n'est requise si tu conserves l'image en taille réelle.
Image d'objet rognée
Étapes supplémentaires requises pour rogner l'image afin d'inclure uniquement la région de l'objet.
{ align="right" }
# (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]- Pour plus d'informations sur les résultats des bounding boxes, consulte la section Boîtes du Mode Predict
Que fait ce code ?
-
L'appel
c.boxes.xyxy.cpu().numpy()récupère les boîtes englobantes sous forme de tableau NumPy au formatxyxy, oùxmin,ymin,xmaxetymaxreprésentent les coordonnées du rectangle de la boîte englobante. Consulte la section Boîtes du Mode Predict pour plus de détails. -
L'opération
squeeze()supprime toutes les dimensions inutiles du tableau NumPy, garantissant qu'il a la forme attendue. -
La conversion des valeurs de coordonnées à l'aide de
.astype(np.int32)change le type de données des coordonnées de la boîte defloat32àint32, les rendant compatibles pour le rognage d'image à l'aide de tranches d'index. -
Enfin, la région de la boîte englobante est rognée à partir de l'image en utilisant le découpage par index. Les limites sont définies par les coordonnées
[ymin:ymax, xmin:xmax]de la boîte englobante de détection.
Que faire si je veux l'objet rogné **y compris** l'arrière-plan ?
Ceci est une fonctionnalité intégrée de la bibliothèque Ultralytics. Consulte l'argument save_crop pour les Arguments d'inférence du Mode Predict pour plus de détails.
- Ce que tu fais ensuite dépend entièrement de toi 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é.
- NOTE : cette étape est optionnelle et peut être ignorée si elle n'est pas nécessaire pour ton 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,
img_nameest le nom de base du fichier image source,labelest le nom de la classe détectée, etciest l'index de la détection d'objet (dans le cas de multiples instances 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 effectuer tout ou partie des commandes contenues dans les boucles for, mais c'est un exercice laissé au lecteur.
from pathlib import Path
import cv2
import numpy as np
from ultralytics import YOLO
m = YOLO("yolo26n-seg.pt") # (4)!
res = m.predict(source="path/to/image.jpg") # (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]
# Add your custom post-processing here (2)- La ligne remplissant
contourest combinée en une seule ligne ici, alors qu'elle était divisée en plusieurs lignes ci-dessus. - {==Ce que tu mets ici dépend de toi!==}
- Consulte le Mode Predict pour des informations supplémentaires.
- Consulte la Tâche de segmentation pour plus d'informations.
- En savoir plus sur Travailler avec les résultats
- En savoir plus sur les Résultats de masque de segmentation
FAQ
Comment isoler des objets en utilisant Ultralytics YOLO26 pour des tâches de segmentation ?
Pour isoler des objets en utilisant Ultralytics YOLO26, suis ces étapes :
-
Charger le modèle et exécuter l'inférence :
from ultralytics import YOLO model = YOLO("yolo26n-seg.pt") results = model.predict(source="path/to/your/image.jpg") -
Générer un masque binaire et dessiner des 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) -
Isoler l'objet à l'aide du masque binaire :
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR) isolated = cv2.bitwise_and(mask3ch, img)
Consulte le guide sur le Mode Predict 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 YOLO26 offre deux options principales pour enregistrer des objets isolés :
-
Avec un arrière-plan noir :
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR) isolated = cv2.bitwise_and(mask3ch, img) -
Avec un arrière-plan transparent :
isolated = np.dstack([img, b_mask])
Pour plus de détails, visite la section Mode Predict.
Comment puis-je rogner des objets isolés sur leurs boîtes englobantes en utilisant Ultralytics YOLO26 ?
Pour rogner des objets isolés sur leurs boîtes englobantes :
-
Récupérer les coordonnées de la boîte englobante :
x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32) -
Rogner l'image isolée :
iso_crop = isolated[y1:y2, x1:x2]
Apprends-en plus sur les résultats des boîtes englobantes dans la documentation du Mode Predict.
Pourquoi devrais-je utiliser Ultralytics YOLO26 pour l'isolation d'objets dans les tâches de segmentation ?
Ultralytics YOLO26 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 une isolation précise des objets.
- Documentation complète et API facile à utiliser pour un développement efficace.
Explore les avantages de l'utilisation de YOLO dans la documentation de la tâche de segmentation.
Puis-je enregistrer des objets isolés en incluant l'arrière-plan en utilisant Ultralytics YOLO26 ?
Oui, il s'agit d'une fonctionnalité intégrée dans Ultralytics YOLO26. Utilise l'argument save_crop dans la méthode predict(). Par exemple :
results = model.predict(source="path/to/your/image.jpg", save_crop=True)Lis-en plus sur l'argument save_crop dans la section Arguments d'inférence du Mode Predict.