D-FINE

Un transformer de detección que reformula la regresión de cajas como una distribución de probabilidad sobre cada borde de la caja, refinada a lo largo de las capas del decoder. LibreYOLO lo soporta para detección y segmentación de instancias.

Tareas
detection, instance segmentation
Tamaños
n, s, m, l, x at 640 px
Instalación
pip install libreyolo
Nivel de compatibilidad
Núcleo, desde v1.1.0. Detectores entrenables del núcleo: las funciones siguen a los modelos emblemáticos en la misma oleada de versiones.
Proyecto original
D-FINE de University of Science and Technology of China, Apache-2.0. Artículo, fuente
Licencias
Código Apache-2.0, pesos Apache-2.0. Uso comercial

Instalación

D-FINE no necesita ningún extra opcional. Todos sus imports están cubiertos por la instalación base.

bash
pip install libreyolo

El fine-tuning con adaptadores mediante lora=True es la excepción, y necesita el extra lora.

bash
pip install "libreyolo[lora]"

Predicción

Los pesos se descargan de Hugging Face en el primer uso y se guardan en la caché local.

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
Segmentación de instancias
from libreyolo import LibreYOLO, SAMPLE_IMAGE # El sufijo -seg del nombre de archivo selecciona la cabeza de máscaras,# así que aquí no hace falta el argumento task.model = LibreYOLO("LibreDFINEn-seg.pt")result = model(SAMPLE_IMAGE, save=True) print(result.masks.data.shape)

El objeto Results devuelto es el mismo que devuelven todas las familias, así que cambiar a otro detector es un cambio de una línea. Un nombre de archivo con -seg resuelve por sí solo a la tarea de segmentación, y entonces result.masks lleva las máscaras de instancia junto a las cajas. conf y max_det filtran la selección de queries; iou se acepta por paridad de API pero no tiene efecto, porque el decoder es un predictor de conjuntos sin paso de NMS. Consulta predicción para fuentes, streaming y manejo de resultados.

Variantes

Cinco tamaños. Todos funcionan a la misma resolución de entrada, así que la tabla los separa por número de parámetros y precisión.

CheckpointEntrada (px)mAP 50-95Parámetros (M)
LibreDFINEl64060.031.24
LibreDFINEm64057.819.59
LibreDFINEn64045.83.78
LibreDFINEs64053.410.32
LibreDFINEx64061.462.62

COCO val2017, 500 images. Medido con el sistema de benchmarks de LibreYOLO y publicado en Vision Analysis, donde se comparan la latencia entre distintos hardwares y runtimes y se conservan los registros completos de las ejecuciones.

La segmentación reutiliza el backbone, el encoder y el decoder de detección y añade una cabeza de máscaras, así que un checkpoint -seg acepta los mismos argumentos que su equivalente de detección. La familia RT-DETRv4 de LibreYOLO está escrita como una subclase del wrapper de D-FINE: hereda esta línea de decoder y luego fija su lista de tareas de vuelta a detección, porque no lleva cabeza de máscaras.

Entrenamiento

El entrenamiento parte de un checkpoint publicado, para ambas tareas.

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
Segmentación de instancias
# Continúa desde pesos de segmentación publicados, cabeza de máscaras incluida.libreyolo train model=LibreDFINEn-seg.pt data=my-dataset.yaml \  task=segment epochs=50 imgsz=640
Segmentación desde pesos de detección
# Los pesos de detección no llevan cabeza de máscaras, así que esto es una# transferencia explícita: la cabeza empieza sin entrenar y solo sirve una# vez entrenada. Pedir task=segment aquí es lo que autoriza la transferencia.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

Si no se toca nada, el trainer ejecuta 132 épocas con lr0=2e-4 y amp=True y amp_dtype="float16", un batch de 16 y early stopping tras 50 épocas sin mejora. libreyolo train parte de la misma receta para ambas tareas: AdamW con un schedule coseno plano, weight_decay=1e-4, 2 épocas de calentamiento, un recorte de la norma del gradiente de 0.1, y sin aumento de mosaic, MixUp, HSV ni afín. Sin name=, sus ejecuciones van a runs/train/dfine_exp. Los pesos de detección son un punto de partida válido para entrenar segmentación, pero solo como transferencia explícita, ya que la cabeza de máscaras empieza sin entrenar y de otro modo devolvería máscaras sin sentido. Pasar task=segment en el CLI es lo que la autoriza. La vía de Python es más estrecha: hay que construir LibreDFINE directamente con allow_detect_to_segment_transfer=True, porque la factoría LibreYOLO() no acepta ese argumento, y la construcción directa no descarga nada, así que el archivo de pesos ya tiene que estar en disco.

lora=True se aplica a detección. El entrenamiento de segmentación lo rechaza y remite a freeze='backbone' en su lugar, porque la cabeza de máscaras no se ha probado con adaptadores. En Apple silicon el trainer mueve toda la ejecución a CPU: el backward pass del matmul por bins del Integral choca con un fallo de compilación de Metal. La inferencia en MPS no se ve afectada.

Consulta entrenamiento para datasets, aumento de datos (data augmentation), multi-GPU y loggers.

Validación

val() devuelve un diccionario indexado por nombre de métrica, e imprime los resultados por clase si verbose se deja activado.

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
Segmentación de instancias
from libreyolo import LibreYOLO model = LibreYOLO("LibreDFINEn-seg.pt")metrics = model.val(data="my-dataset.yaml") print(metrics["metrics/mAP50-95(M)"])   # máscarasprint(metrics["metrics/mAP50-95(B)"])   # cajas

