Audit and suppress nested detector proposals

This commit is contained in:
Jens
2026-07-27 09:58:25 +02:00
parent efd3272bda
commit 51db5baa9c
6 changed files with 264 additions and 4 deletions
+17 -3
View File
@@ -31,15 +31,27 @@ def read_boxes(path: Path, width: int, height: int) -> list[tuple[float, float,
return boxes
def tile_starts(length: int, tile_size: int, overlap: int) -> list[int]:
if length < tile_size:
return []
stride = tile_size - overlap
starts = list(range(0, length - tile_size + 1, stride))
final = length - tile_size
if starts[-1] != final:
starts.append(final)
return starts
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--summary", type=Path, required=True)
parser.add_argument("--output-dir", type=Path, required=True)
parser.add_argument("--tile-size", type=int, default=320)
parser.add_argument("--overlap", type=int, default=0)
parser.add_argument("--min-visible-ratio", type=float, default=0.25)
parser.add_argument("--force", action="store_true")
args = parser.parse_args()
if args.tile_size < 32 or not 0 <= args.min_visible_ratio <= 1:
if args.tile_size < 32 or not 0 <= args.overlap < args.tile_size or not 0 <= args.min_visible_ratio <= 1:
raise SystemExit("invalid tile size or visible ratio")
if args.output_dir.exists():
if not args.force:
@@ -56,8 +68,8 @@ def main() -> int:
source = opened.convert("RGB")
width, height = source.size
boxes = read_boxes(Path(source_tile["label_path"]), width, height)
for top in range(0, height, args.tile_size):
for left in range(0, width, args.tile_size):
for top in tile_starts(height, args.tile_size, args.overlap):
for left in tile_starts(width, args.tile_size, args.overlap):
right, bottom = min(width, left+args.tile_size), min(height, top+args.tile_size)
if right-left < args.tile_size or bottom-top < args.tile_size:
continue
@@ -95,6 +107,7 @@ def main() -> int:
output_summary = dict(summary)
output_summary.update({"output_dir":str(args.output_dir), "dataset_yaml":str(args.output_dir/"dataset.yaml"),
"tiles":output_tiles, "retile_size":args.tile_size,
"retile_overlap":args.overlap,
"retile_min_visible_ratio":args.min_visible_ratio})
summary_path = args.output_dir / "yolo_tile_dataset_summary.json"
summary_path.write_text(json.dumps(output_summary, indent=2), encoding="utf-8")
@@ -102,6 +115,7 @@ def main() -> int:
f"path: {args.output_dir}\ntrain: images/train\nval: images/val\nnames:\n 0: building\n", encoding="utf-8")
evidence = {"schema_version":1, "status":"ok", "source_summary":str(args.summary),
"source_summary_sha256":sha256(args.summary), "tile_size":args.tile_size,
"overlap":args.overlap,
"min_visible_ratio":args.min_visible_ratio, "output_tile_count":len(output_tiles),
"kept_label_count":kept_labels, "dropped_label_count":dropped_labels,
"summary":str(summary_path), "summary_sha256":sha256(summary_path)}