oriented-det 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. export/__init__.py +9 -0
  2. export/ort_runtime.py +67 -0
  3. export/postprocess.py +151 -0
  4. export/scripts/__init__.py +6 -0
  5. export/scripts/build_faster_rcnn_savedmodel.py +104 -0
  6. export/scripts/export_onnx.py +210 -0
  7. export/scripts/onnx_to_savedmodel.py +35 -0
  8. export/scripts/predict_savedmodel.py +94 -0
  9. export/scripts/save_predictions_tf.py +447 -0
  10. export/scripts/to_tflite.py +32 -0
  11. export/tests/test_export_onnx_optional.py +82 -0
  12. export/tests/test_export_wrappers.py +105 -0
  13. export/tests/test_faster_rcnn_export_parity.py +201 -0
  14. export/tests/test_ort_runtime.py +41 -0
  15. export/tf_serving_model.py +96 -0
  16. export/val_dataset.py +116 -0
  17. export/wrappers.py +161 -0
  18. oriented_det/__init__.py +77 -0
  19. oriented_det/cli/__init__.py +92 -0
  20. oriented_det/cli/train.py +18 -0
  21. oriented_det/configs/_base_/augmentation.json +21 -0
  22. oriented_det/configs/_base_/datasets/dota_le90.json +21 -0
  23. oriented_det/configs/_base_/fp16.json +5 -0
  24. oriented_det/configs/_base_/models/oriented_rcnn_r50.json +26 -0
  25. oriented_det/configs/_base_/models/rotated_faster_rcnn_r50.json +53 -0
  26. oriented_det/configs/_base_/models/rotated_retinanet_r50.json +30 -0
  27. oriented_det/configs/_base_/preprocessing.json +8 -0
  28. oriented_det/configs/_base_/schedules/1x.json +33 -0
  29. oriented_det/configs/config.schema.json +404 -0
  30. oriented_det/configs/oriented_rcnn/dota_le90_1x.json +121 -0
  31. oriented_det/configs/oriented_rcnn/dota_le90_3x.json +11 -0
  32. oriented_det/configs/rotated_faster_rcnn/dota_le90_1x.json +119 -0
  33. oriented_det/configs/rotated_faster_rcnn/dota_le90_3x.json +9 -0
  34. oriented_det/configs/rotated_retinanet/dota_le90_1x.json +107 -0
  35. oriented_det/configs/rotated_retinanet/dota_le90_3x.json +30 -0
  36. oriented_det/data/__init__.py +89 -0
  37. oriented_det/data/airbus_playground.py +611 -0
  38. oriented_det/data/dota.py +741 -0
  39. oriented_det/data/dota_classes.py +26 -0
  40. oriented_det/data/evaluation.py +648 -0
  41. oriented_det/data/flips.py +115 -0
  42. oriented_det/data/preprocessing.py +335 -0
  43. oriented_det/data/tiling.py +399 -0
  44. oriented_det/data/transforms.py +377 -0
  45. oriented_det/geometry/__init__.py +8 -0
  46. oriented_det/geometry/poly.py +127 -0
  47. oriented_det/geometry/qbox.py +63 -0
  48. oriented_det/geometry/rbox.py +250 -0
  49. oriented_det/geometry/transforms.py +266 -0
  50. oriented_det/models/__init__.py +36 -0
  51. oriented_det/models/backbones/__init__.py +11 -0
  52. oriented_det/models/backbones/resnet_fpn.py +79 -0
  53. oriented_det/models/backbones/utils.py +81 -0
  54. oriented_det/models/bbox_coder.py +355 -0
  55. oriented_det/models/faster_rcnn_inference.py +494 -0
  56. oriented_det/models/horizontal_roi_coder.py +155 -0
  57. oriented_det/models/oriented_rcnn.py +1256 -0
  58. oriented_det/models/oriented_roi.py +1664 -0
  59. oriented_det/models/oriented_rpn.py +2104 -0
  60. oriented_det/models/rotated_retinanet.py +1030 -0
  61. oriented_det/models/utils.py +590 -0
  62. oriented_det/ops/__init__.py +58 -0
  63. oriented_det/ops/gpu_ops.py +1109 -0
  64. oriented_det/ops/iou.py +172 -0
  65. oriented_det/ops/kfiou.py +275 -0
  66. oriented_det/ops/nms.py +202 -0
  67. oriented_det/ops/probiou.py +165 -0
  68. oriented_det/ops/rotated_ops.py +122 -0
  69. oriented_det/ops/utils.py +257 -0
  70. oriented_det/pretrained/__init__.py +23 -0
  71. oriented_det/pretrained/hub.py +249 -0
  72. oriented_det/pretrained/manifest.json +46 -0
  73. oriented_det/runtime/__init__.py +29 -0
  74. oriented_det/runtime/checkpoint.py +274 -0
  75. oriented_det/runtime/collate.py +348 -0
  76. oriented_det/runtime/inference.py +1286 -0
  77. oriented_det/train/__init__.py +102 -0
  78. oriented_det/train/config.py +872 -0
  79. oriented_det/train/engine.py +2933 -0
  80. oriented_det/train/grouped_ce.py +139 -0
  81. oriented_det/train/piecewise_schedule.py +33 -0
  82. oriented_det/train/profiler.py +287 -0
  83. oriented_det/train/utils.py +999 -0
  84. oriented_det/utils/__init__.py +31 -0
  85. oriented_det/utils/config.py +376 -0
  86. oriented_det/utils/device.py +35 -0
  87. oriented_det/utils/logging.py +163 -0
  88. oriented_det/utils/progress.py +62 -0
  89. oriented_det/utils/viz.py +181 -0
  90. oriented_det-0.1.0.dist-info/METADATA +313 -0
  91. oriented_det-0.1.0.dist-info/RECORD +115 -0
  92. oriented_det-0.1.0.dist-info/WHEEL +5 -0
  93. oriented_det-0.1.0.dist-info/entry_points.txt +2 -0
  94. oriented_det-0.1.0.dist-info/licenses/LICENSE +202 -0
  95. oriented_det-0.1.0.dist-info/top_level.txt +3 -0
  96. tools/__init__.py +1 -0
  97. tools/app.py +1284 -0
  98. tools/dataset_stats.py +389 -0
  99. tools/dota_labels_to_comma.py +132 -0
  100. tools/free_gpu.py +142 -0
  101. tools/generate_airbus_playground_csv.py +154 -0
  102. tools/image_demo.py +200 -0
  103. tools/lr_finder.py +771 -0
  104. tools/measure_sampled_riou_error.py +483 -0
  105. tools/playground_to_dota.py +290 -0
  106. tools/pretrained_download.py +49 -0
  107. tools/preview_augmentation.py +510 -0
  108. tools/publish_checkpoint.py +96 -0
  109. tools/save_predictions.py +2350 -0
  110. tools/sync_vendored_configs.py +94 -0
  111. tools/tile_dota.py +447 -0
  112. tools/train.py +2324 -0
  113. tools/train_example.py +244 -0
  114. tools/train_multi_gpu.py +367 -0
  115. tools/visualize_boxes.py +183 -0
