D-FINE

Transformer detekcyjny, który przedstawia regresję ramki jako rozkład prawdopodobieństwa dla każdej jej krawędzi, udoskonalany między warstwami dekodera. LibreYOLO obsługuje go w detekcji i segmentacji instancji.

Zadania
detection, instance segmentation
Rozmiary
n, s, m, l, x at 640 px
Instalacja
pip install libreyolo
Poziom obsługi
Główny, od wersji v1.1.0. Główne trenowalne detektory: otrzymują funkcje po modelach flagowych w tej samej fali wydań.
Projekt źródłowy
D-FINE, autorzy: University of Science and Technology of China, licencja: Apache-2.0. Publikacja, kod źródłowy
Licencje
Kod: Apache-2.0, wagi: Apache-2.0. Użycie komercyjne

Instalacja

D-FINE nie wymaga opcjonalnego dodatku. Wszystkie importowane elementy znajdują się w instalacji bazowej.

bash
pip install libreyolo

Wyjątkiem jest dostrajanie adapterów z lora=True, które wymaga dodatku lora.

bash
pip install "libreyolo[lora]"

Predykcja

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

Python
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreDFINEn.pt")result = model(SAMPLE_IMAGE, save=True) for box in result.boxes:    print(box.cls, box.conf, box.xyxy)
CLI
libreyolo predict model=LibreDFINEn.pt source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpg save=True
Segmentacja instancji
from libreyolo import LibreYOLO, SAMPLE_IMAGE # Sufiks -seg w nazwie pliku wybiera głowicę masek, więc argument# zadania nie jest tutaj potrzebny.model = LibreYOLO("LibreDFINEn-seg.pt")result = model(SAMPLE_IMAGE, save=True) print(result.masks.data.shape)

Zwracany obiekt Results jest taki sam dla każdej rodziny, dlatego zamiana detektora wymaga zmiany jednego wiersza. Nazwa pliku z sufiksem -seg automatycznie wybiera zadanie segmentacji, a result.masks zawiera wtedy maski instancji obok ramek. Argumenty conf i max_det filtrują wybór zapytań. Argument iou jest akceptowany dla zgodności API, lecz nie ma wpływu na wynik, ponieważ dekoder jest predyktorem zbioru bez etapu NMS. Zobacz stronę predykcji, aby poznać źródła, streaming i obsługę wyników.

Warianty

Dostępnych jest pięć rozmiarów. Wszystkie działają z tą samą rozdzielczością wejściową, dlatego tabela rozróżnia je według liczby parametrów i accuracy.

Checkpoint modeluWejście (px)mAP 50-95Parametry (mln)
LibreDFINEl64060.031.24
LibreDFINEm64057.819.59
LibreDFINEn64045.83.78
LibreDFINEs64053.410.32
LibreDFINEx64061.462.62

COCO val2017, 500 images. Wyniki zmierzono za pomocą zestawu benchmarkowego LibreYOLO i opublikowano w Vision Analysis, gdzie porównywane są opóźnienia na różnych urządzeniach i w różnych środowiskach uruchomieniowych oraz znajdują się pełne zapisy przebiegów.

Segmentacja ponownie wykorzystuje backbone, enkoder i dekoder detekcji oraz dodaje głowicę masek, dlatego checkpoint -seg przyjmuje te same argumenty co odpowiadający mu checkpoint detekcji. Rodzina RT-DETRv4 w LibreYOLO została zaimplementowana jako podklasa otoki D-FINE. Dziedziczy tę linię dekodera, a następnie ogranicza listę zadań z powrotem do detekcji, ponieważ nie zawiera głowicy masek.

Trenowanie

Dla obu zadań trenowanie rozpoczyna się od opublikowanego checkpointu.

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreDFINEn.pt")model.train(data="my-dataset.yaml", epochs=50, imgsz=640, batch=8, lr0=2e-4)
CLI
libreyolo train model=LibreDFINEn.pt data=my-dataset.yaml \  epochs=50 imgsz=640 batch=8 lr0=2e-4
Segmentacja instancji
# Kontynuuje od opublikowanych wag segmentacji wraz z głowicą masek.libreyolo train model=LibreDFINEn-seg.pt data=my-dataset.yaml \  task=segment epochs=50 imgsz=640
Segmentacja z wag detekcji
# Wagi detekcji nie zawierają głowicy masek, więc jest to jawny transfer:# głowica zaczyna bez wytrenowania i staje się użyteczna dopiero po trenowaniu.# Podanie tutaj task=segment autoryzuje transfer.libreyolo train model=LibreDFINEn.pt data=my-dataset.yaml \  task=segment epochs=50 imgsz=640
LoRA
from libreyolo import LibreYOLO model = LibreYOLO("LibreDFINEn.pt")model.train(data="my-dataset.yaml", epochs=50, lora=True)
Multi-GPU
libreyolo train model=LibreDFINEn.pt data=my-dataset.yaml \  epochs=50 device=0,1 batch=16

