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.
pip install libreyoloWyjątkiem jest dostrajanie adapterów z lora=True, które wymaga dodatku lora.
pip install "libreyolo[lora]"Predykcja
Przy pierwszym użyciu wagi są pobierane z Hugging Face i zapisywane lokalnie w pamięci podręcznej.
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)libreyolo predict model=LibreDFINEn.pt source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpg save=Truefrom 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 modelu | Wejście (px) | mAP 50-95 | Parametry (mln) |
|---|---|---|---|
| LibreDFINEl | 640 | 60.0 | 31.24 |
| LibreDFINEm | 640 | 57.8 | 19.59 |
| LibreDFINEn | 640 | 45.8 | 3.78 |
| LibreDFINEs | 640 | 53.4 | 10.32 |
| LibreDFINEx | 640 | 61.4 | 62.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.
from libreyolo import LibreYOLO model = LibreYOLO("LibreDFINEn.pt")model.train(data="my-dataset.yaml", epochs=50, imgsz=640, batch=8, lr0=2e-4)libreyolo train model=LibreDFINEn.pt data=my-dataset.yaml \ epochs=50 imgsz=640 batch=8 lr0=2e-4# 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# 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=640from libreyolo import LibreYOLO model = LibreYOLO("LibreDFINEn.pt")model.train(data="my-dataset.yaml", epochs=50, lora=True)libreyolo train model=LibreDFINEn.pt data=my-dataset.yaml \ epochs=50 device=0,1 batch=16Przy 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.
from libreyolo import LibreYOLO model = LibreYOLO("LibreDFINEn.pt")metrics = model.val(data="my-dataset.yaml") print(metrics["metrics/mAP50-95"])print(metrics["metrics/mAP50"])libreyolo val model=LibreDFINEn.pt data=my-dataset.yamlfrom 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)"]) # ramkiDla 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
| Zadanie | ONNX | TorchScript | ExecuTorch | TensorRT | OpenVINO | Paddle | MNN | RKNN | ncnn | TFLite | CoreML | Core AI |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Detection | Detection to ONNX: obsługiwane | Detection to TorchScript: obsługiwane | Detection to ExecuTorch: brak obsługi | Detection to TensorRT: obsługiwane | Detection to OpenVINO: obsługiwane | Detection to Paddle: obsługiwane | Detection to MNN: obsługiwane | Detection to RKNN: brak obsługi | Detection to ncnn: brak obsługi | Detection to TFLite: brak obsługi | Detection to CoreML: brak obsługi | Detection to Core AI: obsługiwane |
| Instance segmentation | Instance segmentation to ONNX: obsługiwane | Instance segmentation to TorchScript: obsługiwane | Instance segmentation to ExecuTorch: brak obsługi | Instance segmentation to TensorRT: obsługiwane | Instance segmentation to OpenVINO: obsługiwane | Instance segmentation to Paddle: brak obsługi | Instance segmentation to MNN: brak obsługi | Instance segmentation to RKNN: brak obsługi | Instance segmentation to ncnn: brak obsługi | Instance segmentation to TFLite: brak obsługi | Instance segmentation to CoreML: brak obsługi | Instance 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.
from libreyolo import LibreYOLO model = LibreYOLO("LibreDFINEn.pt")model.export(format="onnx", imgsz=640)model.export(format="tensorrt", imgsz=640, half=True)libreyolo export model=LibreDFINEn.pt format=onnx imgsz=640libreyolo export model=LibreDFINEn.pt format=tensorrt imgsz=640 half=Truefrom 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
| Tensor | images float32 [batch, 3, height, width] |
|---|---|
| Kolor | RGB |
| Skalowanie | piksel / 255 |
| Normalizacja | brak |
| Zmiana rozmiaru | rozcią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ście | Kształt | Znaczenie |
|---|---|---|
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
- Apply sigmoid to pred_logits.
- 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.
- Keep the pairs whose score is above the confidence threshold (0.25 by default).
- 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.
- 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.
- LibreYOLO does not clip these boxes, so an edge can sit slightly outside the image.
Instance segmentation, eksport domyślny
| Wyjście | Kształt | Znaczenie |
|---|---|---|
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
- Apply sigmoid to pred_logits.
- 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.
- Keep the pairs whose score is above the confidence threshold (0.25 by default).
- 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.
- 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.
- A pixel belongs to the mask when its value is 0.5 or more.
- Clear every mask pixel outside the box. Pixel (x, y) stays only when x1 <= x < x2 and y1 <= y < y2, in original-image pixels.
- 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.
- 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.
| Plik | Wejście (px) | Licencja wag |
|---|---|---|
| Detection | ||
| LibreDFINEn.pt | 640 | apache-2.0 |
| LibreDFINEs.pt | 640 | apache-2.0 |
| LibreDFINEm.pt | 640 | apache-2.0 |
| LibreDFINEl.pt | 640 | apache-2.0 |
| LibreDFINEx.pt | 640 | apache-2.0 |
| Instance segmentation | ||
| LibreDFINEn-seg.pt | 640 | apache-2.0 |
| LibreDFINEs-seg.pt | 640 | apache-2.0 |
| LibreDFINEm-seg.pt | 640 | apache-2.0 |
| LibreDFINEl-seg.pt | 640 | apache-2.0 |
| LibreDFINEx-seg.pt | 640 | apache-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.