Isolamento di oggetti di segmentazione
Dopo aver eseguito il Segment Task, a volte è utile estrarre gli oggetti isolati dai risultati dell'inferenza. Questa guida fornisce una procedura generica su come realizzarlo utilizzando la Predict Mode di Ultralytics.
Watch: How to Remove Background and Isolate Objects with Ultralytics YOLO Segmentation & OpenCV in Python 🚀
Procedura guidata
-
Consulta la sezione di installazione rapida di Ultralytics per una guida rapida all'installazione delle librerie richieste.
-
Carica un modello ed esegui il metodo
predict()su una sorgente.from ultralytics import YOLO # Load a model model = YOLO("yolo26n-seg.pt") # Run inference results = model.predict()
Senza specificare una sorgente, verranno utilizzate le immagini di esempio dalla libreria:
'ultralytics/assets/bus.jpg'
'ultralytics/assets/zidane.jpg'Questo è utile per test rapidi con il metodo predict().
Per ulteriori informazioni sui modelli di segmentazione, visita la pagina Segment Task. Per saperne di più sul metodo predict(), consulta la sezione Predict Mode della documentazione.
***
Ora itera sui risultati e sui contorni. Per i flussi di lavoro che richiedono il salvataggio di un'immagine su file, il base-name dell'immagine sorgente e la class-label del rilevamento vengono recuperati per un uso successivo (opzionale).
```{ .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)Ciclo For
Una singola immagine itererà il primo ciclo solo una volta. Una singola immagine con un solo rilevamento itererà ogni ciclo solo una volta.
-
Inizia generando una maschera binaria dall'immagine sorgente e poi disegna un contorno riempito sulla maschera. Questo permetterà di isolare l'oggetto dalle altre parti dell'immagine. Un esempio da
bus.jpgper uno degli oggetti rilevati della classepersonè mostrato sulla destra.{ 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)-
Per ulteriori informazioni su
c.masks.xyvedi la sezione Maschere della Predict Mode. -
Qui i valori vengono convertiti in
np.int32per la compatibilità con la funzionedrawContours()di OpenCV. -
La funzione
drawContours()di OpenCV si aspetta che i contorni abbiano una forma[N, 1, 2]; espandi la sezione sottostante per maggiori dettagli.
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.
-
-
Successivamente ci sono 2 opzioni su come procedere con l'immagine da questo punto e un'opzione conseguente per ciascuna.
Opzioni di isolamento oggetto
# Create 3-channel mask
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
# Isolate object with binary mask
isolated = cv2.bitwise_and(mask3ch, img)Come funziona?
-
Innanzitutto, la maschera binaria viene convertita da un'immagine a canale singolo a un'immagine a tre canali. Questa conversione è necessaria per il passaggio successivo in cui la maschera e l'immagine originale vengono combinate. Entrambe le immagini devono avere lo stesso numero di canali per essere compatibili con l'operazione di fusione.
-
L'immagine originale e la maschera binaria a tre canali vengono unite utilizzando la funzione
bitwise_and()di OpenCV. Questa operazione mantiene solo i valori dei pixel superiori a zero(> 0)da entrambe le immagini. Poiché i pixel della maschera sono superiori a zero(> 0)solo all'interno della regione del contorno, i pixel rimanenti dall'immagine originale sono quelli che si sovrappongono al contorno.
Isolamento con pixel neri: Sotto-opzioni
Immagine a dimensione intera
Non sono richiesti ulteriori passaggi se si mantiene l'immagine a dimensione intera.
Immagine dell'oggetto ritagliata
Sono richiesti passaggi aggiuntivi per ritagliare l'immagine in modo da includere solo la regione dell'oggetto.
{ 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]- Per maggiori informazioni sui risultati dei bounding box, vedi la sezione Box della Predict Mode
Cosa fa questo codice?
-
La chiamata
c.boxes.xyxy.cpu().numpy()recupera i bounding box come un array NumPy nel formatoxyxy, dovexmin,ymin,xmaxeymaxrappresentano le coordinate del rettangolo del bounding box. Vedi la sezione Box della Predict Mode per maggiori dettagli. -
L'operazione
squeeze()rimuove eventuali dimensioni non necessarie dall'array NumPy, assicurando che abbia la forma prevista. -
Convertire i valori delle coordinate usando
.astype(np.int32)cambia il tipo di dato delle coordinate del box dafloat32aint32, rendendole compatibili per il ritaglio dell'immagine tramite slice di indice. -
Infine, la regione del bounding box viene ritagliata dall'immagine utilizzando lo slicing di indice. I limiti sono definiti dalle coordinate
[ymin:ymax, xmin:xmax]del bounding box di rilevamento.
Cosa succede se voglio l'oggetto ritagliato **incluso** lo sfondo?
Questa è una funzionalità integrata della libreria Ultralytics. Vedi l'argomento save_crop per gli argomenti di inferenza della Predict Mode per i dettagli.
- Cosa fare dopo spetta interamente a te come sviluppatore. Viene mostrato un esempio base di un possibile passo successivo (salvataggio dell'immagine su file per un uso futuro).
- NOTA: questo passaggio è opzionale e può essere saltato se non richiesto per il tuo caso d'uso specifico.
Esempio passo finale
# Save isolated object to file
_ = cv2.imwrite(f"{img_name}_{label}-{ci}.png", iso_crop)- In questo esempio,
img_nameè il nome base del file immagine sorgente,labelè il nome della classe rilevata eciè l'indice del rilevamento oggetto (in caso di istanze multiple con lo stesso nome di classe).
Codice di esempio completo
Qui, tutti i passaggi della sezione precedente sono combinati in un unico blocco di codice. Per un uso ripetuto, sarebbe ottimale definire una funzione per eseguire alcuni o tutti i comandi contenuti nei cicli for, ma questo è un esercizio lasciato al lettore.
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 riga che popola
contourè combinata in una sola riga qui, mentre sopra era divisa in più parti. - {==Cosa inserire qui dipende da te!==}
- Vedi Predict Mode per informazioni aggiuntive.
- Vedi Segment Task per maggiori informazioni.
- Scopri di più su Lavorare con i risultati
- Scopri di più sui Risultati della maschera di segmentazione
FAQ
Come posso isolare oggetti utilizzando Ultralytics YOLO26 per compiti di segmentazione?
Per isolare oggetti utilizzando Ultralytics YOLO26, segui questi passaggi:
-
Carica il modello ed esegui l'inferenza:
from ultralytics import YOLO model = YOLO("yolo26n-seg.pt") results = model.predict(source="path/to/your/image.jpg") -
Genera una maschera binaria e disegna i contorni:
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) -
Isola l'oggetto usando la maschera binaria:
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR) isolated = cv2.bitwise_and(mask3ch, img)
Fai riferimento alla guida su Predict Mode e al Segment Task per maggiori informazioni.
Quali opzioni sono disponibili per salvare gli oggetti isolati dopo la segmentazione?
Ultralytics YOLO26 offre due opzioni principali per salvare gli oggetti isolati:
-
Con uno sfondo nero:
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR) isolated = cv2.bitwise_and(mask3ch, img) -
Con uno sfondo trasparente:
isolated = np.dstack([img, b_mask])
Per ulteriori dettagli, visita la sezione Predict Mode.
Come posso ritagliare gli oggetti isolati nei loro bounding box utilizzando Ultralytics YOLO26?
Per ritagliare gli oggetti isolati nei loro bounding box:
-
Recupera le coordinate del bounding box:
x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32) -
Ritaglia l'immagine isolata:
iso_crop = isolated[y1:y2, x1:x2]
Scopri di più sui risultati dei bounding box nella documentazione Predict Mode.
Perché dovrei usare Ultralytics YOLO26 per l'isolamento degli oggetti nei compiti di segmentazione?
Ultralytics YOLO26 fornisce:
- Rilevamento e segmentazione di oggetti in tempo reale ad alta velocità.
- Accurati bounding box e generazione di maschere per un isolamento preciso degli oggetti.
- Documentazione completa e API facile da usare per uno sviluppo efficiente.
Esplora i vantaggi dell'utilizzo di YOLO nella documentazione del Segment Task.
Posso salvare oggetti isolati includendo lo sfondo utilizzando Ultralytics YOLO26?
Sì, questa è una funzionalità integrata in Ultralytics YOLO26. Usa l'argomento save_crop nel metodo predict(). Per esempio:
results = model.predict(source="path/to/your/image.jpg", save_crop=True)Leggi di più sull'argomento save_crop nella sezione Argomenti di inferenza della Predict Mode.