Segmentacja instancji

Segmentacja instancji lokalizuje każdą instancję obiektu i zwraca dla niej maskę na poziomie pikseli razem z ramką, klasą i wskaźnikiem zwracanym przez detektor. Kluczem zadania jest segment.

Definicja

Segmentacja instancji jest detekcją rozszerzoną o kształt. Każda instancja obiektu nadal otrzymuje ramkę, klasę i wskaźnik, a dodatkowo binarną maskę obejmującą należące do niej piksele. Maski mogą się nakładać, a piksele nienależące do żadnego obiektu pozostają nieprzypisane. Odróżnia to zadanie od segmentacji semantycznej i segmentacji panoptycznej.

segment jest kanonicznym kluczem zadania, a sufiks -seg w nazwie pliku checkpointu je wybiera. Dlatego podczas wczytywania opublikowanych wag nie trzeba podawać task=.

Funkcja predict() wypełnia result.masks razem z result.boxes. .data jest stosem (N, H, W) na płótnie oryginalnego obrazu, którego wiersze są wyrównane z ramkami. Maska i należy więc do ramki i. .xy przekształca każdą maskę w jej największy kontur zewnętrzny jako tablicę pikseli (P, 2), a .xyn zwraca ten sam znormalizowany kontur.

Modele

Cztery rodziny obsługują zarówno trenowanie, jak i predykcję masek: RF-DETR, EdgeCrafter, D-FINE oraz RTMDet. RF-DETR wymaga własnego zestawu zależności pip install "libreyolo[rfdetr]", a pozostałe trzy działają z pakietem bazowym.

Mask R-CNN przewiduje, waliduje i eksportuje maski, ale jego funkcja train() zgłasza NotImplementedError.

EoMT przewiduje i waliduje maski, ale również nie obsługuje trenowania, a zakres jego eksportu jest jeszcze węższy. export() przyjmuje wyłącznie zadanie semantyczne i zgłasza NotImplementedError dla segment oraz panoptic, ponieważ nie zdefiniowano wymaganego przez te zadania kontraktu masek zapytań w środowisku uruchomieniowym. EoMT należy używać do masek instancji w Pythonie, a nie przez wyeksportowany graf.

Osobna grupa wykonuje segmentację na podstawie promptu zamiast listy klas. Kliknięcie, ramka lub fraza wybiera obiekt, a model zwraca jego maskę. W ten sposób działają SAM, SAM 2, SAM 3, MobileSAM, EdgeTAM i PicoSAM3, a także SenseNova-Vision, którego segmentacja jest referencyjna i przyjmuje frazę nazywającą jeden obiekt. Modele te są wczytywane przez własne funkcje fabrykujące i zestawy zależności, a ich strony zawierają dokładne wywołania.

Predykcja

Przy pierwszym użyciu wagi są pobierane z Hugging Face i zapisywane w lokalnej pamięci podręcznej.

Python
from libreyolo import LibreYOLO, SAMPLE_IMAGE # Sufiks -seg w nazwie pliku wybiera głowicę masek, więc argument task# nie jest potrzebny.model = LibreYOLO("LibreDFINEn-seg.pt")result = model(SAMPLE_IMAGE, save=True) print(result.masks.data.shape)   # (N, H, W), jedna maska na detekcjęprint(result.boxes.xyxy.shape)   # (N, 4), te same N wierszy
CLI
libreyolo predict model=LibreDFINEn-seg.pt save=True \  source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpg
Kontury masek
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreDFINEn-seg.pt")result = model(SAMPLE_IMAGE) # .xy jest listą konturów pikselowych (P, 2), a .xyn tych samych znormalizowanych konturów.for name, contour in zip(result.boxes.cls, result.masks.xy):    print(result.names[int(name)], contour.shape)
Inna rodzina, to samo wywołanie
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreRTMDets-seg.pt")result = model(SAMPLE_IMAGE) print(result.masks.data.shape)

conf i max_det kształtują dane wyjściowe tak samo jak w detekcji, a maski są filtrowane razem z ramkami, do których należą. Informacje o źródłach, streamingu i obsłudze wyników zawiera strona predykcji.

Format zbioru danych

Układ jest taki sam jak dla detekcji. Każdy obraz ma jeden plik etykiet .txt, znajdowany przez zamianę images na labels w ścieżce obrazu i zmianę rozszerzenia.

dataset/
  data.yaml
  images/
    train/000001.jpg
    val/000101.jpg
  labels/
    train/000001.txt
    val/000101.txt

Zmienia się zawartość wiersza. Segment składa się z indeksu klasy i następującego po nim płaskiego wielokąta:

<class_id> <x1> <y1> ... <xN> <yN>

Wymagane są co najmniej trzy punkty, więc liczba współrzędnych po indeksie klasy musi być parzysta i wynosić co najmniej sześć, a wielokąt nie może być zdegenerowany. Współrzędne są wartościami float w zakresie [0, 1] względem szerokości i wysokości oryginalnego obrazu. Pięciopolowy wiersz detekcji jest również akceptowany w zbiorze danych segmentacji i odczytywany jako segment prostokątny. Dzięki temu zbiór zawierający wyłącznie ramki można wczytać bez etapu konwersji.