Contra un checkpoint -seg, la clave metrics/mAP50-95 a secas contiene la puntuación de las máscaras, y la misma ejecución reporta además las cajas bajo (B) y las máscaras bajo (M), así que ambas están disponibles en una sola pasada.

Exportación

TareaONNXTorchScriptExecuTorchTensorRTOpenVINOPaddleMNNRKNNncnnTFLiteCoreMLCore AI
DetectionDetection to ONNX: compatibleDetection to TorchScript: compatibleDetection to ExecuTorch: no compatibleDetection to TensorRT: compatibleDetection to OpenVINO: compatibleDetection to Paddle: compatibleDetection to MNN: compatibleDetection to RKNN: no compatibleDetection to ncnn: no compatibleDetection to TFLite: no compatibleDetection to CoreML: no compatibleDetection to Core AI: compatible
Instance segmentationInstance segmentation to ONNX: compatibleInstance segmentation to TorchScript: compatibleInstance segmentation to ExecuTorch: no compatibleInstance segmentation to TensorRT: compatibleInstance segmentation to OpenVINO: compatibleInstance segmentation to Paddle: no compatibleInstance segmentation to MNN: no compatibleInstance segmentation to RKNN: no compatibleInstance segmentation to ncnn: no compatibleInstance segmentation to TFLite: no compatibleInstance segmentation to CoreML: no compatibleInstance segmentation to Core AI: no compatible

Un artefacto exportado se vuelve a cargar con LibreYOLO() según su sufijo de archivo, así que un archivo .onnx o .engine se comporta como un checkpoint y devuelve el mismo Results. Las rutas de OpenVINO, Paddle, MNN y Core AI exportan con un lienzo fijo en lugar de con formas dinámicas. Exportación lista los argumentos que acepta cada formato y los extras que añaden unos pocos de ellos.

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
Usar el archivo exportado
from libreyolo import LibreYOLO, SAMPLE_IMAGE # La factoría enruta según el sufijo del archivo, así que un artefacto# exportado se carga como cualquier checkpoint y devuelve el mismo Results.model = LibreYOLO("LibreDFINEn.onnx")result = model(SAMPLE_IMAGE) print(result.boxes.xyxy)

Entradas y salidas ONNX

Tensorimages float32 [batch, 3, height, width]
ColorRGB
Escaladopíxel / 255
Normalizaciónninguna
Redimensionadoestirar a ancho x alto (sin relleno, no se conserva la relación de aspecto), Pillow bilinear
Cómo reproducir el redimensionado bilineal de Pillow

LibreYOLO redimensiona con el filtro BILINEAR de Pillow (Image.resize). No es OpenCV INTER_LINEAR ni INTER_AREA: al reducir, Pillow ensancha el filtro según el factor de reducción, y los redimensionados de OpenCV cambian las detecciones y desplazan las cajas varios píxeles. Para reproducirlo sin Pillow, redimensiona un eje, redondea a 8 bits, luego redimensiona el otro eje y vuelve a redondear. Por eje, sea s = in_size / out_size y f = max(s, 1). El píxel de salida i tiene centro c = (i + 0.5) * s y lee los píxeles de origen j desde int(c - f + 0.5) hasta int(c + f + 0.5) - 1, recortados a la imagen, cada uno con peso max(0, 1 - |j + 0.5 - c| / f), dividido por la suma de los pesos. Pillow trabaja en coma fija y elige el orden de los ejes según la forma de la imagen, así que los pesos en coma flotante pueden diferir en un nivel en unos pocos píxeles. Eso no cambia los resultados en nuestras comprobaciones.

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, exportación por defecto
SalidaFormaSignificado
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.

Posprocesado

  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, exportación por defecto
SalidaFormaSignificado
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.

Posprocesado

  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.

Para comprobar tu propia implementación, pasa el mismo archivo por LibreYOLO: LibreYOLO("model.onnx").predict("image.jpg") devuelve los resultados de referencia. Verificado con LibreYOLO 1.7.0.

Checkpoints

Todos los archivos de pesos publicados de esta familia.

ArchivoEntrada (px)Licencia de los pesos
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

Todos los archivos anteriores existen hoy en la organización de LibreYOLO y se descargan la primera vez que se usan.

Licencia

Comprueba la licencia en el repositorio de Hugging Face de los pesos concretos que descargues. Cada checkpoint de la organización de LibreYOLO incluye una, y no siempre es la misma en toda una familia. Ese repositorio es la fuente autorizada; el resumen siguiente describe qué se aplicaba cuando se verificó esta página por última vez.

Esta es una descripción de las licencias implicadas, no asesoramiento legal. Si la respuesta es importante a nivel comercial, lee las licencias y busca tu propio asesoramiento.

Trabajo original
D-FINE, University of Science and Technology of China
Licencia del proyecto original
Apache-2.0
Fuente del proyecto original
github.com/Peterande/D-FINE
Código de LibreYOLO
MIT
Pesos
Apache-2.0, republicados en huggingface.co/LibreYOLO
Interpretación
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.

Los pesos de segmentación tienen un segundo upstream: su decoder de máscaras, el emparejamiento de máscaras y la función de pérdida (loss) de máscaras vienen de ArgoHA/D-FINE-seg, también Apache-2.0, cuyo maintainer aprobó el reuso con atribución.

Cita

@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}
}

Copiado del bloque de cita de los autores en github.com/Peterande/D-FINE#citation.

Verificado con LibreYOLO v1.6.0. Las tablas de compatibilidad, los checkpoints y las cifras de rendimiento de esta página se generan a partir de la biblioteca publicada y los pesos publicados; no se escriben a mano.