DOTA is the pretrain zoo. HRSC2016 is the small-data ship zoo.

Three oriented-det families now have native HRSC recipes and published 3× Hub weights: Oriented R-CNN 90.41%, Rotated Faster R-CNN 88.77%, Rotated FCOS 88.34% mAP50. Those numbers are make eval-val on ImageSets test. Test is not in training. That sentence is the whole point of this dataset in our stack — DOTA eval-val is leaky; HRSC eval-val is a real holdout.

This post is the dataset, the recipes, the L4 trains, and the reports. It is a research benchmark. It is not a production ship detector — see the licensing note.

In-train val mAP50 every 4 epochs on the three HRSC 3× runs (non-empty ImageSets test)

In-train val mAP50 every 4 epochs on the three HRSC 3× runs (non-empty ImageSets test)


The dataset Link to heading

Liu, Yuan, Weng, Yang, ICPRAM 2017. High-resolution optical ships from Google Earth, oriented boxes, one class we actually train: ship. Fine-grained Class_ID values in the XML are ignored.

The original escience.cn page is often offline. Use a copy of the official 2016 release, not HRSC2016-MS:

SourceNotes
IEEE DataPort~3.5 GB HRSC2016_dataset.zip; free IEEE account
Baidu AI StudioSame layout MMRotate points at
Kaggle guofeng/hrsc2016kaggle datasets download -d guofeng/hrsc2016

Point dataset.data_root at the folder that contains FullDataSet/ and ImageSets/ (a wrapping HRSC2016/ directory is accepted):

