Report blank YOLO label QA tiles
GeoIntel CI / docs-smoke (push) Has been cancelled
GeoIntel CI / contract-smoke (push) Has been cancelled

This commit is contained in:
Codex
2026-07-11 22:05:13 +02:00
parent fbccf8322e
commit 5688feec35
5 changed files with 70 additions and 16 deletions
@@ -31,6 +31,12 @@ def parse_args() -> argparse.Namespace:
parser.add_argument("--max-tiles", type=int, default=24, help="Maximum selected tiles to render")
parser.add_argument("--columns", type=int, default=4, help="Contact-sheet columns")
parser.add_argument("--thumb-size", type=int, default=256, help="Rendered tile thumbnail size in pixels")
parser.add_argument(
"--blank-range-threshold",
type=int,
default=3,
help="Mark rendered images with grayscale max-min range at or below this value as low variance.",
)
return parser.parse_args()
@@ -146,6 +152,7 @@ def draw_tile_card(
thumb_size: int,
invalid_label_count: int,
missing_label_file: bool,
low_visual_variance: bool,
) -> Image.Image:
header_height = 44
card = Image.new("RGB", (thumb_size, thumb_size + header_height), color=(245, 247, 250))
@@ -163,6 +170,8 @@ def draw_tile_card(
subtitle_parts.append("missing-label-file")
if invalid_label_count:
subtitle_parts.append(f"invalid:{invalid_label_count}")
if low_visual_variance:
subtitle_parts.append("low-variance")
draw.text((6, 6), title[:44], fill=(255, 255, 255), font=font)
draw.text((6, 24), " | ".join(subtitle_parts)[:52], fill=(191, 219, 254), font=font)
@@ -180,6 +189,12 @@ def draw_tile_card(
return card
def image_has_low_visual_variance(image_path: Path, blank_range_threshold: int) -> bool:
image = Image.open(image_path).convert("L")
min_value, max_value = image.getextrema()
return (max_value - min_value) <= blank_range_threshold
def build_contact_sheet(cards: list[Image.Image], columns: int, output_path: Path) -> None:
if not cards:
return
@@ -216,6 +231,7 @@ def build_report(summary: dict[str, Any], summary_path: Path, args: argparse.Nam
missing_label_file_count = 0
invalid_label_count = 0
valid_label_count = 0
low_visual_variance_tile_count = 0
for tile in selected_tiles:
image_path = resolve_path(tile.get("image_path"), summary_path)
@@ -227,9 +243,13 @@ def build_report(summary: dict[str, Any], summary_path: Path, args: argparse.Nam
missing_label_file_count += 1
rendered = False
low_visual_variance = False
if image_path is None or not image_path.exists():
missing_image_count += 1
else:
low_visual_variance = image_has_low_visual_variance(image_path, args.blank_range_threshold)
if low_visual_variance:
low_visual_variance_tile_count += 1
rendered_cards.append(
draw_tile_card(
image_path=image_path,
@@ -238,6 +258,7 @@ def build_report(summary: dict[str, Any], summary_path: Path, args: argparse.Nam
thumb_size=args.thumb_size,
invalid_label_count=tile_invalid_count,
missing_label_file=missing_label_file,
low_visual_variance=low_visual_variance,
)
)
rendered = True
@@ -255,6 +276,7 @@ def build_report(summary: dict[str, Any], summary_path: Path, args: argparse.Nam
"valid_label_count": len(boxes),
"invalid_label_count": tile_invalid_count,
"missing_label_file": missing_label_file,
"low_visual_variance": low_visual_variance,
"rendered": rendered,
}
)
@@ -285,6 +307,8 @@ def build_report(summary: dict[str, Any], summary_path: Path, args: argparse.Nam
"missing_label_file_count": missing_label_file_count,
"invalid_label_count": invalid_label_count,
"valid_label_count": valid_label_count,
"low_visual_variance_tile_count": low_visual_variance_tile_count,
"blank_range_threshold": args.blank_range_threshold,
"contact_sheets": contact_sheets,
"selected_tiles": selected_report_tiles,
},
@@ -302,6 +326,7 @@ def write_markdown(report: dict[str, Any], output_dir: Path) -> None:
f"- missing images: {report['missing_image_count']}",
f"- missing label files: {report['missing_label_file_count']}",
f"- invalid label rows: {report['invalid_label_count']}",
f"- low-variance rendered tiles: {report['low_visual_variance_tile_count']}",
f"- valid labels rendered: {report['valid_label_count']}",
"",
"## Contact Sheets",
@@ -323,6 +348,8 @@ def write_markdown(report: dict[str, Any], output_dir: Path) -> None:
flags.append("missing-label-file")
if tile["invalid_label_count"]:
flags.append(f"invalid:{tile['invalid_label_count']}")
if tile["low_visual_variance"]:
flags.append("low-variance")
flag_text = ", ".join(flags) if flags else "ok"
lines.append(
"- "