"""Debug overlay: what detection proposed, drawn on the page. The fastest way to judge a detection change, and the tool for working out why song #40 came out wrong. Kept after release for that reason. """ from __future__ import annotations from pathlib import Path import cv2 import numpy as np from .detect import PageDetection _SYSTEM = (0, 160, 0) _CUT = (0, 0, 255) _PROFILE = (220, 120, 0) _PREVIEW_WIDTH = 1100 def draw(gray: np.ndarray, detection: PageDetection) -> np.ndarray: """Straightened page with systems boxed, cuts lined, row profile down the side.""" from .detect import deskew, row_darkness straight = deskew(gray, detection.skew) vis = cv2.cvtColor(straight, cv2.COLOR_GRAY2BGR) h, w = straight.shape thickness = max(1, w // 700) profile = row_darkness(straight) if profile.max() > 0: scaled = (profile / profile.max() * (w * 0.08)).astype(int) for y in range(0, h, max(1, h // 900)): cv2.line(vis, (0, y), (int(scaled[y]), y), _PROFILE, 1) for i, system in enumerate(detection.systems): cv2.rectangle(vis, (2, system.top), (w - 3, system.bottom), _SYSTEM, thickness) label = f"{i + 1}" if system.staff_height: label += f" staff {system.staff_height:.0f}px" cv2.putText(vis, label, (int(w * 0.10), system.top + int(h * 0.02)), cv2.FONT_HERSHEY_SIMPLEX, w / 1400, _SYSTEM, thickness) for y in detection.cuts: cv2.line(vis, (0, y), (w, y), _CUT, thickness) return vis def write(gray: np.ndarray, detection: PageDetection, path: Path) -> Path: vis = draw(gray, detection) height = int(vis.shape[0] * _PREVIEW_WIDTH / vis.shape[1]) cv2.imwrite(str(path), cv2.resize(vis, (_PREVIEW_WIDTH, height), interpolation=cv2.INTER_AREA)) return path