Overslaan naar inhoud

Segmentatieobjecten isoleren

Na het uitvoeren van de Segmenttaak is het soms wenselijk om de geïsoleerde objecten uit de inferentieresultaten te halen. Deze handleiding geeft een algemeen recept om dit te doen met behulp van demodus Ultralytics Predict.

Voorbeeld van segmentatie van geïsoleerde objecten

Recept doorloop

  1. Zie het gedeelteUltralytics Snelstartinstallatie voor een korte handleiding voor het installeren van de benodigde bibliotheken.


  2. Een model laden en uitvoeren predict() methode op een bron.

    from ultralytics import YOLO
    
    # Load a model
    model = YOLO("yolov8n-seg.pt")
    
    # Run inference
    results = model.predict()
    

    Geen voorspelargumenten?

    Zonder een bron op te geven, worden de voorbeeldafbeeldingen uit de bibliotheek gebruikt:

    'ultralytics/assets/bus.jpg'
    'ultralytics/assets/zidane.jpg'
    

    Dit is handig om snel te testen met de predict() methode.

    Ga voor meer informatie over segmentatiemodellen naar de Segment Taak pagina. Voor meer informatie over predict() methode, zie Modus voorspellen sectie van de Documentatie.


  3. Herhaal nu de resultaten en de contouren. Voor workflows die een afbeelding in een bestand willen opslaan, moet de bronafbeelding base-name en de detectie class-label worden opgehaald voor later gebruik (optioneel).

    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. Voor meer informatie over het werken met detectieresultaten, zie Kaders voor de modus Voorspellen.
    2. Voor meer informatie over predict() resultaten zie Werken met resultaten voor de modus Voorspellen
    For-lus

    Een enkele afbeelding zal de eerste lus slechts eenmaal doorlopen. Een enkele afbeelding met slechts ├ę├ęn detectie zal elke lus slechts ├ę├ęn keer doorlopen.


  4. Begin met het genereren van een binair masker van de bronafbeelding en teken dan een gevulde contour op het masker. Hierdoor wordt het object geïsoleerd van de andere delen van de afbeelding. Een voorbeeld van bus.jpg voor een van de gedetecteerde person klasseobjecten wordt rechts getoond.

    Binaire maskerafbeelding

    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. Voor meer informatie over c.masks.xy zie Sectie maskers van voorspelmodus.

    2. Hier worden de waarden in np.int32 voor compatibiliteit met drawContours() functie van OpenCV.

    3. De OpenCV drawContours() functie verwacht dat contouren een vorm hebben van [N, 1, 2] vergroot de sectie hieronder voor meer details.

    Uitbreiden om te begrijpen wat er gebeurt bij het defini├źren van de contour variabel.

    • c.masks.xy :: Geeft de co├Ârdinaten van de maskercontourpunten in het formaat (x, y). Raadpleeg voor meer informatie de Sectie maskers van voorspelmodus.

    • .pop() :: Als masks.xy een lijst is die ├ę├ęn element bevat, wordt dit element ge├źxtraheerd met de pop() methode.

    • .astype(np.int32) :: gebruiken masks.xy zal retourneren met een gegevenstype van float32maar dit zal niet compatibel zijn met de OpenCV drawContours() functie, dus dit zal het gegevenstype veranderen in int32 voor compatibiliteit.

    • .reshape(-1, 1, 2) :: Formatteert de gegevens in de gewenste vorm van [N, 1, 2] waarbij N het aantal contourpunten, waarbij elk punt wordt weergegeven door een enkele invoer 1en de invoer bestaat uit 2 waarden. De -1 geeft aan dat het aantal waarden langs deze dimensie flexibel is.

    Uitvouwen voor een uitleg van de drawContours() configuratie.

    • Het inkapselen van de contour variabele tussen vierkante haakjes, [contour]bleek tijdens het testen effectief het gewenste contourmasker te genereren.

    • De waarde -1 gespecificeerd voor de drawContours() De parameter instrueert de functie om alle contouren te tekenen die aanwezig zijn in de afbeelding.

    • De tuple (255, 255, 255) staat voor de kleur wit, wat de gewenste kleur is voor het tekenen van de contour in dit binaire masker.

    • De toevoeging van cv2.FILLED zal alle pixels omsloten door de contour hetzelfde kleuren, in dit geval zullen alle omsloten pixels wit zijn.

    • Zie OpenCV Documentatie op drawContours() voor meer informatie.


  5. Vervolgens zijn er 2 opties om vanaf dit punt verder te gaan met de afbeelding en een vervolgoptie voor elke optie.

    Opties voor objectisolatie

    # Create 3-channel mask
    mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
    
    # Isolate object with binary mask
    isolated = cv2.bitwise_and(mask3ch, img)
    
    Hoe werkt dit?
    • Eerst wordt het binaire masker geconverteerd van een eenkanaalsafbeelding naar een driekanaalsafbeelding. Deze conversie is nodig voor de volgende stap waarin het masker en de originele afbeelding worden gecombineerd. Beide afbeeldingen moeten hetzelfde aantal kanalen hebben om compatibel te zijn met de overvloeier.

    • De originele afbeelding en het binaire driekanaalsmasker worden samengevoegd met de OpenCV-functie bitwise_and(). Deze bewerking behoudt alleen pixelwaarden die groter zijn dan nul (> 0) van beide afbeeldingen. Omdat de maskerpixels groter zijn dan nul (> 0) alleen Binnen het contourgebied zijn de pixels die overblijven van de oorspronkelijke afbeelding de pixels die overlappen met de contour.

    Isoleren met zwarte pixels: Subopties

    Afbeelding op ware grootte

    Er zijn geen extra stappen nodig als je een afbeelding op ware grootte bewaart.

    Voorbeeld op ware grootte Geïsoleerde objectafbeelding Zwarte achtergrond
    Voorbeeld uitvoer op ware grootte

    Afbeelding bijgesneden object

    Extra stappen nodig om de afbeelding zo bij te snijden dat alleen het objectgebied eronder valt.

    Voorbeeld uitsnede geïsoleerd object zwarte achtergrond

    # (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. Voor meer informatie over de resultaten van bounding boxen, zie Sectie Boxen van de modus Voorspellen
    Wat doet deze code?
    • De c.boxes.xyxy.cpu().numpy() oproep haalt de begrenzingskaders op als een NumPy array in de xyxy formaat, waarbij xmin, ymin, xmaxen ymax staan voor de co├Ârdinaten van de rechthoek van het begrenzingskader. Zie Vakken uit de voorspelmodus voor meer informatie.

    • De squeeze() verwijdert onnodige dimensies uit de NumPy array en zorgt ervoor dat deze de verwachte vorm heeft.

    • De co├Ârdinaatwaarden converteren met .astype(np.int32) verandert het gegevenstype van de boxco├Ârdinaten van float32 naar int32waardoor ze geschikt zijn voor het bijsnijden van afbeeldingen met behulp van index slices.

    • Tenslotte wordt het bounding box-gebied uit de afbeelding geknipt met behulp van index slicing. De grenzen worden gedefinieerd door de [ymin:ymax, xmin:xmax] co├Ârdinaten van het detectiebegrenzingskader.

    # Isolate object with transparent background (when saved as PNG)
    isolated = np.dstack([img, b_mask])
    
    Hoe werkt dit?
    • De NumPy dstack() functie (matrixstapeling langs de diepte-as) in combinatie met het gegenereerde binaire masker, wordt een afbeelding met vier kanalen gemaakt. Hierdoor zijn alle pixels buiten de objectcontour transparant bij het opslaan als een PNG bestand.

    Isoleren met transparante pixels: Subopties

    Afbeelding op ware grootte

    Er zijn geen extra stappen nodig als je een afbeelding op ware grootte bewaart.

    Voorbeeld op ware grootte Geïsoleerde objectafbeelding zonder achtergrond
    Voorbeeld uitvoer op ware grootte + transparante achtergrond

    Afbeelding bijgesneden object

    Extra stappen nodig om de afbeelding zo bij te snijden dat alleen het objectgebied eronder valt.

    Voorbeeldsnede Geïsoleerd object zonder achtergrond

    # (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. Voor meer informatie over de resultaten van bounding boxen, zie Sectie Boxen van de modus Voorspellen
    Wat doet deze code?
    • Bij gebruik van c.boxes.xyxy.cpu().numpy()worden de begrenzende vakken geretourneerd als een NumPy array, met behulp van de xyxy box co├Ârdinaten formaat, die overeenkomen met de punten xmin, ymin, xmax, ymax voor de begrenzende box (rechthoek), zie Vakken uit de voorspelmodus voor meer informatie.

    • toevoegen squeeze() zorgt ervoor dat alle vreemde dimensies uit de NumPy array worden verwijderd.

    • De co├Ârdinaatwaarden converteren met .astype(np.int32) verandert het gegevenstype van de boxco├Ârdinaten van float32 naar int32 die compatibel zal zijn bij het bijsnijden van de afbeelding met behulp van index slices.

    • Tot slot wordt het afbeeldingsgebied voor de bounding box bijgesneden met behulp van index slicing, waarbij de grenzen worden ingesteld met behulp van de optie [ymin:ymax, xmin:xmax] co├Ârdinaten van het detectiebegrenzingskader.

    Wat als ik het bijgesneden object inclusief de achtergrond wil?

    Dit is een ingebouwde functie voor de Ultralytics bibliotheek. Zie de save_crop argument voor Voorspellen van modus Inferentie Argumenten voor meer informatie.


  6. Wat je daarna doet, kun je als ontwikkelaar helemaal zelf bepalen. Een basisvoorbeeld van een mogelijke volgende stap (de afbeelding opslaan in een bestand voor toekomstig gebruik) wordt getoond.

    • OPMERKING: deze stap is optioneel en kan worden overgeslagen als dit niet nodig is voor jouw specifieke toepassing.
    Voorbeeld Laatste stap
    # Save isolated object to file
    _ = cv2.imwrite(f"{img_name}_{label}-{ci}.png", iso_crop)
    
    • In dit voorbeeld is de img_name is de basisnaam van het bronafbeeldingsbestand, label de gedetecteerde klassenaam is en ci is de index van de objectdetectie (in het geval van meerdere instanties met dezelfde klassenaam).