Przy ustawieniach domyślnych moduł trenujący wykonuje 132 epoki z lr0=2e-4, amp=True i amp_dtype="float16", batchem 16 i early stopping po 50 epokach bez poprawy. libreyolo train zaczyna od tej samej receptury dla obu zadań: AdamW z płaskim harmonogramem cosinusowym, weight_decay=1e-4, 2 epoki rozgrzewki, obcinanie normy gradientu do 0.1 oraz brak augmentacji mosaic, MixUp, HSV i afinicznej. Bez name= jego przebiegi trafiają do runs/train/dfine_exp. Wagi detekcji są prawidłowym punktem wyjścia do trenowania segmentacji, ale wyłącznie jako jawny transfer. Głowica masek zaczyna bez wytrenowania i w przeciwnym razie zwracałaby bezwartościowe maski. Podanie task=segment w CLI autoryzuje ten transfer. Ścieżka Pythona jest bardziej ograniczona: klasę LibreDFINE trzeba utworzyć bezpośrednio z allow_detect_to_segment_transfer=True, ponieważ fabryka LibreYOLO() nie przyjmuje takiego argumentu. Bezpośrednie utworzenie nie pobiera pliku, więc wagi muszą już znajdować się na dysku.

Ustawienie lora=True dotyczy detekcji. Trenowanie segmentacji je odrzuca i wskazuje zamiast niego freeze='backbone', ponieważ głowica masek nie została przetestowana z adapterami. Na urządzeniach Apple silicon moduł trenujący przenosi całe uruchomienie na CPU. Przebieg wsteczny skwantowanego mnożenia macierzy w module Integral powoduje błąd kompilacji Metal. Nie ma to wpływu na inferencję w MPS.

Zobacz stronę trenowania, aby poznać zbiory danych, augmentację, obsługę wielu GPU i loggery.

Walidacja

Metoda val() zwraca słownik indeksowany nazwą metryki i wyświetla wyniki dla poszczególnych klas, gdy pozostawiono włączone verbose.

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

Dla checkpointu -seg zwykły klucz metrics/mAP50-95 zawiera wynik masek. To samo uruchomienie raportuje też ramki pod oznaczeniem (B) i maski pod oznaczeniem (M), więc oba wyniki są dostępne po jednym przebiegu.

Eksport

ZadanieONNXTorchScriptExecuTorchTensorRTOpenVINOPaddleMNNRKNNncnnTFLiteCoreMLCore AI
DetectionDetection to ONNX: obsługiwaneDetection to TorchScript: obsługiwaneDetection to ExecuTorch: brak obsługiDetection to TensorRT: obsługiwaneDetection to OpenVINO: obsługiwaneDetection to Paddle: obsługiwaneDetection to MNN: obsługiwaneDetection to RKNN: brak obsługiDetection to ncnn: brak obsługiDetection to TFLite: brak obsługiDetection to CoreML: brak obsługiDetection to Core AI: obsługiwane
Instance segmentationInstance segmentation to ONNX: obsługiwaneInstance segmentation to TorchScript: obsługiwaneInstance segmentation to ExecuTorch: brak obsługiInstance segmentation to TensorRT: obsługiwaneInstance segmentation to OpenVINO: obsługiwaneInstance segmentation to Paddle: brak obsługiInstance segmentation to MNN: brak obsługiInstance segmentation to RKNN: brak obsługiInstance segmentation to ncnn: brak obsługiInstance segmentation to TFLite: brak obsługiInstance segmentation to CoreML: brak obsługiInstance segmentation to Core AI: brak obsługi

