#!/usr/bin/env python3 """Redraw every dumped crop with its detection box marked. The original thumbnails padded by 0.5x the face on each side for recognisability, which in a crowded frame pulls a neighbour into shot — often more prominently than the subject. A label cannot be corrected from a picture that does not say which face it refers to. This rewrites each .jpg IN PLACE, wherever it currently sits, so any sorting already done is preserved: only the pixels change, never the filename or the folder. Re-run it after dump_faces.py, and re-check any sorting done before it. """ import glob, json, os, sys import cv2 CLIPS = ["5157339", "5157344"] OUT = 256 for clip in CLIPS: man = {m["file"]: m for m in json.load(open(f"labelling/{clip}/manifest.json"))} n = 0 for path in glob.glob(f"labelling/{clip}/**/*.jpg", recursive=True): fname = os.path.basename(path) m = man.get(fname) if m is None: continue img = cv2.imread(f"frames/d{clip}_{m['frame']}.png") if img is None: sys.exit(f"missing frames/d{clip}_{m['frame']}.png") x, y, w, h = (int(v) for v in m["bbox"]) pad = int(0.55 * max(w, h)) x0, y0 = max(0, x - pad), max(0, y - pad) x1, y1 = min(img.shape[1], x + w + pad), min(img.shape[0], y + h + pad) sub = img[y0:y1, x0:x1].copy() # Box in the sub-image's coordinates, drawn before the resize so the # line lands exactly on the face at any output size. cv2.rectangle(sub, (x - x0, y - y0), (x - x0 + w, y - y0 + h), (0, 0, 255), 3) # Dim everything outside the box so the subject is unmistakable even # when a neighbour's face is larger or better lit. mask = sub.copy() mask[y - y0:y - y0 + h, x - x0:x - x0 + w] = 0 sub = cv2.addWeighted(sub, 1.0, mask, -0.35, 0) scale = OUT / max(sub.shape[:2]) sub = cv2.resize(sub, (int(sub.shape[1] * scale), int(sub.shape[0] * scale))) canvas = cv2.copyMakeBorder( sub, 0, max(0, OUT - sub.shape[0]), 0, max(0, OUT - sub.shape[1]), cv2.BORDER_CONSTANT, value=(20, 20, 20))[:OUT, :OUT] cv2.putText(canvas, f"{int(m['px'])}px", (5, OUT - 8), cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 255, 255), 1) cv2.imwrite(path, canvas) n += 1 print(f"[{clip}] redrew {n} crops in place", file=sys.stderr)