HRSC2016/
  FullDataSet/AllImages/*.bmp
  FullDataSet/Annotations/*.xml
  ImageSets/{train,val,test,trainval}.txt

The paper quotes 1,061 images as 436 train / 181 val / 444 test. The ImageSets we actually train against are trainval 617 (436 + 181) and test 453 (15 of those empty). filter_empty_gt drops the empties from the training-loop val loader (438 kept); make eval-val scores all 453.

SplitImagesShipsIn training?
ImageSets trainval6171,748Yes
ImageSets test453 (15 empty)1,228 (1,188 in VOC AP)No

XML mbox_cx/cy/w/h/ang is a rotated box with angle in radians. The loader (dataset.format: hrsc2016) converts through the same polygon → RBox path as DOTA, so training is le90.

Unlike DOTA, these images fit a whole-image canvas. No odet tile-dota for the Hub recipes. Optional export exists (odet hrsc-to-dota) if you want DOTA folders anyway.

I am not republishing the Google Earth pixels here. Run odet image-demo on a test BMP if you want to see boxes.


Recipes Link to heading

Six configs, two schedules, three families. Hub publishes only.

Family3× (Hub)
Oriented R-CNNhrsc2016_le90_1x.jsonhrsc2016_le90_3x.json
Rotated Faster R-CNNhrsc2016_le90_1x.jsonhrsc2016_le90_3x.json
Rotated FCOShrsc2016_le90_1x.jsonhrsc2016_le90_3x.json

Shared canvas: keep_ratio, long edge 800, pad_size_divisor 32. Horizontal + vertical + diagonal flips. Batch 2, ResNet-50 FPN, ImageNet backbone, frozen_stages: 1. Train from scratch (load_from_checkpoint: null) — these are not DOTA finetunes.

What changes per family:

KnobOriented R-CNNFaster R-CNNFCOS
Box lossSmooth L1 main + ProbIoU aux 0.1ProbIoU main + Smooth L1 aux 0.1decoded rIoU
LR0.0050.0050.0025
lr_scheduler_gamma0.10.1[0.1, 0.5]
Random rotate 1×offoffon p=0.5 ±20°
Random rotate 3×on p=0.5 ±20°on p=0.5 ±20°on (inherited)
Deploy score0.850.850.20

3× is 36 epochs, milestones [24, 33]. FCOS keeps a milder second drop (0.5 instead of 0.1) so the decoded-rIoU head does not get wrecked at epoch 33.

A 6× schedule was trained and removed. It was +0.2 mAP on Oriented R-CNN; FCOS 6× never beat this 3×. ±20° is the long schedule. ±180° on FCOS 6× diverged after epoch 12.

NMS is 0.1 everywhere that matters: train val, make eval-val, deploy. Two-stage HRSC keeps max_detections_per_image 2000. That is MMRotate HRSC test-cfg, not the DOTA deploy floor.


Trains Link to heading

Three published runs, single NVIDIA L4, PyTorch 2.3, AMP off, batch 2, 309 steps/epoch on 617 trainval images.

ModelRunWallMean epochCheckpoint
Oriented R-CNN 3×runs/oriented_rcnn/20260830-1638572h 34m4m 17sbest_mAP_0.90.pth
Faster R-CNN 3×runs/rotated_faster_rcnn/20260831-0358511h 5m1m 50sbest_mAP_0.89.pth
FCOS 3×runs/rotated_fcos/20260831-02001934m57sbest_mAP_0.89.pth

FCOS is ~4.5× faster to train than Oriented R-CNN on this set. Same ratio we saw on DOTA 1× vs FCOS on L4. Oriented RoIAlign over ~2000 proposals is still the tax.

Periodic mAP every 4 epochs (the plot above) is in-train val: 438 non-empty test images, score ≥ 0.05. It is not the Hub number — but it is how the runs actually moved:

  • Oriented R-CNN is already at 62% by epoch 4 and 89% by epoch 12. The rest of 3× is a slow polish to 90.4%.
  • Faster R-CNN crawls until the first LR drop, then jumps (75% at epoch 24 → 88% at epoch 28).
  • FCOS has a real dip at epoch 20 (37%, down from 74% at epoch 16), then recovers after the milestone and sits with Faster R-CNN in the high 88s.

Best checkpoints are not the last epoch. Oriented R-CNN peaked at epoch 32 (90.41% in-train); epoch 36 was 90.39%. Faster R-CNN peaked at 88.92% then 88.31%. FCOS 88.62% then 88.22%. The Hub weights are those best_mAP_*.pth files, re-scored with make eval-val.

# edit dataset.data_root in the config, then:
odet train --config configs/oriented_rcnn/hrsc2016_le90_3x.json
odet train --config configs/rotated_faster_rcnn/hrsc2016_le90_3x.json
odet train --config configs/rotated_fcos/hrsc2016_le90_3x.json

Results Link to heading

Published metric: make eval-val mAP50 on ImageSets test, rotated IoU ≥ 0.50, NMS 0.1, score ≥ 0.05. 453 images. Held-out.

ModelHub slugmAP50F1 peakDeploy --score-thrMean best IoU
Oriented R-CNN 3×oriented_rcnn_hrsc2016_le90_3x90.41%0.940 @ 0.900.850.848
Rotated Faster R-CNN 3×rotated_faster_rcnn_hrsc2016_le90_3x88.77%0.916 @ 0.900.850.785
Rotated FCOS 3×rotated_fcos_hrsc2016_le90_3x88.34%0.904 @ 0.250.200.746

Deploy floors are the same rule as DOTA: eval-val global F1 minus 0.05. Two-stage HRSC scores pile up near 1.00, so F1 peaks at 0.90. FCOS F1 peaks at 0.25. Copying --score-thr 0.85 onto FCOS will hide the scene. That is the same decoder ring as the macOS FCOS note.

F1 versus score threshold on held-out HRSC test — two-stage heads peak at 0.90, FCOS at 0.25

F1 versus score threshold on held-out HRSC test — two-stage heads peak at 0.90, FCOS at 0.25

At each model’s F1 operating point:

TPFPFNPrecisionRecall
Oriented R-CNN @ 0.90114259860.9510.930
Faster R-CNN @ 0.901108821200.9310.902
FCOS @ 0.2511081151200.9060.902

Faster R-CNN and FCOS miss the same 120 ships. FCOS pays for its one-stage head with extra false positives. Oriented R-CNN is ahead on both counts, and the boxes are tighter (mean best IoU 0.85 vs 0.79 vs 0.75). That is the accuracy pick on this set.

Precision–recall on held-out HRSC test (points with at least one true positive)

Precision–recall on held-out HRSC test (points with at least one true positive)

The PR plot is the calibration story in another shape. Two-stage curves live in a high-recall sliver because the scores are peaked. FCOS traces a long high-precision arc down to low recall — usable, just not at 0.85.

Eval reports (per-class AP is one row: ship): oriented_rcnn_hrsc2016_le90_3x, rotated_faster_rcnn_hrsc2016_le90_3x, rotated_fcos_hrsc2016_le90_3x.


What to download Link to heading

odet pretrained download oriented_rcnn_hrsc2016_le90_3x
odet pretrained download rotated_faster_rcnn_hrsc2016_le90_3x
odet pretrained download rotated_fcos_hrsc2016_le90_3x

odet image-demo path/to/test.bmp hf://oriented_rcnn_hrsc2016_le90_3x \
  --score-thr 0.85 --nms-thr 0.1 --out-file out_orcnn.png

Swap the slug for Faster R-CNN (0.85) or FCOS (0.20). Keep --nms-thr 0.1. HRSC recipes use resize_mode: keep_ratio / pad, so inference is one whole-image forward — no sliding windows.

make eval-val still uses score ≥ 0.05. Do not mix that protocol with the deploy floor.


License, again Link to heading

HRSC2016 is a research ship set collected from Google Earth. The Hub weights are research checkpoints. Apache 2.0 covers oriented-det’s code. It does not cover these images, and it does not turn a 90% mAP weight file into a commercial detector.

If you need ships in production, train on imagery you have licensed for that use. The recipes above are the starting point; the pixels have to be yours.



Written on September 13, 2026 by Jeff Faudi. Link to heading