Suppress duplicate YOLO tile detections
This commit is contained in:
@@ -110,6 +110,7 @@ Environment variables:
|
||||
- `YOLO_IMAGE_SIZE`
|
||||
- `YOLO_MAX_TILES`
|
||||
- `YOLO_MAX_DETECTIONS`
|
||||
- `YOLO_DUPLICATE_IOU_THRESHOLD`
|
||||
- `YOLO_BATCH_SIZE`
|
||||
|
||||
`YOLO_MAX_DETECTIONS` is forwarded to Ultralytics as `max_det` for each
|
||||
@@ -119,6 +120,15 @@ the upstream default would cap recall before QA/QC begins. Operators may lower
|
||||
the value for small rasters or raise it for dense urban tiles after reviewing
|
||||
runtime and false-positive behavior.
|
||||
|
||||
After YOLO boxes are georeferenced, configured-YOLO runs apply a GeoIntel
|
||||
cross-tile duplicate suppression pass before persistence. Candidates are grouped
|
||||
by canonical class and sorted by confidence; lower-confidence same-class
|
||||
candidates with EPSG:4326 geometry IoU greater than or equal to
|
||||
`YOLO_DUPLICATE_IOU_THRESHOLD` are suppressed. The default is `0.5`; set it to
|
||||
`0` to disable this post-processing for operator debugging. Run summaries record
|
||||
raw, persisted and suppressed detection counts so calibration evidence remains
|
||||
auditable.
|
||||
|
||||
### Local model asset catalog
|
||||
|
||||
GeoIntel can list local runtime model files mounted into the backend model
|
||||
@@ -205,6 +215,9 @@ persisted project quality-check list to build `calibration_summary.json`.
|
||||
Results are honest QA/QC evidence from persisted detections and persisted
|
||||
reference `vector_features`; no demo detections, live provider fetches or model
|
||||
downloads are introduced by the calibration tool.
|
||||
Summaries include raw detection candidate count, persisted detection count and
|
||||
suppressed duplicate count so operators can distinguish model output volume from
|
||||
GeoIntel post-processing.
|
||||
|
||||
For model/tile/threshold selection, use the quality matrix wrapper:
|
||||
|
||||
|
||||
@@ -785,6 +785,12 @@ Validation errors:
|
||||
- Configured YOLO inference forwards `YOLO_MAX_DETECTIONS` to Ultralytics
|
||||
`max_det` and defaults to `1000` so dense building AOIs are not silently
|
||||
limited by the upstream default of 300 detections before persisted QA/QC.
|
||||
- Configured YOLO applies cross-tile duplicate suppression after pixel boxes are
|
||||
converted to EPSG:4326 geometries and before `Detection` rows are persisted.
|
||||
Same-class candidates are confidence-sorted and lower-confidence candidates
|
||||
with geometry IoU greater than or equal to
|
||||
`YOLO_DUPLICATE_IOU_THRESHOLD` are suppressed. The default is `0.5`; `0`
|
||||
disables this GeoIntel-side post-processing for debugging.
|
||||
- `DETECTION_DEPENDENCY_UNAVAILABLE` when YOLO dependencies are not installed.
|
||||
- `DETECTION_MODEL_LOAD_FAILED` when the local model file exists but cannot be loaded.
|
||||
|
||||
|
||||
@@ -1,3 +1,35 @@
|
||||
## Sprint 149 YOLO duplicate suppression evidence (2026-07-09)
|
||||
|
||||
Changed:
|
||||
- Added configured-YOLO cross-tile duplicate suppression after pixel boxes are converted to EPSG:4326 geometries and before `Detection` rows are persisted.
|
||||
- Added backend setting `YOLO_DUPLICATE_IOU_THRESHOLD` with default `0.5`; `0` disables the GeoIntel-side pass for debugging.
|
||||
- Detection run `result_json` now records:
|
||||
- `raw_detection_count`
|
||||
- `suppressed_detection_count`
|
||||
- `duplicate_iou_threshold`
|
||||
- Updated `.env.example`, Docker Compose, Unraid env examples and the Dockerman run script.
|
||||
- Updated calibration and quality matrix scripts to fetch detection run details and include raw/suppressed counts in per-run and aggregate summaries.
|
||||
- Updated backend/API/AI/pipeline documentation.
|
||||
|
||||
Why:
|
||||
- Dense overlapping tile inference can produce duplicate candidate buildings, which inflates persisted false positives before QA/QC.
|
||||
- The previous Sprint 148 cap fix allowed dense AOIs to persist more candidates, but made duplicate pressure more visible.
|
||||
- This pass keeps all outputs honest: no model activation, no fake detections and no migration. It only removes lower-confidence same-class geometric duplicates before persistence.
|
||||
|
||||
Tested:
|
||||
- Red step: `python -m pytest backend\tests\test_sprint8b_yolo_foundation.py::test_yolo_run_suppresses_cross_tile_duplicate_detections -q` failed with `detection_count == 2`.
|
||||
- `python -m pytest backend\tests\test_sprint8b_yolo_foundation.py::test_yolo_run_suppresses_cross_tile_duplicate_detections -q` (`1 passed`)
|
||||
- Red step: Docker runtime config tests failed before `.env.example` and Unraid runner exposed `YOLO_DUPLICATE_IOU_THRESHOLD`.
|
||||
- `python -m pytest backend\tests\test_sprint8b_yolo_foundation.py backend\tests\test_docker_runtime_config.py::test_env_example_uses_runtime_env_names_read_by_backend_and_frontend backend\tests\test_docker_runtime_config.py::test_unraid_deploy_passes_ai_build_arg_and_yolo_runtime_env -q` (`17 passed`)
|
||||
- Red step: calibration/matrix script tests failed before detection-run raw/suppressed metadata was included.
|
||||
- `python -m pytest backend\tests\test_sprint124_detection_calibration_sweep.py backend\tests\test_sprint126_detection_quality_matrix.py backend\tests\test_sprint127_operator_sample_quality_matrix.py::test_multi_sample_detection_quality_matrix_runs_existing_matrix_for_each_sample -q` (`3 passed`)
|
||||
- `bash -n scripts/run_detection_calibration_sweep.sh`
|
||||
- `bash -n scripts/run_detection_quality_matrix.sh`
|
||||
- `bash -n scripts/run_multi_sample_detection_quality_matrix.sh`
|
||||
|
||||
Next:
|
||||
- Run full readiness, then deploy Tower and rerun the dense Westerlo/Turnhout sweeps with duplicate suppression enabled to quantify quality impact versus the Sprint 148 uncapped baseline.
|
||||
|
||||
## Sprint 148 YOLO max-detection cap hardening (2026-07-09)
|
||||
|
||||
Changed:
|
||||
|
||||
@@ -110,6 +110,9 @@ Default method:
|
||||
- calculate IoU between overlapping geospatial bboxes
|
||||
- apply non-maximum suppression by confidence
|
||||
- default IoU merge threshold: 0.5
|
||||
- implemented for configured-YOLO as EPSG:4326 cross-tile duplicate suppression
|
||||
before `Detection` persistence; `YOLO_DUPLICATE_IOU_THRESHOLD=0` disables the
|
||||
GeoIntel-side pass for debugging.
|
||||
|
||||
## Step 6 — Storage
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ YOLO_MODEL_PATH=
|
||||
YOLO_MODEL_VERSION=
|
||||
YOLO_MAX_TILES=100
|
||||
YOLO_MAX_DETECTIONS=1000
|
||||
YOLO_DUPLICATE_IOU_THRESHOLD=0.5
|
||||
ENABLE_GRB_WFS=false
|
||||
GRB_WFS_URL=
|
||||
OSM_OVERPASS_URL=https://overpass-api.de/api/interpreter
|
||||
|
||||
+2
-1
@@ -112,10 +112,11 @@ This file now starts with the current implementation status. Older preparation/b
|
||||
- [x] Train and gate an AOI-scale `aoi512e80` YOLOv8s candidate to test the 160px training-scale hypothesis.
|
||||
- [x] Raise configured-YOLO `max_det` through `YOLO_MAX_DETECTIONS` so dense AOIs are not capped at 300 detections before QA/QC.
|
||||
- [x] Rerun live dense-AOI calibration after redeploy with `YOLO_MAX_DETECTIONS=1000`; Westerlo reached 523/1000 detections at lower thresholds and Turnhout reached 822/1000, confirming the old 300 cap is removed.
|
||||
- [x] Add configured-YOLO cross-tile duplicate suppression and raw/suppressed calibration evidence fields.
|
||||
- [ ] Find or train a materially stronger aerial/Kempen building model candidate; `geointel-building-yolov8n-expanded160e50-pt` is the best current dense-AOI candidate but still too weak and too noisy for a V1 default.
|
||||
- [ ] Train a higher-capacity local aerial-building detector with stronger positive recall while preserving the hard-negative false-positive gate.
|
||||
- [ ] Add more diverse positive AOIs and revisit geometry-to-box label strategy before the next default-model training attempt.
|
||||
- [ ] Add operator-side duplicate suppression/post-processing analysis for dense overlapping tile detections before the next promotion gate.
|
||||
- [ ] Rerun live dense-AOI calibration after redeploy with `YOLO_DUPLICATE_IOU_THRESHOLD=0.5` to measure post-processing impact versus the Sprint 148 uncapped baseline.
|
||||
|
||||
## Sprint 8 status
|
||||
|
||||
|
||||
Reference in New Issue
Block a user