"""Quality control image analysis utility. Analyzes the available qc-d06 PNG frames in the recheck directory and produces structured output for visual defect review. """ from PIL import Image import numpy as np import json import os RECECK_DIR = '/root/qc-recheck' MP4_DIR = '/root/qc-recheck/mp4' def load_image(path): """Load image as int RGB array.""" return np.array(Image.open(path).convert('RGB')).astype(int) def sample_color(img, y, x): """Sample color at coordinates.""" return (int(img[y, x, 0]), int(img[y, x, 1]), int(img[y, x, 2])) def find_rects(img, color_range, threshold=50): """Find contiguous regions matching color criteria.""" r, g, b = color_range mask = (np.abs(img[:,:,0].astype(float) - r) < threshold) & \ (np.abs(img[:,:,1].astype(float) - g) < threshold) & \ (np.abs(img[:,:,2].astype(float) - b) < threshold) rows, cols = np.where(mask) if len(rows) == 0: return None return { 'x_min': int(cols.min()), 'x_max': int(cols.max()), 'y_min': int(rows.min()), 'y_max': int(rows.max()), 'count': int(mask.sum()) } def main(): results = { 'images': [], 'summary': {'total_images': 0, 'scanned': False} } # List available PNG files mp4_files = [f for f in os.listdir(MP4_DIR) if f.endswith('.png')] results['summary']['total_images'] = len(mp4_files) print("QC Image Analysis Report") print("=" * 50) print(f"Source directory: {MP4_DIR}") print(f"Images found: {len(mp4_files)}") print() for f in sorted(mp4_files): path = os.path.join(MP4_DIR, f) try: img = load_image(path) H, W, _ = img.shape # Sample key colors bg = sample_color(img, 300, 60) # Page background white_area = img[386:412, 130:780] # Count near-white pixels (250,255,250 like in original QC) white = (img[:,:,0] > 235) & (img[:,:,1] > 235) & (img[:,:,2] > 235) white_count = int(white.sum()) print(f"File: {f}") print(f" Dimensions: {W}x{H}") print(f" Page background: RGB {bg}") print(f" Near-white pixels: {white_count}") print() results['images'].append({ 'filename': f, 'dimensions': [W, H], 'background': bg, 'white_pixel_count': white_count }) except Exception as e: print(f"Error loading {f}: {e}") results['summary']['scanned'] = True # Write JSON output out_path = '/root/.hermes/wizard-outputs/spark/qc_analysis_results.json' with open(out_path, 'w') as fp: json.dump(results, fp, indent=2) print(f"Results written to: {out_path}") return results if __name__ == '__main__': main()