Suppress duplicate YOLO tile detections
GeoIntel CI / docs-smoke (push) Has been cancelled
GeoIntel CI / contract-smoke (push) Has been cancelled

This commit is contained in:
Codex
2026-07-09 10:55:45 +02:00
parent 638534f011
commit 3f5ca4c85e
24 changed files with 266 additions and 39 deletions
+19 -4
View File
@@ -168,6 +168,7 @@ while IFS=$'\t' read -r model_request tile_size tile_overlap threshold run_label
run_index=$((run_index + 1))
run_log="${QUALITY_OUTPUT_DIR}/${run_label}.log"
quality_response="${QUALITY_OUTPUT_DIR}/${run_label}_quality_checks.json"
detection_run_response="${QUALITY_OUTPUT_DIR}/${run_label}_detection_run.json"
run_summary="${QUALITY_OUTPUT_DIR}/${run_label}_summary.json"
model_env="${model_request}"
if [ "${model_request}" = "__active__" ]; then
@@ -203,9 +204,11 @@ while IFS=$'\t' read -r model_request tile_size tile_overlap threshold run_label
fi
curl -fsS "${BASE_URL%/}/api/v1/projects/${project_id}/quality-checks?limit=200" > "${quality_response}"
curl -fsS "${BASE_URL%/}/api/v1/detection/runs/${analysis_run_id}" > "${detection_run_response}"
"${PYTHON_BIN}" - \
"${quality_response}" \
"${detection_run_response}" \
"${run_summary}" \
"${model_request}" \
"${selected_model_asset_id}" \
@@ -226,6 +229,7 @@ import sys
(
quality_path,
detection_run_path,
output_path,
model_request,
selected_model_asset_id,
@@ -241,12 +245,18 @@ import sys
detection_count,
export_id,
run_log,
) = sys.argv[1:17]
) = sys.argv[1:18]
with open(quality_path, "r", encoding="utf-8") as handle:
payload = json.load(handle)
if "data" not in payload:
raise SystemExit("Quality-check list is not a canonical GeoIntel data envelope")
with open(detection_run_path, "r", encoding="utf-8") as handle:
detection_run_payload = json.load(handle)
if "data" not in detection_run_payload:
raise SystemExit("Detection run detail is not a canonical GeoIntel data envelope")
detection_run = detection_run_payload["data"]
run_result = detection_run.get("result_json") or {}
items = payload["data"].get("items") or []
quality_check = next((item for item in items if str(item.get("id")) == quality_check_id), None)
if quality_check is None:
@@ -270,6 +280,9 @@ summary = {
"analysis_run_id": analysis_run_id,
"quality_check_id": quality_check_id,
"detection_count": int(detection_count),
"raw_detection_count": run_result.get("raw_detection_count", int(detection_count)),
"suppressed_detection_count": run_result.get("suppressed_detection_count", 0),
"duplicate_iou_threshold": run_result.get("duplicate_iou_threshold"),
"quality_status": quality_check.get("status"),
"quality_score": quality_check.get("score"),
"precision": metrics.get("precision"),
@@ -285,13 +298,15 @@ summary = {
with open(output_path, "w", encoding="utf-8") as handle:
json.dump(summary, handle, indent=2, sort_keys=True)
print(
"model={model} tile={tile} overlap={overlap} threshold={threshold} detections={detections} "
"model={model} tile={tile} overlap={overlap} threshold={threshold} detections={detections} raw={raw} suppressed={suppressed} "
"score={score} precision={precision} recall={recall} f1={f1} matches={matches} fp={fp} fn={fn}".format(
model=summary["model_asset_id"],
tile=summary["tile_size"],
overlap=summary["tile_overlap"],
threshold=summary["threshold"],
detections=summary["detection_count"],
raw=summary["raw_detection_count"],
suppressed=summary["suppressed_detection_count"],
score=summary["quality_score"],
precision=summary["precision"],
recall=summary["recall"],
@@ -346,10 +361,10 @@ with open(summary_path, "w", encoding="utf-8") as handle:
print("")
print("Detection quality matrix summary")
print("model\ttile\toverlap\tthreshold\tdetections\tscore\tprecision\trecall\tf1\tmatches\tfp\tfn")
print("model\ttile\toverlap\tthreshold\tdetections\traw\tsuppressed\tscore\tprecision\trecall\tf1\tmatches\tfp\tfn")
for item in items:
print(
"{model_asset_id}\t{tile_size}\t{tile_overlap}\t{threshold:.2f}\t{detection_count}\t{quality_score}\t{precision}\t{recall}\t{f1_score}\t{matches}\t{false_positives}\t{false_negatives}".format(
"{model_asset_id}\t{tile_size}\t{tile_overlap}\t{threshold:.2f}\t{detection_count}\t{raw_detection_count}\t{suppressed_detection_count}\t{quality_score}\t{precision}\t{recall}\t{f1_score}\t{matches}\t{false_positives}\t{false_negatives}".format(
**item
)
)