Zum Inhalt springen

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.

Beispiel für isolierte Objektsegmentierung

Exemplarische Vorgehensweise

  1. Eine kurze Anleitung zur Installation der erforderlichen Bibliotheken findest du im Abschnitt Ultralytics Schnellstart-Installation.


  2. 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.


  3. 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 Erkennung class-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()]
    
    1. Um mehr über das Arbeiten mit Erkennungsergebnissen zu erfahren, siehe Boxes Section for Predict Mode.
    2. 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.


  4. 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 erkannten person Klassenobjekte wird rechts gezeigt.

    Binäres Maskenbild

    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)
    
    1. Für weitere Informationen zu c.masks.xy siehe Masks Section from Predict Mode.

    2. Hier werden die Werte in np.int32 umgewandelt, um die Kompatibilität mit der drawContours() Funktion von OpenCV.

    3. 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() :: Da masks.xy eine Liste ist, die ein einzelnes Element enthält, wird dieses Element mit pop() Methode. - .astype(np.int32) extrahiert. :: Verwendung von masks.xy wird mit dem Datentyp float32zurückgegeben, aber dies ist nicht mit der OpenCV- drawContours() Funktion kompatibel, daher wird der Datentyp zur Kompatibilität in int32 zur Kompatibilität. - .reshape(-1, 1, 2) :: Formatiert die Daten in die erforderliche Form [N, 1, 2] wobei N um. Dabei ist die Anzahl der Konturpunkte, wobei jeder Punkt durch einen einzelnen Eintrag 1dargestellt wird und der Eintrag aus 2 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 die drawContours() Parameter weist die Funktion an, alle im Bild vorhandenen Konturen zu zeichnen. - Der tuple (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 von cv2.FILLED werden alle Pixel, die von der Konturgrenze umschlossen werden, gleichfarbig, in diesem Fall werden alle umschlossenen Pixel weiß. - Siehe OpenCV-Dokumentation zu drawContours() für weitere Informationen.


  5. 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 ein isoliertes Objektbild in voller Größe mit schwarzem Hintergrund
    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.

    Beispiel für ein zugeschnittenes isoliertes Objektbild mit schwarzem Hintergrund

    # (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]
    

    1. 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 im xyxy Format, wobei xmin, ymin, xmaxund ymax 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 von float32 zu int32, 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 als PNG 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 ein isoliertes Objektbild in voller Größe ohne Hintergrund
    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.

    Beispiel für ein zugeschnittenes isoliertes Objektbild ohne Hintergrund

    # (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]
    

    1. 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 das xyxy Boxkoordinatenformat verwendet wird, das den Punkten xmin, 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 von float32 zu int32 , 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.


  6. 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 und ci 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)
  1. Die Zeile, die contour füllt, wird hier zu einer einzigen Zeile zusammengefasst, wo sie oben in mehrere aufgeteilt wurde.
  2. Was hier hinkommt, liegt an Ihnen!
  3. Weitere Informationen finden Sie unter Vorhersagemodus.
  4. Weitere Informationen finden Sie unter Segmentierungsaufgabe.
  5. Erfahren Sie mehr über Arbeiten mit Ergebnissen.
  6. 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:

  1. 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")
    
  2. 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)
    
  3. 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:

  1. Mit schwarzem Hintergrund:

    mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
    isolated = cv2.bitwise_and(mask3ch, img)
    
  2. 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:

  1. Abrufen von Koordinaten des Begrenzungsrahmens:

    x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32)
    
  2. 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.



📅 Erstellt vor 1 Jahr ✏️ Aktualisiert vor 2 Monaten

Kommentare