@@ -0,0 +1,404 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/oriented-det/config.schema.json",
4
+ "title": "OrientedDet Training Configuration",
5
+ "description": "Schema for training config files used by tools/train.py. Supports MMRotate-style _base_ inheritance. Written config.json key order: switches first (enable_*), then sections; within sections switch/type first, then keys with same prefix (e.g. lr_scheduler_type then lr_*, roi_*, rpn_*).",
6
+ "type": "object",
7
+ "patternProperties": {
8
+ "^_muted_": true
9
+ },
10
+ "additionalProperties": false,
11
+ "properties": {
12
+ "_base_": {
13
+ "description": "Path(s) to base config(s) to inherit from. Loaded and merged before this config. Paths are relative to the current config file.",
14
+ "oneOf": [
15
+ { "type": "string", "minLength": 1 },
16
+ { "type": "array", "items": { "type": "string", "minLength": 1 } }
17
+ ]
18
+ },
19
+ "model_type": {
20
+ "type": "string",
21
+ "enum": ["oriented_rcnn", "rotated_faster_rcnn", "rotated_retinanet"],
22
+ "description": "Model variant. Must match tools/train.py: oriented_rcnn, rotated_faster_rcnn, or rotated_retinanet.",
23
+ "examples": ["oriented_rcnn", "rotated_retinanet", "rotated_faster_rcnn"]
24
+ },
25
+ "experiment_timestamp": {
26
+ "type": ["string", "null"],
27
+ "description": "Optional run id; set when saving a training experiment."
28
+ },
29
+ "source_recipe": {
30
+ "type": ["string", "null"],
31
+ "description": "Path to the training recipe JSON used for this run (set when saving config.json)."
32
+ },
33
+ "class_map": {
34
+ "type": ["object", "null"],
35
+ "additionalProperties": { "type": "integer" },
36
+ "description": "Saved with checkpoints for inference; not required in hand-written training configs."
37
+ },
38
+ "class_names": {
39
+ "type": ["array", "null"],
40
+ "items": { "type": "string" },
41
+ "description": "Saved with checkpoints; optional in hand-written configs."
42
+ },
43
+ "num_classes": {
44
+ "type": ["integer", "null"],
45
+ "description": "Foreground class count; saved with checkpoints, optional in hand-written configs."
46
+ },
47
+ "dataset": {
48
+ "type": "object",
49
+ "description": "Dataset paths and filtering.",
50
+ "patternProperties": {
51
+ "^_muted_": true
52
+ },
53
+ "additionalProperties": false,
54
+ "properties": {
55
+ "format": {
56
+ "type": "string",
57
+ "default": "dota",
58
+ "enum": ["dota", "airbus_playground"],
59
+ "description": "Dataset format. 'dota' expects train_tiles_dir/val_tiles_dir or train_tiles_dirs/val_tiles_dirs. 'airbus_playground' expects annotations_file/split_file."
60
+ },
61
+ "data_root": { "type": "string", "description": "Root directory of the dataset." },
62
+ "train_tiles_dir": { "type": "string", "description": "Directory containing training tiles (DOTA format)." },
63
+ "val_tiles_dir": { "type": "string", "description": "Directory containing validation tiles (DOTA format)." },
64
+ "train_tiles_dirs": {
65
+ "type": "array",
66
+ "items": { "type": "string" },
67
+ "description": "Optional list of training tile roots (union via ConcatDataset). When set, overrides train_tiles_dir."
68
+ },
69
+ "val_tiles_dirs": {
70
+ "type": "array",
71
+ "items": { "type": "string" },
72
+ "description": "Optional list of validation tile roots (union via ConcatDataset). When set, overrides val_tiles_dir."
73
+ },
74
+ "same_folder": { "type": "boolean", "default": false, "description": "If true, DOTA images and annotation .txt files are in the same directory (train_tiles_dir and val_tiles_dir). If false, expect train_tiles_dir/images and train_tiles_dir/labels (and same for val)." },
75
+ "overlap": {
76
+ "description": "Overlap between adjacent tiles in pixels. 0 = none (e.g. DOTA bases); otherwise use a positive even value (e.g. 16 vehicles, 256 planes). Deploy uses an interior margin of overlap/2 px when production.ignore_margin_pixels is null; overlap 0 disables that margin.",
77
+ "default": 16,
78
+ "oneOf": [
79
+ { "const": 0 },
80
+ { "type": "integer", "minimum": 2, "multipleOf": 2 }
81
+ ]
82
+ },
83
+ "annotations_file": { "type": "string", "description": "Annotations CSV file (Airbus Playground format)." },
84
+ "split_file": { "type": "string", "description": "Split CSV file (Airbus Playground format)." },
85
+ "val_split_id": {
86
+ "type": "integer",
87
+ "default": 0,
88
+ "minimum": 0,
89
+ "description": "For Airbus split.csv with integer fold ids: which fold id is treated as validation (default 0). Ignored when split.csv uses legacy train/val strings."
90
+ },
91
+ "ignore_labels": {
92
+ "type": ["array", "null"],
93
+ "items": { "type": "string" },
94
+ "description": "Labels to ignore for Airbus Playground CSV generation/loading."
95
+ },
96
+ "map_labels": {
97
+ "type": ["object", "null"],
98
+ "additionalProperties": { "type": "string" },
99
+ "description": "Label remapping dictionary for Airbus Playground, e.g. {\"taxi\":\"car\"}."
100
+ },
101
+ "difficult_strategy": { "type": "string", "enum": ["drop", "ignore", "keep"], "default": "drop", "description": "How to handle DOTA 'difficult' annotations: drop at read-time, ignore (MMRotate-style don't-care), or keep as normal GT." },
102
+ "filter_empty_gt": { "type": "boolean", "default": false, "description": "DOTA only: drop tiles with no ground truth after difficult_strategy, allowed_classes, and ignore_labels (MMRotate DOTADataset filter_empty_gt parity). Default false keeps empty tiles." },
103
+ "max_train_samples": { "type": ["integer", "null"], "description": "Cap training samples (for overfitting sanity checks)." },
104
+ "max_val_samples": { "type": ["integer", "null"], "description": "Cap validation samples." },
105
+ "max_samples_shuffle_seed": {
106
+ "type": ["integer", "null"],
107
+ "description": "When set with max_train_samples or max_val_samples, pick a deterministic random subset (spread across dataset order) instead of the first N indices."
108
+ },
109
+ "allowed_classes": {
110
+ "type": ["array", "null"],
111
+ "items": { "type": "string" },
112
+ "description": "Restrict to these class names. null = all classes."
113
+ },
114
+ "tile_metrics_csv": {
115
+ "type": ["string", "null"],
116
+ "description": "CSV from save_predictions tile metrics; join on image_id (stem) to oversample hard tiles."
117
+ },
118
+ "hard_tile_metric_column": { "type": "string", "default": "f1", "description": "Column in tile_metrics_csv compared to hard_tile_threshold." },
119
+ "hard_tile_threshold": { "type": "number", "default": 0.8, "description": "Tiles with metric strictly below this are oversampled." },
120
+ "hard_tile_oversample_factor": { "type": "number", "default": 2.0, "description": "Sampling weight multiplier for hard tiles (WeightedRandomSampler)." }
121
+ }
122
+ },
123
+ "data_loader": {
124
+ "type": "object",
125
+ "description": "PyTorch DataLoader settings.",
126
+ "patternProperties": {
127
+ "^_muted_": true
128
+ },
129
+ "additionalProperties": false,
130
+ "properties": {
131
+ "batch_size": { "type": "integer", "default": 16, "minimum": 1, "description": "Samples per batch per GPU." },
132
+ "num_workers": { "type": "integer", "default": 4, "minimum": 0, "description": "DataLoader worker processes." },
133
+ "shuffle": { "type": "boolean", "default": true, "description": "Shuffle training data each epoch." },
134
+ "pin_memory": { "type": "boolean", "default": true, "description": "Pin memory for faster GPU transfer." }
135
+ }
136
+ },
137
+ "model": {
138
+ "type": "object",
139
+ "description": "Model architecture. Keys grouped by prefix: backbone, fpn_*, anchor_*, target_*, roi_*, rpn_*, nms_*, etc.",
140
+ "patternProperties": {
141
+ "^_muted_": true
142
+ },
143
+ "additionalProperties": false,
144
+ "properties": {
145
+ "backbone": { "type": "string", "default": "resnet50", "enum": ["resnet18", "resnet34", "resnet50", "resnet101"], "description": "Backbone architecture." },
146
+ "pretrained_backbone": { "type": "boolean", "default": true, "description": "Load ImageNet pretrained weights for backbone." },
147
+ "trainable_layers": { "type": "integer", "default": 5, "description": "Number of backbone layers to train. 5 = all layers." },
148
+ "frozen_stages": { "type": ["integer", "null"], "description": "If set, overrides trainable_layers: freeze this many stages from the start (MMRotate: 1 = freeze stage 1, effective trainable_layers=3)." },
149
+ "fpn_returned_layers": { "type": "array", "items": { "type": "integer" }, "default": [1, 2, 3, 4], "description": "Backbone layers for FPN (1-based). Default [1, 2, 3, 4] = C2-C5 (5 levels); [2, 3, 4] = C3-C5 only (4 levels)." },
150
+ "fpn_strides": { "type": ["array", "null"], "items": { "type": "integer" }, "description": "Optional nominal FPN strides for ROI module init and logs. Training/inference derive strides from image size and feature map shapes so anchors and ROI align match the grid; a warning is emitted if this list disagrees with the derived values." },
151
+ "fpn_extra_level": { "type": "boolean", "default": false, "description": "RetinaNet: append stride-128 FPN level via 3x3 conv (MMRotate P7)." },
152
+ "anchor_scales": { "type": "array", "items": { "type": "integer" }, "description": "Anchor scales. Single scale [8] recommended with FPN." },
153
+ "anchor_ratios": { "type": "array", "items": { "type": "number" }, "description": "Anchor aspect ratios. e.g. [0.5, 1, 2]." },
154
+ "anchor_octave_base_scale": { "type": ["number", "null"], "default": null, "description": "RetinaNet MMRotate octave_base_scale (with anchor_scales_per_octave)." },
155
+ "anchor_scales_per_octave": { "type": ["integer", "null"], "default": null, "description": "RetinaNet MMRotate scales_per_octave (e.g. 3)." },
156
+ "target_means": { "type": "array", "items": { "type": "number" }, "minItems": 5, "maxItems": 5, "description": "Box regression target means [dx, dy, dw, dh, dangle]." },
157
+ "target_stds": { "type": "array", "items": { "type": "number" }, "minItems": 5, "maxItems": 5, "description": "Box regression target stds [dx, dy, dw, dh, dangle]." },
158
+ "roi_loss_type": { "type": "string", "enum": ["cross_entropy", "focal"], "default": "cross_entropy", "description": "ROI classification loss: cross_entropy or focal." },
159
+ "roi_focal_alpha": { "type": "number", "default": 1.0, "description": "Focal loss alpha (when roi_loss_type is focal)." },
160
+ "roi_focal_gamma": { "type": "number", "default": 2.0, "description": "Focal loss gamma (when roi_loss_type is focal)." },
161
+ "roi_norm_factor": { "type": ["number", "null"], "description": "Angle scaling for ROI. null for RetinaNet (MMRotate match)." },
162
+ "roi_edge_swap": { "type": "boolean", "default": true, "description": "Use edge_swap for ROI bbox coder." },
163
+ "roi_proj_xy": { "type": "boolean", "default": false, "description": "If true, encode/decode ROI dx/dy in proposal local frame (MMRotate DeltaXYWHTRBBoxCoder proj_xy)." },
164
+ "roi_box_reg_angle_weight": { "type": "number", "default": 1.0, "description": "Weight for angle (5th) in ROI box regression; use > 1 for better alignment." },
165
+ "roi_box_reg_angle_schedule_epochs": { "type": ["array", "null"], "items": { "type": "integer" }, "description": "0-based epoch boundaries for roi_box_reg_angle_weight schedule." },
166
+ "roi_box_reg_angle_schedule_values": { "type": ["array", "null"], "items": { "type": "number" }, "description": "Angle SmoothL1 weight per schedule segment. When null, roi_box_reg_angle_weight is constant." },
167
+ "roi_box_reg_iou_weight": { "type": "number", "default": 0.0, "description": "Extra auxiliary loss weight on decoded ROI positives; see roi_box_reg_iou_loss_type." },
168
+ "roi_box_reg_iou_schedule_epochs": { "type": ["array", "null"], "items": { "type": "integer" }, "description": "0-based epoch boundaries for roi_box_reg_iou_weight schedule (same convention as final_nms_iou_schedule_epochs)." },
169
+ "roi_box_reg_iou_schedule_values": { "type": ["array", "null"], "items": { "type": "number" }, "description": "Auxiliary IoU loss weight per schedule segment. When null, roi_box_reg_iou_weight is constant." },
170
+ "roi_box_reg_iou_loss_type": { "type": "string", "default": "riou", "enum": ["riou", "kfiou", "probiou"], "description": "Auxiliary regression term when roi_box_reg_iou_weight > 0: riou = mean(1 - rIoU); kfiou = Kalman-filter IoU surrogate; probiou = mean ProbIoU (Gaussian BBox)." },
171
+ "roi_box_reg_kfiou_fun": { "type": ["string", "null"], "default": null, "enum": [null, "none", "ln", "exp"], "description": "When roi_box_reg_iou_loss_type is kfiou, overlap mapping: none → 1-KFIoU; ln → -log(KFIoU); exp → exp(1-KFIoU)-1." },
172
+ "roi_box_reg_probiou_mode": { "type": ["string", "null"], "default": null, "enum": [null, "l1", "l2"], "description": "When roi_box_reg_iou_loss_type is probiou, metric variant: l1 (bounded, default) or l2 (-log(1-l1^2))." },
173
+ "retinanet_stacked_convs": { "type": "integer", "default": 1, "minimum": 1, "description": "RetinaNet shared 3x3 conv depth before cls/reg (MMRotate: 4)." },
174
+ "box_reg_loss_type": { "type": "string", "default": "smooth_l1", "enum": ["smooth_l1", "l1"], "description": "RetinaNet box regression loss (MMRotate: l1)." },
175
+ "box_reg_weight": { "type": "number", "default": 1.0, "description": "RetinaNet box regression loss weight." },
176
+ "roi_batch_size_per_image": { "type": "integer", "default": 512, "description": "ROI proposals to sample per image for training." },
177
+ "roi_positive_iou_threshold": { "type": "number", "default": 0.5, "description": "IoU threshold for positive ROI proposals." },
178
+ "roi_negative_iou_threshold": { "type": "number", "default": 0.5, "description": "IoU threshold for negative ROI proposals." },
179
+ "roi_match_low_quality": { "type": "boolean", "default": false, "description": "Force best proposal per GT to positive (MMRotate RCNN: false)." },
180
+ "roi_min_pos_iou": { "type": "number", "default": 0.5, "description": "Min IoU for low-quality ROI matches when roi_match_low_quality is true (MMRotate RCNN assigner min_pos_iou)." },
181
+ "rpn_min_size": { "type": "number", "default": 0.0, "description": "Min proposal side length in pixels. 2-4 filters tiny boxes." },
182
+ "rpn_pre_nms_top_n": { "type": "integer", "default": 2000, "description": "Max RPN proposals to keep before NMS per level." },
183
+ "rpn_post_nms_top_n": { "type": "integer", "default": 1000, "description": "Max RPN proposals after NMS (fed to ROI head)." },
184
+ "rpn_nms_threshold": { "type": "number", "default": 0.7, "description": "RPN proposal NMS IoU threshold (Rotated Faster R-CNN / Oriented R-CNN)." },
185
+ "rpn_batch_size_per_image": { "type": "integer", "default": 256, "description": "RPN anchors to sample per image (MMRotate: 256)." },
186
+ "rpn_positive_iou_threshold": { "type": "number", "default": 0.7, "description": "IoU threshold for positive RPN anchors." },
187
+ "rpn_negative_iou_threshold": { "type": "number", "default": 0.3, "description": "IoU threshold for negative RPN anchors." },
188
+ "rpn_min_pos_iou": { "type": "number", "default": 0.3, "description": "Min IoU for best-anchor-per-GT to be positive (MMRotate RPN)." },
189
+ "rpn_match_low_quality": { "type": "boolean", "default": true, "description": "Force best anchor per GT to positive when IoU >= rpn_min_pos_iou." },
190
+ "use_hbb_for_matching": { "type": "boolean", "default": false, "description": "Use axis-aligned (HBB) IoU for matching. When true, helps angle regression and classifier stability (e.g. TOY-200)." },
191
+ "add_gt_as_proposals": { "type": "boolean", "default": true, "description": "Append GT boxes to RPN proposals in training (MMRotate default)." },
192
+ "final_nms_iou_threshold": { "type": "number", "default": 0.5, "description": "Final detection NMS IoU threshold after ROI head (distinct from rpn_nms_threshold)." },
193
+ "nms_class_agnostic": { "type": "boolean", "default": false, "description": "If true, run one oriented NMS on all classes (suppresses overlapping car/truck); if false, NMS per class (default)." },
194
+ "final_nms_use_cpu": { "type": "boolean", "default": false, "description": "If true, final detection oriented NMS uses exact polygon IoU on CPU (slower; ignores GPU sampling NMS and ORIENTED_DET_ROTATED_BACKEND for that step only)." },
195
+ "final_nms_iou_schedule_epochs": { "type": ["array", "null"], "items": { "type": "integer" }, "description": "Epoch boundaries for final detection NMS IoU schedule (same parameter as final_nms_iou_threshold)." },
196
+ "final_nms_iou_schedule_values": { "type": ["array", "null"], "items": { "type": "number" }, "description": "Final NMS IoU values per segment." },
197
+ "max_detections_per_image": { "type": "integer", "default": 100, "description": "Max detections to keep per image after final NMS." },
198
+ "inference_pre_nms_score_threshold": { "type": "number", "default": 0.05, "description": "Pre-NMS score threshold for detection candidates." },
199
+ "roi_inference_top_class_only": { "type": "boolean", "default": false, "description": "Two-stage ROI inference: if true, argmax foreground class per proposal (MMRotate-style); if false, keep every class above inference_pre_nms_score_threshold. Prefer false early in training; true for late fine-tune and deployment." }
200
+ }
201
+ },
202
+ "training": {
203
+ "type": "object",
204
+ "description": "Training hyperparameters. Keys: lr_scheduler_type (switch) first, then lr_* grouped, then rest.",
205
+ "patternProperties": {
206
+ "^_muted_": true
207
+ },
208
+ "additionalProperties": false,
209
+ "properties": {
210
+ "lr_scheduler_type": { "type": ["string", "null"], "description": "LR scheduler: null/'multistep'/'step' = MultiStepLR/StepLR; 'reduce_on_plateau' = ReduceLROnPlateau; 'one_cycle' = OneCycleLR (per-step); 'cosine_annealing'/'cosine' = PyTorch CosineAnnealingLR (SGDR restarts if num_epochs > T_max); 'cosine_annealing_with_tail'/'cosine_with_tail' = cosine phase then fixed tail_lr." },
211
+ "lr_scheduler_step_epochs": { "type": "integer", "default": 8, "description": "StepLR period in epochs (LR *= gamma every N epochs). Distinct from lr_warmup_steps (optimizer steps)." },
212
+ "lr_scheduler_milestones": { "type": ["array", "null"], "items": { "type": "integer" }, "description": "Optional MultiStepLR milestones in epochs. When set, takes precedence over lr_scheduler_step_epochs." },
213
+ "lr_scheduler_gamma": { "type": "number", "default": 0.1, "description": "Factor by which LR is multiplied at each step (StepLR) or milestone (MultiStepLR)." },
214
+ "lr_scheduler_plateau_metric": { "type": "string", "default": "total_loss", "description": "Metric to monitor for ReduceLROnPlateau. Use 'mAP' (mode=max) or 'total_loss' (mode=min)." },
215
+ "lr_scheduler_plateau_factor": { "type": "number", "default": 0.1, "description": "ReduceLROnPlateau: factor by which LR is multiplied when metric plateaus." },
216
+ "lr_scheduler_plateau_patience": { "type": "integer", "default": 5, "description": "ReduceLROnPlateau: number of epochs with no improvement before reducing LR." },
217
+ "lr_scheduler_one_cycle_pct_start": { "type": "number", "default": 0.3, "description": "OneCycleLR: fraction of total steps for warmup phase." },
218
+ "lr_scheduler_one_cycle_div_factor": { "type": "number", "default": 25.0, "description": "OneCycleLR: initial_lr = max_lr / div_factor." },
219
+ "lr_scheduler_one_cycle_final_div_factor": { "type": "number", "default": 1e4, "description": "OneCycleLR: min_lr = initial_lr / final_div_factor." },
220
+ "lr_scheduler_cosine_t_max": { "type": ["integer", "null"], "description": "Legacy alias for cosine phase length when lr_scheduler_cosine_epochs is unset. Same meaning as CosineAnnealingLR T_max." },
221
+ "lr_scheduler_cosine_eta_min": { "type": "number", "default": 1e-6, "description": "Minimum LR at end of cosine phase (eta_min)." },
222
+ "lr_scheduler_cosine_epochs": { "type": ["integer", "null"], "minimum": 1, "description": "Cosine decay length in epochs. With tail settings, num_epochs should equal cosine_epochs + tail_epochs." },
223
+ "lr_scheduler_cosine_tail_epochs": { "type": "integer", "default": 0, "minimum": 0, "description": "Fixed-LR tail after cosine (0 = auto from num_epochs - cosine_epochs when longer)." },
224
+ "lr_scheduler_cosine_tail_lr": { "type": ["number", "null"], "description": "Constant LR during tail; default lr_scheduler_cosine_eta_min." },
225
+ "lr_warmup_steps": { "type": "integer", "default": 500, "description": "Number of optimizer steps for linear warmup." },
226
+ "lr_scaling_with_accumulation": { "type": "string", "enum": ["linear", "sqrt", "none"], "default": "linear", "description": "Scale base LR by effective batch size: linear, sqrt, or none." },
227
+ "lr_scale_with_world_size": { "type": "boolean", "default": false, "description": "If true, multiply base LR by DDP world size. MMRotate parity mode keeps this false." },
228
+ "use_lr_param_groups": { "type": "boolean", "default": false, "description": "If true, use per-module learning rate multipliers (backbone, RPN, ROI, RetinaNet head, other)." },
229
+ "lr_mult_backbone": { "type": "number", "default": 0.5, "description": "LR multiplier for backbone parameters." },
230
+ "lr_mult_rpn": { "type": "number", "default": 0.5, "description": "LR multiplier for RPN head (ignored for rpn_head.* when lr_mult_head is set)." },
231
+ "lr_mult_roi": { "type": "number", "default": 2.0, "description": "LR multiplier for ROI head (ignored for roi_head.* when lr_mult_head is set)." },
232
+ "lr_mult_other": { "type": "number", "default": 1.0, "description": "LR multiplier for other parameters." },
233
+ "lr_mult_head": { "type": ["number", "null"], "default": null, "description": "Optional LR multiplier for head.* (RetinaNet). When set, rpn_head.* and roi_head.* use the same multiplier (single knob for detector heads); when null, head.* uses lr_mult_other and two-stage heads use lr_mult_rpn / lr_mult_roi." },
234
+ "num_epochs": { "type": "integer", "default": 20, "minimum": 1, "description": "Number of training epochs." },
235
+ "learning_rate": { "type": "number", "default": 0.001, "description": "Base learning rate (scaled by gradient accumulation / world size when configured)." },
236
+ "momentum": { "type": "number", "default": 0.9, "description": "SGD momentum." },
237
+ "weight_decay": { "type": "number", "default": 0.0001, "description": "Weight decay (L2)." },
238
+ "use_amp": { "type": "boolean", "default": true, "description": "Mixed precision (FP16) training." },
239
+ "gradient_accumulation_steps": { "type": "integer", "default": 2, "minimum": 1, "description": "Accumulate gradients over this many steps; effective batch = batch_size × this." },
240
+ "max_grad_norm": { "type": "number", "default": 1.0, "description": "Gradient clipping." },
241
+ "freeze_backbone_epochs": { "type": "integer", "default": 0, "minimum": 0, "description": "While training loop epoch index epoch < N (0-based), freeze backbone.* (requires_grad=False). ROI head still trains. 0 = disabled." },
242
+ "freeze_rpn_epochs": { "type": "integer", "default": 0, "minimum": 0, "description": "While epoch < N, freeze rpn_head.* on two-stage detectors. No-op without rpn_head (e.g. RetinaNet). 0 = disabled." },
243
+ "loss_weights": { "type": ["object", "null"], "additionalProperties": { "type": "number" }, "description": "Per-loss weights, e.g. { \"loss_box_reg\": 0.5 } to stabilize ROI head." },
244
+ "early_stop_patience": { "type": ["integer", "null"], "default": null, "description": "If set, stop training after this many epochs without improvement on early_stop_metric (null = disabled)." },
245
+ "early_stop_metric": { "type": "string", "default": "mAP", "description": "Validation metric key for early stopping (e.g. mAP). Skips update when mAP was not computed (-1)." },
246
+ "early_stop_min_delta": { "type": "number", "default": 0, "description": "Minimum change to qualify as improvement for early stopping." },
247
+ "early_stop_higher_is_better": { "type": ["boolean", "null"], "default": null, "description": "If null, inferred from metric name (mAP/AP_* = higher)." }
248
+ }
249
+ },
250
+ "evaluation": {
251
+ "type": "object",
252
+ "description": "Evaluation settings.",
253
+ "patternProperties": {
254
+ "^_muted_": true
255
+ },
256
+ "additionalProperties": false,
257
+ "properties": {
258
+ "score_threshold": { "type": "number", "default": 0.5, "description": "Min confidence for detections and TensorBoard viz." },
259
+ "per_class_score_threshold": {
260
+ "type": ["object", "null"],
261
+ "additionalProperties": { "type": "number" },
262
+ "description": "Optional class_name -> min score; classes not listed use score_threshold."
263
+ },
264
+ "iou_threshold": { "type": "number", "default": 0.5, "description": "IoU threshold for mAP." },
265
+ "compute_map_every_n_epochs": { "type": "integer", "default": 0, "description": "If >0, compute mAP every N epochs during training (current model). 0 = only at end; final mAP uses best checkpoint when compute_map_final is true." },
266
+ "compute_map_final": { "type": "boolean", "default": true, "description": "If true, after training load the best checkpoint and compute mAP once (final mAP uses best model)." },
267
+ "extended_gt_metrics": { "type": "boolean", "default": false, "description": "If true, compute expensive GT–IoU histogram diagnostics (mean/median/buckets, 0% best-IoU GT count, wrong-class counts) and class-agnostic duplicate rate on post-threshold detections (same schedule as mAP during training)." },
268
+ "use_exact_rotated_iou": { "type": "boolean", "default": true, "description": "When true, periodic mAP and GT-cover / accuracy matching use exact CPU polygon IoU (Shapely when installed). When false, use GPU sampling IoU (faster, approximate). Does not affect final detection NMS or production/deploy decode." },
269
+ "use_exact_rotated_iou_for_final_map": { "type": ["boolean", "null"], "default": null, "description": "IoU backend for compute_map_final only (best-checkpoint mAP after training). When null, uses use_exact_rotated_iou. Set true for exact publishable final mAP while keeping periodic in-training mAP on GPU sampling." }
270
+ }
271
+ },
272
+ "production": {
273
+ "type": "object",
274
+ "description": "Production overrides (deploy, save_predictions): score_threshold and per_class_score_threshold (merge with evaluation); mAP IoU is evaluation.iou_threshold only. Decode/NMS patch model only in load_model_from_checkpoint / deploy / image_demo — not during tools/train.py. Sliding-window: overlap, margin, canvas. Null fields fall back to evaluation/model/dataset or deploy defaults.",
275
+ "patternProperties": {
276
+ "^_muted_": true
277
+ },
278
+ "additionalProperties": false,
279
+ "properties": {
280
+ "score_threshold": { "type": ["number", "null"], "default": null, "description": "When set, overrides evaluation.score_threshold for mAP / val matching and deploy display score (resolve_inference_score_threshold)." },
281
+ "per_class_score_threshold": {
282
+ "type": ["object", "null"],
283
+ "additionalProperties": { "type": "number" },
284
+ "description": "Per-class floors merged after evaluation.per_class_score_threshold (same keys update/override)."
285
+ },
286
+ "final_nms_iou_threshold": { "type": ["number", "null"], "default": null, "description": "Same meaning as model.final_nms_iou_threshold; when set, patches the live model after checkpoint load." },
287
+ "final_nms_use_cpu": { "type": ["boolean", "null"], "default": null, "description": "When set, patches model.final_nms_use_cpu (exact polygon NMS on CPU)." },
288
+ "inference_pre_nms_score_threshold": { "type": ["number", "null"], "default": null, "description": "Decoder pre-NMS score floor; when set, patches model.inference_pre_nms_score_threshold (or RetinaNet score_threshold)." },
289
+ "max_detections_per_image": { "type": ["integer", "null"], "default": null, "description": "When set, patches model.max_detections_per_image." },
290
+ "nms_class_agnostic": { "type": ["boolean", "null"], "default": null, "description": "When set, patches model.nms_class_agnostic (two-stage / RetinaNet where supported)." },
291
+ "roi_inference_top_class_only": { "type": ["boolean", "null"], "default": null, "description": "Two-stage only: when set, patches model.roi_inference_top_class_only." },
292
+ "rpn_pre_nms_top_n": { "type": ["integer", "null"], "default": null, "description": "When set, patches model.rpn_pre_nms_top_n (two-stage)." },
293
+ "rpn_post_nms_top_n": { "type": ["integer", "null"], "default": null, "description": "When set, patches model.rpn_post_nms_top_n (two-stage)." },
294
+ "rpn_nms_threshold": { "type": ["number", "null"], "default": null, "description": "When set, patches model.rpn_nms_threshold (two-stage proposal NMS)." },
295
+ "overlap_pixels": { "type": ["integer", "null"], "default": null, "description": "Sliding-window overlap in pixels per axis; null = 200 (same default as oriented_det.runtime.inference)." },
296
+ "ignore_margin_pixels": { "type": ["number", "null"], "default": null, "description": "Interior margin (px): drop detections whose centroid lies in the outer band; null = dataset.overlap/2 (0 disables)." },
297
+ "use_first_image_canvas": { "type": ["boolean", "null"], "default": null, "description": "Deploy: expand square canvas from first image (fixed resize); null = false." },
298
+ "stick_to_model_canvas": { "type": ["boolean", "null"], "default": null, "description": "Deploy: always use config target_size; null = true." }
299
+ }
300
+ },
301
+ "tensorboard": {
302
+ "type": "object",
303
+ "description": "TensorBoard and validation logging options.",
304
+ "patternProperties": {
305
+ "^_muted_": true
306
+ },
307
+ "additionalProperties": false,
308
+ "properties": {
309
+ "log_debug_anchors_proposals": { "type": "boolean", "default": false, "description": "Log val/debug_anchors and val/debug_proposals (random val image each epoch with RPN anchors and proposals overlaid). Only applies to RCNN-style models." },
310
+ "vis_score_threshold": { "type": ["number", "null"], "default": null, "description": "Min score for boxes in TensorBoard prediction images; null = use evaluation.score_threshold." }
311
+ }
312
+ },
313
+ "checkpoint": {
314
+ "type": "object",
315
+ "description": "Checkpoint loading and best-model saving.",
316
+ "patternProperties": {
317
+ "^_muted_": true
318
+ },
319
+ "additionalProperties": false,
320
+ "properties": {
321
+ "load_from_checkpoint": { "type": ["string", "null"], "description": "Path to checkpoint file (.pth), relative path under project root (e.g. pretrained/...), or hf://<asset> for Hugging Face Hub download when missing." },
322
+ "load_from_experiment": { "type": ["string", "null"], "description": "Path to experiment directory." },
323
+ "discover_previous_run": { "type": "boolean", "default": false, "description": "If true, when load_from_experiment is null and load_from_checkpoint does not point to an existing file, set load_from_experiment to the newest other run under runs/<model_type>/. If false, never auto-fill (scratch training unless paths are set)." },
324
+ "resume_from_checkpoint_epoch": { "type": "boolean", "default": true, "description": "When loading from an experiment dir: if true, use latest checkpoint_epoch_*.pth and continue training from that epoch (optimizer/scheduler per load_* flags). If false, prefer best_* checkpoint and usually start at epoch 0 with fresh optimizer unless overridden." },
325
+ "load_optimizer_state": { "type": "boolean", "default": true, "description": "When loading a checkpoint, restore optimizer state if present." },
326
+ "load_scheduler_state": { "type": "boolean", "default": true, "description": "When resume_from_checkpoint_epoch is true, restore LR scheduler state from checkpoint if true. Set false with lr_warmup_steps=0 to rebuild cosine (see tools/train.py continuation path)." },
327
+ "start_epoch": { "type": "integer", "default": 0, "description": "Epoch index to start from (overridden when resuming)." },
328
+ "best_metric": { "type": "string", "default": "total_loss", "description": "Metric used to save the best checkpoint. Use 'mAP' to save at best validation mAP, or 'total_loss' to save at lowest loss. evaluation.compute_map_final uses the best checkpoint for final mAP." },
329
+ "higher_is_better": { "type": ["boolean", "null"], "default": null, "description": "If true, higher metric value is better (e.g. mAP). If false, lower is better (e.g. total_loss). If null, inferred from best_metric ('mAP' -> true, else false)." },
330
+ "load_include_prefixes": { "type": ["array", "null"], "items": { "type": "string" }, "description": "When loading checkpoint: load only weights whose key starts with one of these prefixes. null = no filter." },
331
+ "load_exclude_prefixes": { "type": ["array", "null"], "items": { "type": "string" }, "description": "When loading checkpoint: do not load weights whose key starts with one of these prefixes. null = no filter." }
332
+ }
333
+ },
334
+ "loss": {
335
+ "type": "object",
336
+ "description": "Loss configuration. Keys: loss_type (switch) first, then rest.",
337
+ "patternProperties": {
338
+ "^_muted_": true
339
+ },
340
+ "additionalProperties": false,
341
+ "properties": {
342
+ "loss_type": { "type": "string", "enum": ["cross_entropy", "class_weighted", "focal", "focal_weighted", "none"], "default": "class_weighted", "description": "Experiment-level ROI loss recipe: cross_entropy = plain CE (MMRotate-style), class_weighted = CE with dataset-derived weights, focal = unweighted focal, focal_weighted = focal with dataset-derived weights, none = legacy fallback to model.roi_loss_type." },
343
+ "class_weight_method": { "type": "string", "enum": ["sqrt", "inv_freq", "effective_num", "log_inv_freq"], "default": "sqrt", "description": "How to compute class weights from counts." },
344
+ "class_weight_beta": { "type": "number", "default": 0.9999, "description": "effective_num only: beta parameter close to 1.0 for smoother weights." },
345
+ "class_weight_schedule_type": { "type": ["string", "null"], "default": null, "enum": [null, "linear_ramp"], "description": "Optional schedule for ROI class weights. When set to 'linear_ramp', weights ramp from uniform -> computed weights between start/end epochs." },
346
+ "class_weight_schedule_start_epoch": { "type": "integer", "default": 0, "description": "Schedule start epoch (inclusive) for class weight ramp." },
347
+ "class_weight_schedule_end_epoch": { "type": "integer", "default": 0, "description": "Schedule end epoch (inclusive-ish). Must be > start_epoch to enable ramp." },
348
+ "class_weight_schedule_power": { "type": "number", "default": 1.0, "description": "Ramp exponent: 1.0 linear, >1 delays the effect (eases in), <1 speeds it up." },
349
+ "background_weight": { "type": ["number", "null"], "default": null, "description": "Optional weight override for background class (index 0) in ROI classifier." },
350
+ "focal_alpha": { "type": "number", "default": 1.0, "description": "Focal loss alpha (when loss_type is focal or focal_weighted)." },
351
+ "focal_gamma": { "type": "number", "default": 2.0, "description": "Focal loss gamma (when loss_type is focal or focal_weighted)." },
352
+ "class_weight_overrides": { "type": ["object", "null"], "additionalProperties": { "type": "number" }, "description": "Optional per-class weight overrides, e.g. {\"truck\": 0.25} to reduce dominant-class bias." },
353
+ "label_smoothing": { "type": "number", "default": 0, "minimum": 0, "maximum": 1, "description": "Label smoothing for ROI classification (e.g. 0.1)." },
354
+ "roi_grouped_ce_enabled": { "type": "boolean", "default": false, "description": "When true, use coarse-to-fine grouped cross-entropy on the ROI classifier (single-run curriculum)." },
355
+ "roi_grouped_ce_groups": { "type": ["object", "null"], "additionalProperties": { "type": "array", "items": { "type": "string" } }, "description": "Maps group name to class names, e.g. {\"plane\": [\"Bomber Aircraft\", \"Fighter Aircraft\", ...]}." },
356
+ "roi_grouped_ce_schedule_type": { "type": ["string", "null"], "default": null, "enum": [null, "step", "linear_ramp"], "description": "Grouped CE mix schedule: step = grouped until end_epoch then fine CE; linear_ramp = blend grouped→fine from start to end epoch." },
357
+ "roi_grouped_ce_schedule_start_epoch": { "type": "integer", "default": 0, "description": "Grouped CE schedule start epoch (linear_ramp)." },
358
+ "roi_grouped_ce_schedule_end_epoch": { "type": "integer", "default": 8, "description": "Grouped CE schedule end epoch (step: first fine epoch; ramp: last grouped-heavy epoch)." },
359
+ "roi_grouped_ce_schedule_power": { "type": "number", "default": 1.0, "description": "Ramp exponent for linear_ramp (1.0 = linear)." }
360
+ }
361
+ },
362
+ "preprocessing": {
363
+ "type": "object",
364
+ "description": "Image preprocessing. Keys: resize_mode (switch) first, then target_size, normalize_*, pad_*, enable_flip_*.",
365
+ "patternProperties": {
366
+ "^_muted_": true
367
+ },
368
+ "additionalProperties": false,
369
+ "properties": {
370
+ "resize_mode": { "type": "string", "default": "fixed", "description": "\"fixed\" = stretch to (H,W); \"pad\" = uniform scale so longer edge equals max(H,W) then zero-pad; \"crop\" = native-res crop/pad to (H,W)." },
371
+ "target_size": { "type": "array", "items": { "type": "integer" }, "minItems": 1, "maxItems": 2, "description": "[H, W] canvas for fixed/pad/crop, or [size] for square canvas (pad/crop)." },
372
+ "normalize_mean": { "type": "array", "items": { "type": "number" }, "description": "RGB mean for normalization ([0,1] scale). Default: MMDetection-style." },
373
+ "normalize_std": { "type": "array", "items": { "type": "number" }, "description": "RGB std for normalization ([0,1] scale)." },
374
+ "pad_size_divisor": { "type": "integer", "default": 32, "description": "Pad image to multiple of this (training)." },
375
+ "enable_flip_horizontal": { "type": "boolean", "default": true, "description": "Apply random horizontal flip during training." },
376
+ "enable_flip_vertical": { "type": "boolean", "default": true, "description": "Apply random vertical flip during training." },
377
+ "enable_flip_diagonal": { "type": "boolean", "default": false, "description": "Apply random diagonal flip (MMRotate RRandomFlip direction=diagonal). With H+V+D enabled, each flip has 25% probability and 25% no flip." }
378
+ }
379
+ },
380
+ "augmentation": {
381
+ "type": "object",
382
+ "description": "Albumentations (non-geometric). Keys: limits first, then p_* (probabilities). Only used when enable_albumentation is true.",
383
+ "patternProperties": {
384
+ "^_muted_": true
385
+ },
386
+ "additionalProperties": false,
387
+ "properties": {
388
+ "brightness_limit": { "type": "number", "default": 0.2, "description": "Range for brightness/contrast shift (Albumentations)." },
389
+ "contrast_limit": { "type": "number", "default": 0.2, "description": "Range for contrast shift (Albumentations)." },
390
+ "gamma_limit": { "type": "array", "items": { "type": "integer" }, "minItems": 2, "maxItems": 2, "description": "[min, max] gamma for gamma transform." },
391
+ "gauss_noise_var_limit": { "type": "array", "items": { "type": "number" }, "minItems": 2, "maxItems": 2, "description": "[min, max] variance for Gaussian noise." },
392
+ "blur_limit": { "type": "integer", "default": 3, "description": "Max kernel size for blur." },
393
+ "clahe_clip_limit": { "type": "number", "default": 4.0, "description": "CLAHE clip limit." },
394
+ "p_brightness_contrast": { "type": "number", "default": 0.5, "description": "Probability of brightness/contrast transform." },
395
+ "p_gamma": { "type": "number", "default": 0.3, "description": "Probability of gamma transform." },
396
+ "p_noise": { "type": "number", "default": 0.2, "description": "Probability of Gaussian noise." },
397
+ "p_blur": { "type": "number", "default": 0.2, "description": "Probability of blur." },
398
+ "p_clahe": { "type": "number", "default": 0.3, "description": "Probability of CLAHE." }
399
+ }
400
+ },
401
+ "enable_albumentation": { "type": "boolean", "default": false, "description": "Enable Albumentations (non-geometric) augmentation pipeline." },
402
+ "enable_profiling": { "type": "boolean", "default": false, "description": "Enable training step profiler (TensorBoard trace)." }
403
+ }
404
+ }
@@ -0,0 +1,121 @@
1
+ {
2
+ "_base_": [
3
+ "../_base_/datasets/dota_le90.json",
4
+ "../_base_/models/oriented_rcnn_r50.json",
5
+ "../_base_/schedules/1x.json",
6
+ "../_base_/preprocessing.json"
7
+ ],
8
+ "enable_albumentation": false,
9
+ "data_loader": {
10
+ "batch_size": 2,
11
+ "num_workers": 4,
12
+ "shuffle": true,
13
+ "pin_memory": true
14
+ },
15
+ "checkpoint": {
16
+ "load_from_checkpoint": null,
17
+ "load_from_experiment": null,
18
+ "discover_previous_run": false,
19
+ "resume_from_checkpoint_epoch": false,
20
+ "load_optimizer_state": false,
21
+ "load_scheduler_state": false,
22
+ "start_epoch": 0,
23
+ "best_metric": "mAP",
24
+ "higher_is_better": true
25
+ },
26
+ "training": {
27
+ "num_epochs": 12,
28
+ "learning_rate": 0.005,
29
+ "momentum": 0.9,
30
+ "weight_decay": 0.0001,
31
+ "use_amp": false,
32
+ "gradient_accumulation_steps": 1,
33
+ "max_grad_norm": 35.0,
34
+ "lr_scheduler_milestones": [8, 11],
35
+ "lr_scheduler_gamma": 0.1,
36
+ "lr_warmup_steps": 500,
37
+ "lr_scaling_with_accumulation": "linear",
38
+ "lr_scale_with_world_size": false,
39
+ "use_lr_param_groups": false
40
+ },
41
+ "loss": {
42
+ "loss_type": "cross_entropy",
43
+ "label_smoothing": 0.0
44
+ },
45
+ "dataset": {
46
+ "train_tiles_dirs": [
47
+ "/path/to/data/DOTA-v1.0-tiled/train",
48
+ "/path/to/data/DOTA-v1.0-tiled/val"
49
+ ],
50
+ "val_tiles_dirs": [
51
+ "/path/to/data/DOTA-v1.0-tiled/val"
52
+ ],
53
+ "filter_empty_gt": true,
54
+ "overlap": 200,
55
+ "difficult_strategy": "keep",
56
+ "ignore_labels": [
57
+ "container-crane",
58
+ "airport",
59
+ "helipad"
60
+ ]
61
+ },
62
+ "preprocessing": {
63
+ "enable_flip_diagonal": true
64
+ },
65
+ "evaluation": {
66
+ "score_threshold": 0.05,
67
+ "iou_threshold": 0.5,
68
+ "compute_map_final": false,
69
+ "compute_map_every_n_epochs": 4,
70
+ "extended_gt_metrics": true
71
+ },
72
+ "tensorboard": {
73
+ "log_debug_anchors_proposals": true,
74
+ "vis_score_threshold": 0.5
75
+ },
76
+ "model": {
77
+ "pretrained_backbone": true,
78
+ "frozen_stages": 1,
79
+ "inference_pre_nms_score_threshold": 0.05,
80
+ "rpn_pre_nms_top_n": 2000,
81
+ "rpn_post_nms_top_n": 2000,
82
+ "rpn_min_size": 0,
83
+ "rpn_nms_threshold": 0.8,
84
+ "final_nms_iou_threshold": 0.1,
85
+ "roi_box_reg_angle_weight": 1.0,
86
+ "roi_box_reg_iou_weight": 0.1,
87
+ "roi_box_reg_iou_loss_type": "probiou",
88
+ "roi_box_reg_probiou_mode": "l1",
89
+ "final_nms_use_cpu": true,
90
+ "nms_class_agnostic": false,
91
+ "max_detections_per_image": 100,
92
+ "rpn_positive_iou_threshold": 0.7,
93
+ "rpn_negative_iou_threshold": 0.3,
94
+ "rpn_min_pos_iou": 0.3,
95
+ "rpn_match_low_quality": true,
96
+ "roi_positive_iou_threshold": 0.5,
97
+ "roi_negative_iou_threshold": 0.5,
98
+ "roi_match_low_quality": false,
99
+ "roi_batch_size_per_image": 512,
100
+ "use_hbb_for_matching": true,
101
+ "add_gt_as_proposals": true,
102
+ "roi_proj_xy": true,
103
+ "roi_edge_swap": true,
104
+ "roi_norm_factor": null,
105
+ "roi_inference_top_class_only": true
106
+ },
107
+ "production": {
108
+ "score_threshold": 0.05,
109
+ "inference_pre_nms_score_threshold": 0.05,
110
+ "final_nms_iou_threshold": 0.5,
111
+ "rpn_pre_nms_top_n": 6000,
112
+ "rpn_post_nms_top_n": 6000,
113
+ "max_detections_per_image": 3000,
114
+ "roi_inference_top_class_only": true,
115
+ "overlap_pixels": 200,
116
+ "ignore_margin_pixels": 0,
117
+ "use_first_image_canvas": false,
118
+ "stick_to_model_canvas": true,
119
+ "final_nms_use_cpu": true
120
+ }
121
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "_base_": [
3
+ "dota_le90_1x.json"
4
+ ],
5
+ "training": {
6
+ "num_epochs": 36,
7
+ "learning_rate": 0.005,
8
+ "lr_scheduler_milestones": [24, 33],
9
+ "lr_scheduler_gamma": 0.1
10
+ }
11
+ }