Plik YAML jest taki sam jak dla detekcji:

yaml
path: dataset
train: images/train
val: images/val
names:
  0: person
  1: bicycle

Natywny format JSON COCO również działa. Należy dodać mapowanie annotations od nazwy podziału do pliku JSON, a ścieżka podziału wskazuje katalog główny obrazów.

Trenowanie

Python
from libreyolo import LibreYOLO # Kontynuuje od opublikowanych wag segmentacji, łącznie z głowicą masek.# data musi wskazywać zbiór danych, którego etykiety zawierają wielokąty.model = LibreYOLO("LibreDFINEn-seg.pt")model.train(data="my-dataset.yaml", epochs=50, imgsz=640, batch=8, lr0=2e-4)
CLI
libreyolo train model=LibreDFINEn-seg.pt data=my-dataset.yaml \  epochs=50 imgsz=640 batch=8 lr0=2e-4
Z wag detekcji
# Wagi detekcji nie zawierają głowicy masek, dlatego jest to jawny transfer:# głowica rozpoczyna bez wytrenowania. Zezwala na to podanie task=segment.libreyolo train model=LibreDFINEn.pt data=my-dataset.yaml \  task=segment epochs=50 imgsz=640

Domyślnie trenowanie jest kontynuowane z opublikowanego checkpointu -seg. Można rozpocząć od wag detekcji, ale jest to celowy transfer. Wagi te nie zawierają głowicy masek, więc rozpoczyna ona bez wytrenowania, a przekazanie task=segment zezwala na tę zamianę. Informacje o zbiorach danych, augmentacji, wielu GPU i modułach rejestrujących zawiera strona trenowania.

Walidacja

Funkcja val() zwraca zwykły słownik kluczy metrics/. Ramki i maski są oceniane osobno za pomocą oceny COCO, a wyniki masek są wynikami głównymi.

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreDFINEn-seg.pt")metrics = model.val(data="my-dataset.yaml") print(metrics["metrics/mAP50-95"])       # maskiprint(metrics["metrics/mAP50-95(M)"])    # maski, jawnieprint(metrics["metrics/mAP50-95(B)"])    # ramki
CLI
libreyolo val model=LibreDFINEn-seg.pt data=my-dataset.yaml

Klucze bez sufiksu zawierają wyniki masek: metrics/mAP50-95, metrics/mAP50, metrics/mAP75, następnie metrics/mAP_small, metrics/mAP_medium i metrics/mAP_large według powierzchni obiektu oraz metrics/AR1, metrics/AR10, metrics/AR100, metrics/AR_small, metrics/AR_medium i metrics/AR_large dla średniego recall. metrics/AR_max_det i metrics/max_det zapisują limit detekcji użyty w uruchomieniu.

Cztery wartości są również publikowane z jawnym sufiksem, (M) dla maski i (B) dla ramki, dzięki czemu porównanie nie zależy od tego, którą wartość dana rodzina uznała za główną: metrics/mAP50-95(M) i metrics/mAP50-95(B), metrics/mAP50(M) i metrics/mAP50(B), metrics/precision(M) i metrics/precision(B), metrics/recall(M) i metrics/recall(B). To zadanie nie ma klucza metrics/precision ani metrics/recall bez sufiksu.

Klucze precision i recall należy interpretować ostrożnie. Zachowano je dla zgodności wstecznej i są aliasami, a nie punktem pracy. metrics/precision(M) zawiera tę samą wartość co metrics/mAP50-95(M), a metrics/recall(M) tę samą wartość co AR masek przy 100 detekcjach. Sufiks (B) działa tak samo dla ramek. Wykreślenie tej pary zgłasza jedną wartość dwukrotnie.

Eksport

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreDFINEn-seg.pt")model.export(format="onnx", imgsz=640)
CLI
libreyolo export model=LibreDFINEn-seg.pt format=onnx imgsz=640
Użycie wyeksportowanego pliku
from libreyolo import LibreYOLO, SAMPLE_IMAGE # Funkcja fabrykująca wybiera ścieżkę na podstawie sufiksu pliku, więc# wyeksportowany artefakt wczytuje się jak checkpoint i zwraca ten sam obiekt Results.model = LibreYOLO("LibreDFINEn-seg.onnx")result = model(SAMPLE_IMAGE) print(result.masks.data.shape)

Wyeksportowany artefakt wczytuje się ponownie przez LibreYOLO() na podstawie sufiksu pliku. Plik .onnx lub .engine działa więc jak checkpoint i zwraca ten sam obiekt Results. Zakres segmentacji jest węższy niż zakres detekcji w tej samej rodzinie. Macierz na stronie każdego modelu jest generowana ze zweryfikowanego zestawu i podaje przyczynę niedostępności formatu. Formaty, ich zestawy zależności i ograniczenia opisuje strona eksportu i wdrożenia.

Zweryfikowano z LibreYOLO v1.5.0.