Wyeksportowany artefakt jest ponownie wczytywany przez LibreYOLO() na podstawie sufiksu pliku, dlatego plik .onnx lub .engine zachowuje się jak checkpoint i zwraca ten sam obiekt Results. Ścieżki OpenVINO, Paddle, MNN i Core AI eksportują ze stałym obszarem zamiast kształtów dynamicznych. Strona Eksport zawiera argumenty obsługiwane przez każdy format oraz dodatki wymagane przez niektóre z nich.

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreDFINEn.pt")model.export(format="onnx", imgsz=640)model.export(format="tensorrt", imgsz=640, half=True)
CLI
libreyolo export model=LibreDFINEn.pt format=onnx imgsz=640libreyolo export model=LibreDFINEn.pt format=tensorrt imgsz=640 half=True
Użycie wyeksportowanego pliku
from libreyolo import LibreYOLO, SAMPLE_IMAGE # Fabryka wybiera ścieżkę na podstawie sufiksu pliku, więc wyeksportowany# artefakt wczytuje się jak każdy checkpoint i zwraca ten sam obiekt Results.model = LibreYOLO("LibreDFINEn.onnx")result = model(SAMPLE_IMAGE) print(result.boxes.xyxy)

Wejścia i wyjścia ONNX

Tensorimages float32 [batch, 3, height, width]
KolorRGB
Skalowaniepiksel / 255
Normalizacjabrak
Zmiana rozmiarurozciągnij do szerokości x wysokości (bez wypełnienia, proporcje nie są zachowane), Pillow bilinear
Jak odtworzyć dwuliniowe skalowanie Pillow

LibreYOLO skaluje filtrem BILINEAR z Pillow (Image.resize). To nie jest OpenCV INTER_LINEAR ani INTER_AREA: przy zmniejszaniu Pillow poszerza filtr o współczynnik zmniejszenia, a skalowania OpenCV zmieniają detekcje i przesuwają ramki o kilka pikseli. Aby odtworzyć to bez Pillow, przeskaluj jedną oś, zaokrąglij do 8 bitów, potem przeskaluj drugą oś i zaokrąglij ponownie. Dla każdej osi niech s = in_size / out_size oraz f = max(s, 1). Piksel wyjściowy i ma środek c = (i + 0.5) * s i czyta piksele źródłowe j od int(c - f + 0.5) do int(c + f + 0.5) - 1, przycięte do obrazu, każdy z wagą max(0, 1 - |j + 0.5 - c| / f), podzieloną przez sumę wag. Pillow liczy w arytmetyce stałoprzecinkowej i wybiera kolejność osi na podstawie kształtu obrazu, więc wagi zmiennoprzecinkowe mogą się od niego różnić o jeden poziom na kilku pikselach. To nie zmienia wyników w naszych sprawdzeniach.

Square input only. Export rejects a non-square imgsz, and height and width are 640 by default.

Batch size 1 only. The graph declares a dynamic batch axis, but batches of 2 or more fail in 1.7.0.

Divide by 255 after the resize. There is no mean or std normalization.

Detection, eksport domyślny
WyjścieKształtZnaczenie
pred_logits[batch, queries, nc]One logit per query and class. Sigmoid is not applied. queries is 300 for every size.
pred_boxes[batch, queries, 4]cx, cy, w, h of each query, normalized 0 to 1 of the input. The input is the whole image stretched, so these are also fractions of the original image.

Przetwarzanie końcowe

  1. Apply sigmoid to pred_logits.
  2. Flatten the [queries, nc] scores and take the top 300 (max_det, 300 by default). For flat index k, the query is k // nc and the class is k % nc. One query can yield several classes.
  3. Keep the pairs whose score is above the confidence threshold (0.25 by default).
  4. Convert the query's box to x1 = cx - w / 2, y1 = cy - h / 2, x2 = cx + w / 2, y2 = cy + h / 2. Multiply x by the original image width and y by the original image height.
  5. There is no NMS and the iou threshold is not used. D-FINE predicts a set of boxes, and export with nms=True raises NotImplementedError.
  6. LibreYOLO does not clip these boxes, so an edge can sit slightly outside the image.
Instance segmentation, eksport domyślny
WyjścieKształtZnaczenie
pred_logits[batch, queries, nc]One logit per query and class. Sigmoid is not applied. queries is 300 for every size.
pred_boxes[batch, queries, 4]cx, cy, w, h of each query, normalized 0 to 1 of the input. The input is the whole image stretched, so these are also fractions of the original image.
pred_masks[batch, queries, mask_h, mask_w]One mask per query, sigmoid already applied. mask_h is height / 4 and mask_w is width / 4, 160 x 160 at 640 x 640.

