Isolamento degli oggetti di segmentazione
Dopo aver eseguito la Segment Task, a volte è auspicabile estrarre gli oggetti isolati dai risultati dell'inferenza. Questa guida fornisce una ricetta generica su come realizzare questo obiettivo utilizzando la Predict Mode di Ultralytics.
Guida pratica alla ricetta
-
Consulta la sezione di installazione rapida di Ultralytics per una rapida panoramica sull'installazione delle librerie richieste.
-
Carica un modello ed esegui
predict()
method su una source.from ultralytics import YOLO # Load a model model = YOLO("yolo11n-seg.pt") # Run inference results = model.predict()
Nessun argomento di previsione?
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
predict()
metodo.Per ulteriori informazioni sui modelli di segmentazione, visitare la pagina Segment Task page. Per saperne di più su
predict()
metodo, vedi Modalità di previsione sezione della documentazione.
-
Ora scorri i risultati e i contorni. Per i flussi di lavoro che desiderano salvare un'immagine su file, l'immagine sorgente
base-name
e il rilevamentoclass-label
vengono recuperati per un uso successivo (opzionale).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()]
- Per ulteriori informazioni sull'utilizzo dei risultati del detection, consultare la Sezione Riquadri per la modalità Predict.
- Per saperne di più su
predict()
risultati vedi Lavorare con i risultati per la modalità Predict
For-Loop
Una singola immagine itererà il primo ciclo solo una volta. Una singola immagine con una sola rilevazione itererà ogni ciclo solo una volta.
-
Inizia generando una maschera binaria dall'immagine sorgente e poi disegna un contorno riempito sulla maschera. Questo permetterà all'oggetto di essere isolato dalle altre parti dell'immagine. Un esempio da
bus.jpg
per uno degli elementi rilevatiperson
gli oggetti classe sono mostrati sulla destra.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 maggiori informazioni su
c.masks.xy
vedi Sezione Maschere dalla Modalità Predict. -
Qui i valori vengono convertiti in
np.int32
per la compatibilità condrawContours()
funzione da OpenCV. -
OpenCV
drawContours()
La funzione prevede che i contorni abbiano una forma di[N, 1, 2]
espandi la sezione sottostante per maggiori dettagli.
Espandi per capire cosa succede quando si definisce il
contour
variabile.-
c.masks.xy
:: Fornisce le coordinate dei punti del contorno della maschera nel formato(x, y)
. Per maggiori dettagli, fare riferimento al Sezione Maschere dalla Modalità Predict. -.pop()
:: Comemasks.xy
è una lista contenente un singolo elemento; questo elemento viene estratto usando il/lapop()
metodo. -.astype(np.int32)
:: Utilizzandomasks.xy
restituirà un tipo di dati difloat32
, ma questo non sarà compatibile con OpenCVdrawContours()
funzione, quindi questo cambierà il tipo di dati inint32
per la compatibilità. -.reshape(-1, 1, 2)
:: Riformatta i dati nella forma richiesta di[N, 1, 2]
doveN
è il numero di punti di contorno, con ogni punto rappresentato da una singola voce1
, e la voce è composta da2
valori. La-1
indica che il numero di valori lungo questa dimensione è flessibile.Espandi per una spiegazione del
drawContours()
configurazione.- Incapsulando il
contour
variabile tra parentesi quadre,[contour]
, si è rivelato efficace nel generare la maschera di contorno desiderata durante i test. - Il valore-1
specificato per ildrawContours()
parametro indica alla funzione di disegnare tutti i contorni presenti nell'immagine. - Iltuple
(255, 255, 255)
rappresenta il colore bianco, che è il colore desiderato per disegnare il contorno in questa maschera binaria. - L'aggiunta dicv2.FILLED
colorerà tutti i pixel racchiusi dal contorno allo stesso modo, in questo caso, tutti i pixel racchiusi saranno bianchi. - Vedi Documentazione OpenCV sudrawContours()
per maggiori informazioni.
-
-
Successivamente, ci sono 2 opzioni su come procedere con l'immagine da questo punto e una successiva opzione per ciascuna.
Opzioni di isolamento degli oggetti
Esempio
# 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 OpenCV
bitwise_and()
. Questa operazione conserva solo valori dei pixel superiori a zero(> 0)
da entrambe le immagini. Poiché i pixel della maschera sono maggiori di zero(> 0)
solo all'interno della regione del contorno, i pixel rimanenti dall'immagine originale sono quelli che si sovrappongono al contorno.
Isolare con pixel neri: Sotto-opzioni
Immagine a dimensione intera
Non sono necessari passaggi aggiuntivi se si mantiene l'immagine a dimensione intera.
Esempio di output a dimensione intera Immagine dell'oggetto ritagliato
Passaggi aggiuntivi necessari per ritagliare l'immagine in modo da includere solo la regione dell'oggetto.
# (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, consulta la Sezione Box della Modalità Predict.
Cosa fa questo codice?
-
Il
c.boxes.xyxy.cpu().numpy()
la chiamata recupera le caselle di delimitazione come array NumPy nelxyxy
formato, dovexmin
,ymin
,xmax
, eymax
rappresentano le coordinate del rettangolo di delimitazione. Vedi Sezione Riquadri dalla modalità Predict per maggiori dettagli. -
Il
squeeze()
L'operazione rimuove qualsiasi dimensione non necessaria dall'array NumPy, assicurando che abbia la forma prevista. -
Conversione dei valori delle coordinate utilizzando
.astype(np.int32)
modifica il tipo di dati delle coordinate della casella dafloat32
aint32
, rendendoli compatibili per il ritaglio delle immagini utilizzando le sezioni di indice. -
Infine, la regione del riquadro di delimitazione viene ritagliata dall'immagine utilizzando l'indicizzazione a fette. I limiti sono definiti dal
[ymin:ymax, xmin:xmax]
coordinate del riquadro di delimitazione del rilevamento.
# Isolate object with transparent background (when saved as PNG) isolated = np.dstack([img, b_mask])
Come funziona?
- Utilizzando NumPy
dstack()
La funzione (stacking di array lungo l'asse della profondità) in combinazione con la maschera binaria generata, creerà un'immagine con quattro canali. Ciò consente a tutti i pixel al di fuori del contorno dell'oggetto di essere trasparenti quando si salva comePNG
file.
Isolare con pixel trasparenti: Sotto-opzioni
Immagine a dimensione intera
Non sono necessari passaggi aggiuntivi se si mantiene l'immagine a dimensione intera.
Esempio di output a dimensione intera + sfondo trasparente Immagine dell'oggetto ritagliato
Passaggi aggiuntivi necessari per ritagliare l'immagine in modo da includere solo la regione dell'oggetto.
# (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, consulta la Sezione Box della Modalità Predict.
Cosa fa questo codice?
-
Quando si utilizza
c.boxes.xyxy.cpu().numpy()
, i riquadri di delimitazione vengono restituiti come array NumPy, utilizzando ilxyxy
formato delle coordinate del riquadro, che corrispondono ai puntixmin, ymin, xmax, ymax
per il riquadro di delimitazione (rettangolo), vedere Sezione Riquadri dalla modalità Predict per maggiori informazioni. -
Aggiunta
squeeze()
assicura che qualsiasi dimensione estranea venga rimossa dall'array NumPy. -
Conversione dei valori delle coordinate utilizzando
.astype(np.int32)
modifica il tipo di dati delle coordinate della casella dafloat32
aint32
che sarà compatibile quando si ritaglia l'immagine usando le sezioni di indice. -
Infine, la regione dell'immagine per il riquadro di delimitazione viene ritagliata utilizzando l'indicizzazione a fette, dove i limiti sono impostati utilizzando il
[ymin:ymax, xmin:xmax]
coordinate del riquadro di delimitazione del rilevamento.
Cosa succede se voglio l'oggetto ritagliato incluso lo sfondo?
Questa è una funzionalità integrata per la libreria Ultralytics. Vedi il
save_crop
argomento per Argomenti di inferenza della modalità di previsione per i dettagli.
-
-
Cosa fare dopo è interamente lasciato a te come sviluppatore. Viene mostrato un esempio base di un possibile passo successivo (salvare l'immagine in un file per un uso futuro).
- NOTA: questo passaggio è facoltativo e può essere saltato se non è necessario per il caso d'uso specifico.
Esempio di fase finale
# Save isolated object to file _ = cv2.imwrite(f"{img_name}_{label}-{ci}.png", iso_crop)
- In questo esempio, il
img_name
è il nome base del file immagine sorgente,label
è il nome della classe rilevata, eci
è l'indice del il rilevamento di oggetti (in caso di più istanze 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 nel for
-loop, ma questo è un esercizio lasciato al lettore.
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)
- La riga che popola
contour
è combinato in un'unica riga qui, mentre sopra era diviso in più righe. - Ciò che viene inserito qui dipende da te!
- Consulta la Modalità Predict per ulteriori informazioni.
- Consulta Segment Task per maggiori informazioni.
- Scopri di più su Come lavorare con i risultati
- Scopri di più sui Risultati della maschera di segmentazione
FAQ
Come posso isolare gli oggetti utilizzando Ultralytics YOLO11 per attività di segmentazione?
Per isolare gli oggetti utilizzando Ultralytics YOLO11, segui questi passaggi:
-
Carica il modello ed esegui l'inferenza:
from ultralytics import YOLO model = YOLO("yolo11n-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)
-
Isolare l'oggetto usando la maschera binaria:
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR) isolated = cv2.bitwise_and(mask3ch, img)
Consulta la guida sulla Modalità Predict e l'Attività Segment per maggiori informazioni.
Quali opzioni sono disponibili per salvare gli oggetti isolati dopo la segmentazione?
Ultralytics YOLO11 offre due opzioni principali per il salvataggio di 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 maggiori dettagli, visita la sezione Modalità Predict.
Come posso ritagliare oggetti isolati alle loro bounding box utilizzando Ultralytics YOLO11?
Per ritagliare gli oggetti isolati alle loro bounding box:
-
Recupera le coordinate del riquadro di delimitazione:
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 riquadri di delimitazione nella documentazione della Modalità di previsione.
Perché dovrei usare Ultralytics YOLO11 per l'isolamento di oggetti in attività di segmentazione?
Ultralytics YOLO11 offre:
- Rilevamento e segmentazione di oggetti in tempo reale ad alta velocità.
- Generazione accurata di riquadri di delimitazione e maschere per un isolamento preciso degli oggetti.
- Documentazione completa e API di facile utilizzo per uno sviluppo efficiente.
Esplora i vantaggi dell'utilizzo di YOLO nella documentazione sull'attività di segmentazione.
Posso salvare oggetti isolati incluso lo sfondo utilizzando Ultralytics YOLO11?
Sì, questa è una funzionalità integrata in Ultralytics YOLO11. Usa l'argomento save_crop
argomento nel predict()
metodo. Per esempio:
results = model.predict(source="path/to/your/image.jpg", save_crop=True)
Scopri di più su save_crop
argomento nel Argomenti di inferenza della modalità di previsione sezione.