Skip to content

RF-DETR v1.8.3: Correct keypoint flip augm.

Latest

Choose a tag to compare

@Borda Borda released this 29 Jun 07:53
3bd6bff

πŸ“‹ Summary

RF-DETR 1.8.3 is a focused patch release with one new capability and three correctness fixes. The headline addition is optimize_for_inference(inplace=True) β€” a memory-efficient inference path that skips the deep-copy of the base model, useful on memory-constrained GPUs and edge devices. On the bug-fix side: keypoint horizontal-flip augmentation now correctly swaps left/right pairs (previously labels were corrupted on flip); bounding boxes are clamped to image bounds so objects at image edges no longer produce negative or out-of-frame coordinates; and default loss coefficients for segmentation and keypoint fine-tuning are restored to their intended values after a regression introduced in v1.7.

✨ Spotlights

In-place inference optimization

optimize_for_inference(inplace=True) exports the model using the loaded weights directly β€” no deep-copy β€” reducing peak memory during the optimization step by roughly 0.5Γ— model weight. After inplace optimization, the base model is cleared: export() raises RuntimeError and remove_optimized_model() issues a UserWarning and returns cleanly. The new is_optimized_inplace property lets you check the current state.

model = RFDETRSmall()

# Default: deep-copy kept, fully reversible
model.optimize_for_inference(compile=False, dtype="float16")
model.remove_optimized_model()  # works fine

# New: inplace, lowest possible memory β€” irreversible
model.optimize_for_inference(compile=False, inplace=True, dtype="float16")
print(model.is_optimized_inplace)  # True

Correct keypoint flip augmentation

Keypoint training now correctly swaps symmetric pairs during horizontal flip augmentation. CocoKeypointSchema and YoloKeypointSchema both gain a keypoint_flip_pairs field, populated automatically from keypoint names (COCO left/right convention) or from flip_idx (YOLO pose). infer_coco_keypoint_schema and infer_yolo_keypoint_schema are also re-exported from the public rfdetr.datasets namespace.

from rfdetr.datasets import infer_coco_keypoint_schema  # now public

schema = infer_coco_keypoint_schema("path/to/_annotations.coco.json")
print(schema.keypoint_flip_pairs)  # [1, 2, 3, 4, ...] β€” auto-inferred

model.train(dataset_dir=DATASET_DIR, epochs=50, keypoint_schema=schema)

Native COCO format (dataset_file="coco") is supported alongside "roboflow" and "yolo".

Bounding box coordinates clamped to image bounds

Predicted boxes are now guaranteed to lie within [0, width] Γ— [0, height]. Model regression output is unbounded β€” objects near image edges could previously produce negative x1/y1 or x2/y2 values exceeding image dimensions. scale_fct is also cast to boxes.dtype to avoid dtype mismatch with fp16 inference.

Loss coefficient defaults corrected

Two training config defaults were silently wrong since v1.7:

  • SegmentationTrainConfig.cls_loss_coef was 5.0 β€” now 1.0, restoring the effective weight from before the v1.7 TrainConfig ownership migration.
  • KeypointTrainConfig.keypoint_nll_loss_coef was 0.5 β€” now 1.0, aligning the NLL term with all other keypoint loss weights.

If your current fine-tuned runs relied on the old defaults, pass the values explicitly to maintain continuity.

πŸ”„ Migration guide

No breaking API changes in this release.

Segmentation fine-tuning β€” cls_loss_coef default change: if you fine-tune segmentation models without setting cls_loss_coef explicitly, your loss balance shifts. To reproduce prior runs:

from rfdetr.config import SegmentationTrainConfig

config = SegmentationTrainConfig(cls_loss_coef=5.0)

Keypoint fine-tuning β€” keypoint_nll_loss_coef default change: to reproduce prior runs:

from rfdetr.config import KeypointTrainConfig

config = KeypointTrainConfig(keypoint_nll_loss_coef=0.5)

Keypoint horizontal-flip augmentation now active: flip augmentation was disabled for keypoints in v1.8.1 because pair swapping was not yet implemented. With this release it is enabled automatically when keypoint_flip_pairs is non-empty. Datasets without left/right keypoint naming conventions infer zero pairs and skip ReplayCompose automatically β€” no action required.

πŸ“ Notable changes

πŸš€ Added

  • optimize_for_inference(inplace=True) β€” keyword-only arg on RFDETR.optimize_for_inference(); skips deep-copy for memory-constrained inference-only deployments. Requires compile=False. (#1089)
  • RFDETR.is_optimized_inplace β€” property returning True after a successful inplace optimization. (#1089)
  • CocoKeypointSchema.keypoint_flip_pairs and YoloKeypointSchema.keypoint_flip_pairs β€” flat list of horizontal-flip swap pairs, inferred from keypoint names (COCO) or flip_idx (YOLO). (#1164)
  • infer_coco_keypoint_schema and infer_yolo_keypoint_schema re-exported from rfdetr.datasets (public namespace). (#1164)

🌱 Changed

  • Horizontal flip detection in AlbumentationsWrapper now uses Albumentations ReplayCompose replay metadata instead of heuristic bbox-center mirroring; eliminates false positives. Falls back to alb.Compose with a UserWarning on albumentations <1.3. (#1164)
  • Keypoint schema inference now supports native COCO format (dataset_file="coco") alongside "roboflow" and "yolo". (#1164)
  • _keypoint_schema_cache key changed from dataset_dir to (dataset_file, dataset_dir) tuple to prevent cross-format cache collisions. (#1164)
  • SegmentationTrainConfig.cls_loss_coef default: 5.0 β†’ 1.0. (#1165)
  • KeypointTrainConfig.keypoint_nll_loss_coef default: 0.5 β†’ 1.0. (#1165)

πŸ”§ Fixed

  • Predicted bounding boxes clamped to [0, width] Γ— [0, height] in PostProcess._postprocess_boxes(); scale_fct also cast to boxes.dtype for fp16 safety. (#1168)
  • SegmentationTrainConfig.cls_loss_coef default corrected from 5.0 to 1.0 β€” restores the pre-v1.7 effective classification loss weight. (#1165)
  • KeypointTrainConfig.keypoint_nll_loss_coef default restored to 1.0. (#1165)
  • optimize_for_inference() flag ordering fixed: _optimized_inplace set before model.model = None so exception recovery sees correct state. (#1089)
  • remove_optimized_model() now issues UserWarning and returns cleanly after inplace optimization instead of raising RuntimeError. (#1089)
  • export() now raises RuntimeError immediately if called after inplace optimization. (#1089)

πŸ† Contributors

  • Jonas Pirner (@pirnerjonas) β€” added in-place inference optimization for memory-efficient deployment
  • Alessandro Brunello (@Armaggheddon, LinkedIn) β€” fixed postprocessor to clamp predicted boxes to image bounds
  • Jirka Borovec (@Borda, LinkedIn) β€” restored loss coefficient defaults, fixed keypoint flip-pair augmentation, restructured test layout

Full changelog: 1.8.2...1.8.3