Volledige voorbeeldcode

Hier worden alle stappen uit de vorige sectie gecombineerd in ├ę├ęn blok code. Voor herhaald gebruik zou het optimaal zijn om een functie te defini├źren om enkele of alle opdrachten uit te voeren die in de for-lussen, maar dat is een oefening voor de lezer.

from pathlib import Path

import cv2
import numpy as np

from ultralytics import YOLO

m = YOLO("yolov8n-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. De regel die contour is hier samengevoegd tot ├ę├ęn regel, waar het hierboven was opgesplitst in meerdere regels.
  2. Wat hier komt is aan jou!
  3. Zie Voorspelmodus voor meer informatie.
  4. Zie Segmenttaak voor meer informatie.
  5. Meer informatie over Werken met resultaten
  6. Meer informatie over de resultaten van het Segmentatiemasker

FAQ

Hoe isoleer ik objecten met Ultralytics YOLOv8 voor segmentatietaken?

Volg deze stappen om objecten te isoleren met Ultralytics YOLOv8 :

  1. Laad het model en voer de inferentie uit:

    from ultralytics import YOLO
    
    model = YOLO("yolov8n-seg.pt")
    results = model.predict(source="path/to/your/image.jpg")
    
  2. Genereer een binair masker en teken contouren:

    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. Isoleer het object met behulp van het binaire masker:

    mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
    isolated = cv2.bitwise_and(mask3ch, img)
    

Raadpleeg de handleiding over de Voorspelmodus en de Segmenttaak voor meer informatie.

Welke opties zijn beschikbaar voor het opslaan van de geïsoleerde objecten na segmentatie?

Ultralytics YOLOv8 biedt twee hoofdopties voor het opslaan van geïsoleerde objecten:

  1. Met een zwarte achtergrond:

    mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
    isolated = cv2.bitwise_and(mask3ch, img)
    
  2. Met een transparante achtergrond:

    isolated = np.dstack([img, b_mask])
    

Ga voor meer informatie naar het gedeelte Voorspelmodus.

Hoe kan ik geïsoleerde objecten bijsnijden tot hun bounding boxes met Ultralytics YOLOv8 ?

Geïsoleerde objecten bijsnijden tot hun begrenzingskader:

  1. Haal de co├Ârdinaten van de begrenzende box op:

    x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32)
    
  2. Snijd de geïsoleerde afbeelding bij:

    iso_crop = isolated[y1:y2, x1:x2]
    

Meer informatie over bounding box resultaten in de Predict Mode documentatie.

Waarom zou ik Ultralytics YOLOv8 gebruiken voor objectisolatie bij segmentatietaken?

Ultralytics YOLOv8 voorziet:

  • Snelle realtime objectdetectie en segmentatie.
  • Nauwkeurige bounding box en masker generatie voor precieze objectisolatie.
  • Uitgebreide documentatie en gebruiksvriendelijke API voor effici├źnte ontwikkeling.

Verken de voordelen van het gebruik van YOLO in de Segment Task documentatie.

Kan ik geïsoleerde objecten inclusief de achtergrond opslaan met Ultralytics YOLOv8 ?

Ja, dit is een ingebouwde functie in Ultralytics YOLOv8 . Gebruik de save_crop argument in de predict() methode. Bijvoorbeeld:

results = model.predict(source="path/to/your/image.jpg", save_crop=True)

Lees meer over de save_crop argument in de Voorspellen van modus Inferentie Argumenten sectie.



Aangemaakt 2023-11-27, Bijgewerkt 2024-07-05
Auteurs: glenn-jocher (12), IvorZhu331 (1), RizwanMunawar (1), Burhan-Q (1)

Reacties