Comment isoler des objets segmentés avec Ultralytics YOLO#
La segmentation d'instance produit un masque précis au pixel près pour chaque objet détecté, ce qui te permet de détourer chaque objet d'une image de manière autonome. Ce guide te montre comment transformer les résultats de segmentation de Ultralytics YOLO en objets isolés à l'aide du Predict Mode et d'OpenCV, avec soit un fond noir uni, soit un fond transparent pour l'enregistrement au format PNG.
Watch: How to Remove Background and Isolate Objects with Ultralytics YOLO Segmentation & OpenCV in Python 🚀
Pourquoi isoler des objets segmentés ?#
Extraire des objets individuels d'une image ouvre la porte à toute une série de flux de travail en aval :
- Suppression de l'arrière-plan pour des photos de produits, des catalogues ou de l'édition créative.
- Recadrages par objet pour construire des jeux de données de classification à partir de tes détections.
- Traitement ciblé pour que les étapes ultérieures comme l'OCR, l'analyse des couleurs ou la mesure ne voient que l'objet, et non la scène environnante.
- Export PNG transparent pour composer des objets sur de nouveaux arrière-plans.
Cette méthode fonctionne avec n'importe quel modèle de segmentation de Ultralytics YOLO et se déroule en quatre étapes : exécuter l'inférence → extraire chaque contour → isoler l'objet → enregistrer le résultat.
Exécuter l'inférence de segmentation#
Installe les bibliothèques requises, puis charge un modèle de segmentation (le suffixe -seg, nécessaire pour produire des masques) et lance la prédiction sur ton image source :
from ultralytics import YOLO
# Load a segmentation model
model = YOLO("yolo26n-seg.pt")
# Run inference on a source
results = model.predict(source="path/to/image.jpg")Si tu appelles model.predict() sans source, Ultralytics utilise par défaut les exemples d'images fournis avec le paquet (bus.jpg et zidane.jpg), ce qui est pratique pour tester rapidement le flux de travail.
Extraire les contours des objets#
Chaque élément de results correspond à une image, et l'itération sur un résultat renvoie une détection à la fois. Pour chaque détection, copie l'image originale, lis l'étiquette de classe et dessine le contour du masque de l'objet sur un masque binaire vierge. La région blanche de ce masque indique exactement quels pixels appartiennent à l'objet.
Les extraits de cette section et de la suivante s'exécutent à l'intérieur de la boucle de détection ci-dessous ; le script complet et prêt à être copié se trouve dans Full Example.
{ width="240", align="right" }
from pathlib import Path
import cv2
import numpy as np
for r in results:
img = np.copy(r.orig_img)
img_name = Path(r.path).stem # source image base-name
# Iterate each detected object in the image
for ci, c in enumerate(r):
label = c.names[c.boxes.cls.tolist().pop()] # class name
# Build a binary mask and draw the object contour onto it
b_mask = np.zeros(img.shape[:2], np.uint8)
contour = c.masks.xy[0].astype(np.int32).reshape(-1, 1, 2)
cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)c.masks.xy[0]renvoie le contour du masque sous forme de coordonnées de points(x, y)pour l'objet dans ce résultat à détection unique..astype(np.int32)convertit les points defloat32, que ledrawContours()d'OpenCV n'accepte pas..reshape(-1, 1, 2)redimensionne les points dans la disposition[N, 1, 2]attendue pardrawContours(), oùNest le nombre de points du contour.
Passer [contour] avec l'indice -1 dessine tous les points du contour fourni, et cv2.FILLED remplit chaque pixel inclus en blanc.
Isoler l'objet#
Une fois le masque binaire prêt, combine-le avec l'image originale. Il existe deux styles courants, selon ce que tu souhaites obtenir pour l'arrière-plan :
Convertis le masque en trois canaux et ne garde que les pixels qui chevauchent l'objet. Tout ce qui se trouve en dehors du contour devient noir :
# Isolate object with a black background
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
isolated = cv2.bitwise_and(mask3ch, img)Pour ne conserver que la zone de l'objet au lieu de l'image en taille réelle, découpe-la selon la boîte englobante de la détection :
# Bounding box coordinates
x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
# Crop the isolated image to the object region
iso_crop = isolated[y1:y2, x1:x2]C'est intégré. Passe save_crop=True à predict() et Ultralytics enregistre automatiquement les recadrages de boîtes englobantes, sans nécessiter de masquage.
Enregistrer le résultat (optionnel)#
Ce que tu fais avec chaque objet isolé dépend de toi. Une étape suivante courante consiste à l'écrire sur le disque pour une utilisation ultérieure :
# Save the isolated object to file
cv2.imwrite(f"{img_name}_{label}-{ci}.png", isolated)Ici, img_name est le nom de base de l'image source, label est le nom de la classe et ci est l'indice de détection, de sorte que plusieurs instances de la même classe obtiennent des noms de fichiers uniques. Remplace isolated par iso_crop si tu as appliqué le recadrage optionnel ci-dessus.
Exemple complet#
Le script ci-dessous combine chaque étape en un seul bloc exécutable. Il utilise un fond noir par défaut ; modifie la ligne unique marquée en np.dstack([img, b_mask]) pour obtenir un PNG transparent à la place :
from pathlib import Path
import cv2
import numpy as np
from ultralytics import YOLO
model = YOLO("yolo26n-seg.pt")
results = model.predict(source="path/to/image.jpg")
for r in results:
img = np.copy(r.orig_img)
img_name = Path(r.path).stem
for ci, c in enumerate(r):
label = c.names[c.boxes.cls.tolist().pop()]
# Build a binary mask from the object contour
b_mask = np.zeros(img.shape[:2], np.uint8)
contour = c.masks.xy[0].astype(np.int32).reshape(-1, 1, 2)
cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)
# Isolate the object (black background)
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
isolated = cv2.bitwise_and(mask3ch, img) # transparent PNG: isolated = np.dstack([img, b_mask])
# Save or add your custom post-processing here
cv2.imwrite(f"{img_name}_{label}-{ci}.png", isolated)
# Optional: crop to the bounding box before saving
# x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
# cv2.imwrite(f"{img_name}_{label}-{ci}.png", isolated[y1:y2, x1:x2])Pour une utilisation répétée, enveloppe le corps de la boucle dans une fonction afin de pouvoir l'appeler sur de nombreuses images.
Conclusion#
Tu disposes désormais d'une méthode complète pour isoler des objets segmentés avec Ultralytics YOLO : exécuter l'inférence, construire un masque binaire à partir de chaque contour, puis extraire l'objet sur un fond noir ou transparent et éventuellement le rogner selon sa boîte englobante. Explore la documentation complète de Segment Task et du Predict Mode pour adapter le flux de travail à tes propres classes.
FAQ#
Il existe deux styles principaux. Pour un fond noir, convertis le masque en trois canaux et utilise
cv2.bitwise_and(). Pour un fond transparent (lors de l'enregistrement au format PNG), empile le masque en tant que quatrième canal alpha avecnp.dstack([img, b_mask]). Les deux sont présentés dans Isolate the Object.Lis les coordonnées de la boîte englobante à partir de la détection et découpe l'image isolée :
x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32) iso_crop = isolated[y1:y2, x1:x2]Apprends-en davantage sur les résultats des boîtes englobantes dans la documentation du Predict Mode.
Ultralytics YOLO fournit une segmentation d'instances rapide et en temps réel avec une génération précise de masques et de boîtes englobantes, ainsi qu'une API Python simple qui transforme les résultats d'inférence en objets isolés avec quelques lignes de code OpenCV.
Oui. Utilise l'argument
save_cropdanspredict()pour enregistrer les recadrages de boîtes englobantes avec leur fond d'origine :results = model.predict(source="path/to/your/image.jpg", save_crop=True)Pour en savoir plus, consulte la section Predict Mode Inference Arguments.
Charge un modèle de segmentation, exécute l'inférence, construis un masque binaire à partir du contour de chaque détection et combine-le avec l'image originale :
Consulte la section Full Example pour voir la boucle complète par détection.