Spaces:
Running
Running
File size: 3,501 Bytes
d70361b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | """Re-run detection on a saved report pair and rewrite regions_json.
Used to repair reports that lost regions to the aggressive Other filter.
Example:
python scripts/repair_run_regions.py --run-id 47
"""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
from PIL import Image
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT))
def main() -> int:
ap = argparse.ArgumentParser()
ap.add_argument("--run-id", type=int, required=True)
args = ap.parse_args()
from dotenv import load_dotenv
load_dotenv(ROOT / ".env", override=True)
from app.database import SessionLocal, DATA_DIR
from app.models import DetectionRun
from app.detection_engine import run_detection
from app.dda.detect_service import _serialize_regions, _filter_weak_other_regions
from app.dda.geo_regions import enrich_regions_geo
from app.dda.change_type_map import enrich_region_for_dda
db = SessionLocal()
try:
run = db.query(DetectionRun).filter(DetectionRun.id == args.run_id).first()
if not run:
print(f"Run {args.run_id} not found")
return 1
before_p = DATA_DIR / run.before_full_path
after_p = DATA_DIR / run.after_full_path
if not before_p.is_file() or not after_p.is_file():
print("Missing before/after overlay PNGs for this run")
return 1
before = Image.open(before_p).convert("RGB")
after = Image.open(after_p).convert("RGB")
print(f"Re-detecting run {run.id} at {before.size} ...")
def _prog(pct, stage):
print(f" [{pct:3d}%] {stage}", flush=True)
mask, vis, stats, regions = run_detection(
before, after,
method=run.method or "AI-Based Deep Learning",
enable_registration=False,
enable_normalization=True,
detection_sensitivity=0.5,
max_size=max(before.size),
on_progress=_prog,
)
print(f" engine regions={len(regions)} change%={stats.get('change_percentage')}")
serial = _serialize_regions(regions)
serial = [enrich_region_for_dda(r) for r in serial]
before_n = len(serial)
serial = _filter_weak_other_regions(serial)
print(f" after Other filter: {before_n} -> {len(serial)}")
w = int(stats.get("image_width") or before.size[0])
h = int(stats.get("image_height") or before.size[1])
serial = enrich_regions_geo(serial, img_width=w, img_height=h, bounds=None, geo=None)
# Refresh overlay image too so boxes match regions
out_overlay = DATA_DIR / run.overlay_path
Image.fromarray(vis).save(out_overlay)
run.regions_json = json.dumps(serial)
run.regions_count = len(serial)
run.change_percentage = float(stats.get("change_percentage") or run.change_percentage)
run.changed_pixels = int(stats.get("changed_pixels") or run.changed_pixels)
run.total_pixels = int(stats.get("total_pixels") or run.total_pixels)
db.commit()
print(f"Updated run {run.id}: regions_count={run.regions_count}")
for r in serial[:20]:
print(
f" #{r.get('id')} {r.get('ddaChangeType')} "
f"conf={float(r.get('confidence') or 0):.2f} area={r.get('area')}"
)
return 0
finally:
db.close()
if __name__ == "__main__":
raise SystemExit(main())
|