Isolieren von Segmentierungsobjekten
Nach der Durchführung der Segmentierungsaufgabe ist es manchmal wünschenswert, die isolierten Objekte aus den Inferenz-Ergebnissen zu extrahieren. Dieser Leitfaden bietet eine allgemeine Anleitung, wie dies mit dem Ultralytics Predict-Modus erreicht werden kann.
Exemplarische Vorgehensweise
-
Eine kurze Anleitung zur Installation der erforderlichen Bibliotheken findest du im Abschnitt Ultralytics Schnellstart-Installation.
-
Laden eines Modells und Ausführen
predict()
Methode auf einer Quelle.from ultralytics import YOLO # Load a model model = YOLO("yolo11n-seg.pt") # Run inference results = model.predict()
Keine Vorhersageargumente?
Ohne Angabe einer Quelle werden die Beispielbilder aus der Bibliothek verwendet:
'ultralytics/assets/bus.jpg' 'ultralytics/assets/zidane.jpg'
Dies ist hilfreich für schnelle Tests mit dem
predict()
Methode.Für weitere Informationen zu Segmentierungsmodellen besuchen Sie die Seite Segment Task . Um mehr über die
predict()
Methode zu erfahren, siehe den Abschnitt Predict Mode der Dokumentation.
-
Iterieren Sie nun über die Ergebnisse und die Konturen. Für Workflows, die ein Bild in einer Datei speichern möchten, werden das Quellbild
base-name
und die Erkennungclass-label
zur späteren Verwendung abgerufen (optional).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()]
- Um mehr über das Arbeiten mit Erkennungsergebnissen zu erfahren, siehe Boxes Section for Predict Mode.
- Um mehr über
predict()
Ergebnisse zu erfahren, siehe Working with Results for Predict Mode
For-Loop
Ein einzelnes Bild durchläuft die erste Schleife nur einmal. Ein einzelnes Bild mit nur einer einzigen Erkennung durchläuft jede Schleife nur einmal.
-
Beginnen Sie mit der Generierung einer binären Maske aus dem Quellbild und zeichnen Sie dann eine gefüllte Kontur auf die Maske. Dadurch kann das Objekt von den anderen Teilen des Bildes isoliert werden. Ein Beispiel von
bus.jpg
für eines der erkanntenperson
Klassenobjekte wird rechts gezeigt.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)
-
Für weitere Informationen zu
c.masks.xy
siehe Masks Section from Predict Mode. -
Hier werden die Werte in
np.int32
umgewandelt, um die Kompatibilität mit derdrawContours()
Funktion von OpenCV. -
OpenCV zu gewährleisten.
drawContours()
Funktion erwartet, dass Konturen die Form[N, 1, 2]
Erweitern Sie den Abschnitt unten für weitere Details.
Erweitern, um zu verstehen, was bei der Definition der
contour
Variable geschieht.-
c.masks.xy
:: Stellt die Koordinaten der Maskenkonturpunkte im Format(x, y)
bereit. Weitere Informationen finden Sie im Abschnitt Masks Section from Predict Mode. -.pop()
:: Damasks.xy
eine Liste ist, die ein einzelnes Element enthält, wird dieses Element mitpop()
Methode. -.astype(np.int32)
extrahiert. :: Verwendung vonmasks.xy
wird mit dem Datentypfloat32
zurückgegeben, aber dies ist nicht mit der OpenCV-drawContours()
Funktion kompatibel, daher wird der Datentyp zur Kompatibilität inint32
zur Kompatibilität. -.reshape(-1, 1, 2)
:: Formatiert die Daten in die erforderliche Form[N, 1, 2]
wobeiN
um. Dabei ist die Anzahl der Konturpunkte, wobei jeder Punkt durch einen einzelnen Eintrag1
dargestellt wird und der Eintrag aus2
Werten besteht. Das-1
gibt an, dass die Anzahl der Werte entlang dieser Dimension flexibel ist.Erweitern für eine Erläuterung der
drawContours()
Konfiguration.- Einkapselung der
contour
Variable in eckigen Klammern,[contour]
, wurde als effektiv befunden, um während des Testens die gewünschte Konturmaske zu generieren. - Der Wert-1
für diedrawContours()
Parameter weist die Funktion an, alle im Bild vorhandenen Konturen zu zeichnen. - Dertuple
(255, 255, 255)
stellt die Farbe Weiß dar, die die gewünschte Farbe zum Zeichnen der Kontur in dieser binären Maske ist. - Die Ergänzung voncv2.FILLED
werden alle Pixel, die von der Konturgrenze umschlossen werden, gleichfarbig, in diesem Fall werden alle umschlossenen Pixel weiß. - Siehe OpenCV-Dokumentation zudrawContours()
für weitere Informationen.
-
-
Als Nächstes gibt es 2 Optionen, wie man von diesem Punkt aus mit dem Bild fortfahren kann, und eine nachfolgende Option für jede.
Optionen zur Objektisolierung
Beispiel
# Create 3-channel mask mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR) # Isolate object with binary mask isolated = cv2.bitwise_and(mask3ch, img)
Wie funktioniert das?
-
Zuerst wird die binäre Maske von einem Einkanalbild in ein Dreikanalbild umgewandelt. Diese Umwandlung ist für den nächsten Schritt notwendig, bei dem die Maske und das Originalbild kombiniert werden. Beide Bilder müssen die gleiche Anzahl von Kanälen haben, um mit der Überblendungsoperation kompatibel zu sein.
-
Das Originalbild und die dreikanalige binäre Maske werden mit der OpenCV-Funktion zusammengeführt
bitwise_and()
. Diese Operation behält nur Pixelwerte bei, die größer als Null sind(> 0)
aus beiden Bildern. Da die Maskenpixel größer als Null sind(> 0)
nur innerhalb des Konturbereichs, sind die verbleibenden Pixel aus dem Originalbild diejenigen, die sich mit der Kontur überschneiden.
Isolieren mit schwarzen Pixeln: Unteroptionen
Bild in voller Größe
Es sind keine zusätzlichen Schritte erforderlich, wenn das Bild in voller Größe beibehalten wird.
Beispiel für eine Ausgabe in voller Größe Zugeschnittenes Objektbild
Zusätzliche Schritte erforderlich, um das Bild so zuzuschneiden, dass nur der Objektbereich enthalten ist.
# (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]
- Weitere Informationen zu Bounding-Box-Ergebnissen finden Sie im Abschnitt "Boxes" im Vorhersagemodus.
Was macht dieser Code?
-
Die
c.boxes.xyxy.cpu().numpy()
Aufruf ruft die Bounding Boxes als NumPy-Array imxyxy
Format, wobeixmin
,ymin
,xmax
undymax
die Koordinaten des Begrenzungsrahmenrechtecks darstellen. Siehe Abschnitt "Boxes" im Vorhersagemodus für weitere Details. -
Die
squeeze()
Operation entfernt alle unnötigen Dimensionen aus dem NumPy-Array und stellt sicher, dass es die erwartete Form hat. -
Konvertieren der Koordinatenwerte mit
.astype(np.int32)
ändert den Datentyp der Boxkoordinaten vonfloat32
zuint32
, wodurch sie für das Zuschneiden von Bildern mit Index-Slices kompatibel werden. -
Schließlich wird der Bereich des Begrenzungsrahmens mit Index-Slicing aus dem Bild ausgeschnitten. Die Grenzen werden durch die
[ymin:ymax, xmin:xmax]
Koordinaten des Erkennungs-Begrenzungsrahmens definiert.
# Isolate object with transparent background (when saved as PNG) isolated = np.dstack([img, b_mask])
Wie funktioniert das?
- Verwenden der NumPy
dstack()
Funktion (Array-Stapelung entlang der Tiefenachse) in Verbindung mit der generierten binären Maske erzeugt ein Bild mit vier Kanälen. Dies ermöglicht, dass alle Pixel außerhalb der Objektkontur transparent sind, wenn sie alsPNG
Datei gespeichert werden.
Isolieren mit transparenten Pixeln: Unteroptionen
Bild in voller Größe
Es sind keine zusätzlichen Schritte erforderlich, wenn das Bild in voller Größe beibehalten wird.
Beispiel für eine Ausgabe in voller Größe + transparenter Hintergrund Zugeschnittenes Objektbild
Zusätzliche Schritte erforderlich, um das Bild so zuzuschneiden, dass nur der Objektbereich enthalten ist.
# (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]
- Weitere Informationen zu den Ergebnissen der Begrenzungsrahmen finden Sie im Abschnitt "Boxes" im Vorhersagemodus.
Was macht dieser Code?
-
Bei Verwendung von
c.boxes.xyxy.cpu().numpy()
werden die Begrenzungsrahmen als NumPy-Array zurückgegeben, wobei dasxyxy
Boxkoordinatenformat verwendet wird, das den Punktenxmin, ymin, xmax, ymax
für den Begrenzungsrahmen (Rechteck) entspricht, siehe Abschnitt "Boxes" im Vorhersagemodus für weitere Informationen. -
Das Hinzufügen von
squeeze()
stellt sicher, dass alle überflüssigen Dimensionen aus dem NumPy-Array entfernt werden. -
Konvertieren der Koordinatenwerte mit
.astype(np.int32)
ändert den Datentyp der Boxkoordinaten vonfloat32
zuint32
, wodurch es beim Zuschneiden des Bildes mit Index-Slices kompatibel ist. -
Schließlich wird der Bildbereich für den Begrenzungsrahmen mit Index-Slicing zugeschnitten, wobei die Grenzen mit den
[ymin:ymax, xmin:xmax]
Koordinaten des Erkennungs-Begrenzungsrahmens definiert.
Was ist, wenn ich das zugeschnittene Objekt einschließlich des Hintergrunds haben möchte?
Dies ist eine integrierte Funktion für die Ultralytics Bibliothek. Siehe das
save_crop
Argument für Inferenzargumente für den Vorhersagemodus für Details.
-
-
Was als Nächstes zu tun ist, bleibt ganz Ihnen als Entwickler überlassen. Ein einfaches Beispiel für einen möglichen nächsten Schritt (das Speichern des Bildes zur späteren Verwendung) wird gezeigt.
- HINWEIS: Dieser Schritt ist optional und kann übersprungen werden, wenn er für Ihren speziellen Anwendungsfall nicht erforderlich ist.
Beispiel für den letzten Schritt
# Save isolated object to file _ = cv2.imwrite(f"{img_name}_{label}-{ci}.png", iso_crop)
- In diesem Beispiel ist
img_name
der Basisname der Quellbilddatei,label
der erkannte Klassenname undci
der Index des Objekterkennung durchzuführen (im Falle von mehreren Instanzen mit demselben Klassennamen).
Vollständiger Beispielcode
Hier werden alle Schritte aus dem vorherigen Abschnitt in einem einzigen Codeblock zusammengefasst. Für die wiederholte Verwendung wäre es optimal, eine Funktion zu definieren, die einige oder alle Befehle in den for
-Schleifen ausführt, aber das bleibt dem Leser überlassen.
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)
- Die Zeile, die
contour
füllt, wird hier zu einer einzigen Zeile zusammengefasst, wo sie oben in mehrere aufgeteilt wurde. - Was hier hinkommt, liegt an Ihnen!
- Weitere Informationen finden Sie unter Vorhersagemodus.
- Weitere Informationen finden Sie unter Segmentierungsaufgabe.
- Erfahren Sie mehr über Arbeiten mit Ergebnissen.
- Erfahren Sie mehr über Ergebnisse von Segmentierungsmasken.
FAQ
Wie isoliere ich Objekte mit Ultralytics YOLO11 für Segmentierungsaufgaben?
Um Objekte mit Ultralytics YOLO11 zu isolieren, führen Sie die folgenden Schritte aus:
-
Laden Sie das Modell und führen Sie die Inferenz aus:
from ultralytics import YOLO model = YOLO("yolo11n-seg.pt") results = model.predict(source="path/to/your/image.jpg")
-
Generieren Sie eine binäre Maske und zeichnen Sie Konturen:
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)
-
Isolieren Sie das Objekt mithilfe der binären Maske:
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR) isolated = cv2.bitwise_and(mask3ch, img)
Weitere Informationen finden Sie im Leitfaden zum Vorhersagemodus und zur Segmentierungsaufgabe.
Welche Optionen gibt es zum Speichern der isolierten Objekte nach der Segmentierung?
Ultralytics YOLO11 bietet zwei Hauptoptionen zum Speichern isolierter Objekte:
-
Mit schwarzem Hintergrund:
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR) isolated = cv2.bitwise_and(mask3ch, img)
-
Mit transparentem Hintergrund:
isolated = np.dstack([img, b_mask])
Weitere Informationen finden Sie im Abschnitt Vorhersagemodus.
Wie kann ich isolierte Objekte mit Ultralytics YOLO11 auf ihre Bounding Boxes zuschneiden?
So schneiden Sie isolierte Objekte auf ihre Begrenzungsrahmen zu:
-
Abrufen von Koordinaten des Begrenzungsrahmens:
x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32)
-
Zuschneiden des isolierten Bildes:
iso_crop = isolated[y1:y2, x1:x2]
Erfahren Sie mehr über die Ergebnisse der Begrenzungsrahmen in der Dokumentation zum Vorhersagemodus.
Warum sollte ich Ultralytics YOLO11 für die Objektisolierung in Segmentierungsaufgaben verwenden?
Ultralytics YOLO11 bietet:
- Hochgeschwindigkeits-Echtzeit-Objekterkennung und -Segmentierung.
- Genaue Generierung von Begrenzungsrahmen und Masken für eine präzise Objektisolierung.
- Umfassende Dokumentation und benutzerfreundliche API für eine effiziente Entwicklung.
Entdecken Sie die Vorteile der Verwendung von YOLO in der Dokumentation zur Segmentierungsaufgabe.
Kann ich isolierte Objekte einschließlich des Hintergrunds mit Ultralytics YOLO11 speichern?
Ja, dies ist eine integrierte Funktion in Ultralytics YOLO11. Verwenden Sie das save_crop
Argument in der predict()
Methode. Zum Beispiel:
results = model.predict(source="path/to/your/image.jpg", save_crop=True)
Lesen Sie mehr über die save_crop
Argument in der Inferenzargumente für den Vorhersagemodus Abschnitt.