Changelog¶
All notable changes to OrientedDet will be documented in this file.
[Unreleased]¶
Toward v0.4.2 (native YOLO-OBB). The detector is already in the tree (model_type: yolo_obb). Next is COCO pretrain and DOTA.
[0.4.1] - 2026-10-10¶
Citation and discoverability. No model or API changes.
Added¶
CITATION.cff— Citation File Format for GitHub “Cite this repository” and Zenodo.- Shared project one-liner: oriented and rotated object detection in aerial and satellite images (README, docs, PyPI description, keywords). Overview: oriented detection in aerial and satellite images.
Changed¶
- Roadmap: native YOLO-OBB moves to v0.4.2; Rotated RTMDet multi-scale DOTA to v0.4.3.
[0.4.0] - 2026-10-10¶
Rotated RTMDet. rotated_rtmdet_dota_le90_3x (CSPNeXt-S + PAFPN) is on the Hub at official Task 1 77.60%, the top of the DOTA zoo. Native YOLO-OBB is 0.4.2.
Added¶
- Rotated RTMDet (
model_type: rotated_rtmdet) — clean-room CSPNeXt backbone + CSPNeXt-PAFPN neck, SepBN head (shared convs, per-level BN), dynamic soft-label assigner, Quality Focal Loss + decoded rotated IoU box loss. Base fragments:rotated_rtmdet_cspnext_s.jsonandrotated_rtmdet_cspnext_tiny.json(tiny has no Hub weights). - RTMDet-S 3× Hub —
rotated_rtmdet_dota_le90_3x. Official Task 1 77.60% (AP75 52.01, COCO mAP 49.02; deploy 0.45; leaky eval-val 82.75%). Recipe:dota_le90_3x_s.json(36 epochs, AdamW, EMA, random rotate p=0.5 ±180°, mosaic off). Report:docs/eval-reports/rotated_rtmdet_dota_le90_3x/. - EMA —
training.use_ema/ema_momentum/ema_gamma. Validation andbest_mAP_*.pthuse the EMA weights; epoch checkpoints keep raw weights plusema_state_dictfor resume. - AdamW and weight-decay groups —
training.optimizer: adamw(adamw_betas),weight_decay_norm_mult/weight_decay_bias_mult.max_grad_norm: nulldisables clipping. Defaults (SGD, multipliers 1, clip 1.0) are unchanged. lr_scheduler_type: cosine_annealing_late— flat LR after warmup untillr_scheduler_cosine_start_epoch, then cosine tolr_scheduler_cosine_eta_min.preprocessing.random_rotate_rect_labels— tiles containing those classes rotate by 90° steps only (RTMDet usesstorage-tankandroundabout).- Cached mosaic (
preprocessing.enable_mosaicandmosaic_*keys), off by default and off in every published recipe. tools/bench_latency.py— single-tile forward latency (backbone + head + decode + NMS) for several detectors on the same canvas and device.- OSSDD FCOS and Faster R-CNN 3× —
ossdd_le90_vh_3x.jsonandossdd_le90_vh_3x.jsoninherit VH 1× finetunes of the DOTA 1× hubs (36 epochs, MultiStep milestones 24/33, 512 crop, batch 4). - OSSDD mAP —
evaluation.map_iou_thresholdsaverages the area under the precision-recall curve over rotated IoU 0.10 to 0.95 step 0.05. Set on the OSSDD recipes only.best_metricmAP uses that average.iou_thresholdstays 0.5 for GT-cover and the precision-recall operating point. - RTMDet ONNX —
odet export onnx --mode rotated_rtmdet_pre_nms. CSPNeXt + SepBN head + box decode in the graph; rotated NMS stays in Python. Fixed H×W, batch 1, same pre-NMS tensors as FCOS.
Changed¶
- Evaluation split into
val_*andtest_*. Periodic val andmake eval-valuseval_score_threshold(often 0.3).test_mapandmake eval-testusetest_score_threshold(null → 0.05). The 1× schedule setstest_map: trueandval_map_at_end: false. DOTA and FAIR1M pointtest_tiles_dirat the val tiles (leaky).dota-submitstill requires the unlabeled official test and does not readtest_tiles_dir. Older keys (train_val_score_threshold,preds_score_threshold,compute_map_final,compute_map_test, …) remap on load. Published Hub sidecars inpretrained/use the new names. odet preds/make metricsmetrics margin defaults to 0 (every GT and detection is scored). It no longer readsproduction.ignore_margin_pixels, tile overlap, or a margin stored inpredictions.json. Pass--metrics-margin-pixelsfor a positive band. Deploy /image_demostill useproduction.ignore_margin_pixels.- Tutorial notebooks write to
work_dirs/in a checkout (wastutorial_work/).ORIENTED_DET_TUTORIAL_WORKand the Kaggle/kaggle/workingdefault are unchanged.
ONNX export covers Rotated FCOS, Rotated RTMDet, Oriented R-CNN, and Rotated Faster R-CNN.
[0.3.1] - 2026-09-21¶
Patch: Rotated RetinaNet Hub default is OBB (no suffix). Circum-HBB lives at *_hbb. Official Task 1 71.72% (1×) / 73.89% (3×).
Added¶
- Rotated RetinaNet 1× OBB Hub —
rotated_retinanet_dota_le90_1xis now exact convex IoU assign (use_hbb_for_matching: false). Official Task 1 71.72% (AP75 43.46, COCO mAP 42.18; deploy 0.25; leaky eval-val 71.12%; ahead of MMRotate OBB 68.42%). Recipe:dota_le90_1x.json. - Rotated RetinaNet 3× OBB Hub —
rotated_retinanet_dota_le90_3xinherits 1× OBB (36 epochs). Official Task 1 73.89% (AP75 47.11, COCO mAP 44.63; deploy 0.25; leaky eval-val 78.56%). Recipe:dota_le90_3x.json. - HBB Hub slugs — previous circum-HBB weights:
rotated_retinanet_dota_le90_1x_hbb(67.87% Task 1) androtated_retinanet_dota_le90_3x_hbb(70.70% Task 1). odet export— ONNX-only (onnx,infer,demo,preds). Same CLI aspython -m export. TensorFlow / SavedModel stay removed.
Changed¶
- Un-suffixed RetinaNet 1×/3× recipes are OBB; HBB is
dota_le90_*_hbb.json. v0.3.0hf://rotated_retinanet_dota_le90_1x(HBB) and…_3x(HBB) map to the_hbbslugs in 0.3.1. Old Hub filenames stay for 0.3.0 clients. - RetinaNet OBB deploy floor is 0.25 (eval-val F1 0.30 − 0.05). HBB stays 0.35.
Fixed¶
- Deploy
generate_description.pytreats a DOTA class list as v1 full by set equality (Hub sidecars are alphabetical, notDOTA_V1_CLASSESorder). - RetinaNet convex-IoU hull padding no longer fills unused shoelace slots with an exterior dummy vertex (that clamped some IoUs to 1.0). Unused slots repeat the first hull vertex.
[0.3.0] - 2026-09-19¶
Dataset release: native HRSC2016, FAIR1M, SSDD, and HRSID loaders; HRSC Hub 3× zoo; DOTA zoo refreshed to official Task 1 numbers (advertise / finetune from 1×). Restores ONNX-only export (python -m export) after dropping the 0.2 TensorFlow stack.
Added¶
- HRSC2016 (
dataset.format: hrsc2016) — official XML + ImageSets, single-classship, le90 via the DOTA polygon path. Whole-imagekeep_ratio+ pad-32. Optionalodet hrsc-to-dota. Recipes: Oriented R-CNN / Faster R-CNN / FCOS 1× and 3× underconfigs/*/hrsc2016_le90_*.json. Hub 3× held-out ImageSets test:oriented_rcnn_hrsc2016_le90_3x90.41%,rotated_faster_rcnn_hrsc2016_le90_3x88.77%,rotated_fcos_hrsc2016_le90_3x88.34%. FCOS HRSC 1×/3× and two-stage 3× use random rotate p=0.5 ±20°. - FAIR1M (
dataset.format: fair1m) — 37-class XML loader, official + Kaggle layouts,odet fair1m-to-dotathen tile 1024/200. 1× recipes finetune the matching DOTA 1× Hub checkpoint (37-way classifier re-init; no FAIR1M zoo). Local Faster R-CNN 1× tiled-val mAP50 36.70%. Notebook:notebooks/kaggle_fair1m_tutorial.ipynb. See data.md. - SSDD (
dataset.format: ssdd) — SAR ship chips, official last-digit train/test, VOC XML / COCO / DOTA, keep-ratio 608. 1× Faster R-CNN finetuneshf://rotated_faster_rcnn_dota_le90_1x(no SSDD zoo). Local held-out test mAP50 90.34%. Optionalodet ssdd-to-dota. Notebook:notebooks/ssdd_finetune_tutorial.ipynb. - HRSID (
dataset.format: hrsid) — COCO polygons → le90 rbox (n-gons via min-area rect), official train/test (no val), keep-ratio 800. 1× recipes finetune matching DOTA 1× Hub (no HRSID zoo). Local Faster R-CNN 1× held-out test mAP50 78.55% (Wei HBB AP50 >84.7%, not a drop-in match). Genericodet coco-to-dota. - DOTA Hub (official v1.0 Task 1) — advertised / finetune init is 1×. 3× stays on Hub for AP75. Deploy
production.score_thresholdis eval-val global F1 − 0.05. Reports underdocs/eval-reports/. oriented_rcnn_dota_le90_1x76.73% (AP75 50.24, COCO mAP 46.59; deploy 0.55; leaky eval-val 77.66%)oriented_rcnn_dota_le90_3x74.88% (AP75 51.23, COCO mAP 46.91; deploy 0.55; leaky eval-val 82.92%) — September retrain with the diagonal-flip θ fixrotated_faster_rcnn_dota_le90_1x74.42% (AP75 41.90, COCO mAP 42.74; deploy 0.6; leaky eval-val 77.55%)rotated_faster_rcnn_dota_le90_3x74.48% (AP75 45.39, COCO mAP 43.94; deploy 0.6; leaky eval-val 83.46%)rotated_fcos_dota_le90_1x73.07% (AP75 40.40, COCO mAP 41.56; deploy 0.2; leaky eval-val 75.13%)rotated_fcos_dota_le90_3x72.91% (AP75 45.39, COCO mAP 44.18; deploy 0.2; leaky eval-val 82.32%)rotated_retinanet_dota_le90_1x67.87% circum-HBB (AP75 40.08, COCO mAP 38.91; deploy 0.35; leaky eval-val 68.20%; ahead of MMRotate HBB 64.55%)rotated_retinanet_dota_le90_3x70.70% circum-HBB (AP75 43.34, COCO mAP 41.59; deploy 0.35; leaky eval-val 76.51%)- DOTA Task 1 submit —
odet dota-submit/make dota-submitwritesTask1_*.txt+ zip from unlabeled official test (--checkpoint hf://<slug>,--experiment-dir, or--from-json). Inference NMS is 0.1. Test labels stay private; upload to the DOTA v1.0 Task 1 server. resize_mode: keep_ratio— MMRotate-style long-edge scale without square pad; thenpad_size_divisor(bottom-right). HRSC Oriented R-CNN / Faster R-CNN / FCOS 1×/3× use this canvas.- Random rotate (train only) —
preprocessing.enable_random_rotate/random_rotate_prob/random_rotate_angle_range. MMRotatePolyRandomRotateafter flips. RetinaNet 1× RR ablation:dota_le90_1x_rr.json(p=0.5 ±180°; not Hub). training.lr_scheduler_gammaaccepts a number or a list (one factor per milestone).evaluation.train_val_score_threshold: 0.3on all leaf recipes (in-train mAP /best_mAP; dataclass/schema default).preds_score_threshold/production.score_thresholdunchanged.dataset.drop_easy_empty_tilesanddataset.class_tile_oversample_classesfor train-tile sampling.- Class-agnostic final NMS on FCOS / RetinaNet via
model.nms_class_agnostic/production.nms_class_agnostic(defaultfalse). DOTA / HRSC recipes stay class-aware. model.anchor_angles(degrees) for Rotated RetinaNet; Hub 1×/3× stay[0].- Rotated RetinaNet 1× OBB —
dota_le90_1x_obb.jsonsetsuse_hbb_for_matching: false(not Hub). - ONNX export restored (
export/,python -m export/make export-onnx) — pre-NMS ONNX plus Python preprocess / rotated NMS for Rotated FCOS, Oriented R-CNN, and Rotated Faster R-CNN. Supported canvas is fixed H×W (DOTA 1024 tiles). Consumers need only numpy, Pillow, and ONNX Runtime (no PyTorch, no oriented-det). Producer extra:uv pip install -e ".[export]". Not anodetsubcommand. Out of this graph:keep_ratio(HRSC / SSDD / HRSID), sliding-window tiling, RetinaNet detect (heads-only subgraph only). TensorFlow / SavedModel / TFLite are not brought back.
Changed¶
evaluation.train_val_score_thresholdrenames the formerevaluation.score_threshold. Legacyscore_thresholdstill loads with a deprecation warning. In-train mAP usesevaluationonly (production.score_thresholdstays deploy /image_demo).make eval-val/odet predsuse CLI →evaluation.preds_score_threshold→ 0.05.- DOTA / HRSC recipes and Hub sidecars set
production.final_nms_iou_threshold: 0.1(was 0.3 / 0.5 on some sidecars) so deploy /image_demomatch train val and eval-val NMS. Weights are unchanged. HRSC two-stagemax_detections_per_imageis 2000. - Deploy floors are eval-val global F1 − 0.05: DOTA Oriented R-CNN 0.55, Faster R-CNN 0.6, RetinaNet 0.35, FCOS 0.2; HRSC Oriented R-CNN / Faster R-CNN 0.85, FCOS 0.2. 3× inherits the 1× floor.
make eval-valstill uses 0.05. - DOTA 3× recipes are 1× + 36 epochs (milestones
[24, 33]) only. Finetune from 1×, not 3× — 3× leaky eval-val is train+val tile memorization; official AP50 is a wash or a drop; AP75 is the 3× gain. - Rotated RetinaNet DOTA Hub pins
use_hbb_for_matching: true(circum-HBB)._base_/models/rotated_retinanet_r50.jsonremainsfalse(MMRotate OBB default). MaxIoU concatenates P3–P7 then splits by level; assignment is RetinaNet-only (retinanet_assign.py). - Manifest
eval_map50is leaky eval-val for DOTA Task 1 slugs; official scores live ineval_task1_map50.make eval-valis leaky on DOTA and held-out on HRSC / FAIR1M / SSDD / HRSID. Canonical table: Train / eval splits. - DOTA FCOS / RetinaNet 1× inherit
dota_le90.jsonmean/std (were ImageNet). FCOS DOTAdota_le90_3x.jsonis the decoded rIoU 3× recipe (wasdota_le90_3x_riou.json). - Sliding-window last tiles flush to the image edge (
tile_dota.pyparity). Per-window centroid margin default is 0. Micro-batch default is 8 (GPU) / 4 (CPU); unsetORIENTED_DET_WINDOW_BATCH_SIZEno longer VRAM-probes. Setautoto restore probing. odet tile-dotareads JPEG/TIFF/BMP as well as PNG (--output-format auto).odet fair1m-to-dotadefault--image-format originalcopies JPEG/PNG.- Minimum PyTorch 2.4 / torchvision 0.19; NumPy 2 is supported. Docs, convert-tool examples, Gradio viewer default, and published Hub sidecar
source_code_rootuse/path/to/dataand/path/to/oriented-det. loss.focal_weightedscales FCOS / RetinaNet sigmoid focal per class. ROI box-reg aux keys rename toroi_box_reg_aux_weight+roi_box_reg_aux_loss_type.training.lr_scheduler_cosine_t_maxremaps tolr_scheduler_cosine_epochs. Old keys still load with a deprecation warning.make wizard/--wizardFCOS FPN nudges are class-agnostic (pooled GT width vs finest stride). HRSCkeep_ratio/padeval uses the same whole-image scale as training.make eval-valtakesEXPERIMENT=, notCONFIG=.
Fixed¶
- Diagonal flip angle — MMRotate
RRandomFlip(direction='diagonal')mirrors box centers and keeps θ. We incorrectly appliedπ − θ. keep_ratio+pad_size_divisor32 no longer crashes on P6 (odd feature-mapmax_pool); stride derivation falls back to[4, 8, 16, 32, 64]. Collate bottom-right pads a batch to a shared H×W.- Rotated RetinaNet
proj_xy— encode/decode dx/dy in the anchor local frame (no-op for Hubθ = 0priors). odet preds --checkpoint hf://<slug>uses the pretrained sidecar (no longer the latestruns/JSON).dota-submitafter Hub inference includesoutput_dir/predictions_jsonin metadata.- SSDD dump discovery no longer treats
HRSID_JPGas SSDD.python -m oriented_det.cliworks via__main__.py. FAIR1M large rasters setImage.MAX_IMAGE_PIXELS = None.
Removed¶
- TensorFlow / SavedModel / TFLite export, and
odet export-*. ONNX ispython -m exportwithoriented-det[export]. - Hub slugs
rotated_faster_rcnn_dota_le90_3x_ceandrotated_fcos_dota_le90_3x_kfiou_aux(eval reports stay underdocs/eval-reports/). - Rotated RetinaNet 1× oriented-priors ablation (
dota_le90_1x_oriented_anchors.json). Hub staysθ = 0. - HRSC2016 6× recipes. 3× ±20° is the long schedule.
- Notebook geometric transform classes (
Rotate,HorizontalFlip, …). Image+box augs areapply_random_train_flips/apply_random_train_rotateandapply_flip_to_*/apply_rotate_to_*.
[0.2.0] - 2026-08-25¶
Added¶
- Rotated FCOS (
model_type: rotated_fcos) — anchor-free single-stage detector: DistanceAnglePointCoder, center-in-OBB assigner, centerness, and L1 / KFIoU / decoded rIoU box regression. Recipes underconfigs/rotated_fcos/. - Differentiable polygon IoU (
oriented_det.ops.diff_iou_rotated) for FCOSbox_reg_loss_type: riou(1 - IoU). Distinct from samplingpairwise_rotated_iou. Recipesdota_le90_1x_riou.json/dota_le90_3x.json(lr 2.5e-3). - Hub slug
rotated_fcos_dota_le90_3x(81.58% eval-val mAP50) — Rotated FCOS 3× decoded rIoU; reportdocs/eval-reports/rotated_fcos_dota_le90_3x/. - Hub slug
rotated_fcos_dota_le90_3x_kfiou_aux(77.18% eval-val mAP50) — Rotated FCOS 3× L1 + KFIoU aux; reportdocs/eval-reports/rotated_fcos_dota_le90_3x_kfiou_aux/. - TF/ONNX export mode
rotated_fcos_pre_nms— Rotated FCOS decode + pad uses the same Keras detect bundle as two-stage models.
Removed¶
- FCOS 1× ProbIoU-aux recipe (
dota_le90_1x_probiou_aux.json). Train-time mAP50 66.8% vs 76.5% for 1× KFIoU aux on the same protocol.
[0.1.1] - 2026-07-11¶
Added¶
- ProbIoU ROI regression for Rotated Faster R-CNN (
roi_box_reg_main_loss_type: probiou+ Smooth L1 aux). - Hub slugs
rotated_faster_rcnn_dota_le90_3x(83.42% eval-val mAP50) androtated_faster_rcnn_dota_le90_1x(77.57% eval-val mAP50). dataset.train_includes_valconfig flag (Airbus Playground: train on all folds; val fold for monitoring only).- Source provenance metadata in training runs (
git_commit, package version, config hash). - Eval reports under
docs/eval-reports/;make eval-valfull-tile protocol documented.
Changed (MMRotate parity)¶
- ROI regression loss: encoded-space Smooth L1 on all 5 channels (MMRotate), replacing radian periodic angle loss that under-weighted angle gradients vs MMRotate.
- Oriented R-CNN: MMDet
avg_factorfor midpoint RPN and oriented ROI losses; training RPN proposals no longer score-filtered; ROI matching defaults to rotated IoU (roi_use_hbb_for_matching: false); oriented RoIAlign uses first 4 FPN levels only. - Rotated RetinaNet: separate cls/reg 4-conv towers with 3×3 prediction heads; P6/P7 via
LastLevelP6P7on C5; rotated IoU assignment; encoded L1 reg loss withavg_factornormalization.
Breaking¶
- RetinaNet checkpoints from before this release are incompatible (
head.convs/ 1×1 heads /extra_fpn_convremoved). Re-train or use Hub weights published after this change.
[0.1.0] - 2026-05-27¶
Added¶
- Core geometry (Polygon, QBox, RBox) and transforms
- Rotated IoU, NMS, and optional GPU kernels
- DOTA loader, tiling, augmentations, oriented mAP
- Airbus Playground CSV dataset support
- Oriented R-CNN, Rotated Faster R-CNN, Rotated RetinaNet
- JSON config training via
odet train - Pretrained weights on Hugging Face Hub (
dl4eo/oriented-det-pretrained), including Oriented R-CNN 1× DOTA le90 (74.79%eval-val mAP50) and Oriented R-CNN 3× DOTA le90 (79.40%eval-val mAP50) - MkDocs user guide and API reference
Notes¶
- Public home: https://github.com/DL4EO/oriented-det