Przetwarzanie końcowe

  1. Apply sigmoid to pred_logits.
  2. Flatten the [queries, nc] scores and take the top 300 (max_det, 300 by default). For flat index k, the query is k // nc and the class is k % nc. One query can yield several classes.
  3. Keep the pairs whose score is above the confidence threshold (0.25 by default).
  4. Convert the query's box to x1 = cx - w / 2, y1 = cy - h / 2, x2 = cx + w / 2, y2 = cy + h / 2. Multiply x by the original image width and y by the original image height.
  5. For each kept pair, take its query's mask. Resize it with bilinear interpolation and half-pixel centers (align_corners=False, no antialiasing) to height x width, then again to the original image size.
  6. A pixel belongs to the mask when its value is 0.5 or more.
  7. Clear every mask pixel outside the box. Pixel (x, y) stays only when x1 <= x < x2 and y1 <= y < y2, in original-image pixels.
  8. There is no NMS and the iou threshold is not used. D-FINE predicts a set of boxes, and export with nms=True raises NotImplementedError.
  9. LibreYOLO does not clip the boxes of a .pt predict, so an edge can sit slightly outside the image. Its ONNX backend clips them to the image.

Aby sprawdzić własną implementację, uruchom ten sam plik w LibreYOLO: LibreYOLO("model.onnx").predict("image.jpg") zwraca wyniki wzorcowe. Zweryfikowano w LibreYOLO 1.7.0.

Checkpointy

Wszystkie opublikowane pliki wag dla tej rodziny.

PlikWejście (px)Licencja wag
Detection
LibreDFINEn.pt640apache-2.0
LibreDFINEs.pt640apache-2.0
LibreDFINEm.pt640apache-2.0
LibreDFINEl.pt640apache-2.0
LibreDFINEx.pt640apache-2.0
Instance segmentation
LibreDFINEn-seg.pt640apache-2.0
LibreDFINEs-seg.pt640apache-2.0
LibreDFINEm-seg.pt640apache-2.0
LibreDFINEl-seg.pt640apache-2.0
LibreDFINEx-seg.pt640apache-2.0

Każdy z powyższych plików jest obecnie dostępny w organizacji LibreYOLO i pobierany przy pierwszym użyciu.

Licencjonowanie

Sprawdź licencję w repozytorium konkretnych pobieranych wag na Hugging Face. Każdy checkpoint w organizacji LibreYOLO ma licencję, która nie zawsze jest taka sama w całej rodzinie. To repozytorium jest źródłem rozstrzygającym, a poniższe podsumowanie opisuje stan z chwili ostatniej weryfikacji tej strony.

To opis obowiązujących licencji, a nie porada prawna. Jeśli odpowiedź ma znaczenie komercyjne, przeczytaj licencje i zasięgnij własnej porady prawnej.

Oryginalna praca
D-FINE, University of Science and Technology of China
Licencja projektu źródłowego
Apache-2.0
Kod źródłowy projektu
github.com/Peterande/D-FINE
Kod LibreYOLO
MIT
Wagi
Apache-2.0, ponownie opublikowane w huggingface.co/LibreYOLO
Interpretacja
Apache-2.0 is a permissive license, so these weights can be used in commercial and closed-source products. It asks you to keep its license text and attribution notices with any copy of the weights you redistribute, and it grants a patent license. It places no obligation on your own application code, and weights you train yourself on your own data are yours. The segmentation weights carry a second Apache-2.0 upstream, ArgoHA/D-FINE-seg, under the same terms.

Wagi segmentacji mają drugie źródło upstream. Dekoder masek, dopasowywanie masek i funkcja straty masek pochodzą z ArgoHA/D-FINE-seg, również na licencji Apache-2.0. Opiekun tego projektu zatwierdził ponowne użycie z podaniem źródła.

Cytowanie

@misc{peng2024dfine,
      title={D-FINE: Redefine Regression Task in DETRs as Fine-grained Distribution Refinement},
      author={Yansong Peng and Hebei Li and Peixi Wu and Yueyi Zhang and Xiaoyan Sun and Feng Wu},
      year={2024},
      eprint={2410.13842},
      archivePrefix={arXiv},
      primaryClass={cs.CV}
}

Skopiowano z bloku cytowania autorów w github.com/Peterande/D-FINE#citation.

Zweryfikowano z LibreYOLO v1.6.0. Tabele obsługi, checkpointy i wyniki benchmarków na tej stronie są generowane na podstawie wydanej biblioteki i opublikowanych wag, a nie wpisywane ręcznie.