Spaces:
Sleeping
Sleeping
| """ | |
| Debug script to visualize each preprocessing step for red play clock digits. | |
| """ | |
| from pathlib import Path | |
| import cv2 | |
| import numpy as np | |
| def main(): | |
| # Load the red play clock region (frame 472849, which shows "5") | |
| region_path = Path("output/debug/red_play_clock/frame_472849_region.png") | |
| output_dir = Path("output/debug/red_preprocessing") | |
| output_dir.mkdir(parents=True, exist_ok=True) | |
| # Load the region | |
| region = cv2.imread(str(region_path)) | |
| if region is None: | |
| print(f"Failed to load {region_path}") | |
| return | |
| print(f"Loaded region: {region.shape}") | |
| # Step 1: Split into color channels | |
| b, g, r = cv2.split(region) | |
| cv2.imwrite(str(output_dir / "01_red_channel.png"), r) | |
| cv2.imwrite(str(output_dir / "01_green_channel.png"), g) | |
| cv2.imwrite(str(output_dir / "01_blue_channel.png"), b) | |
| print(f"Red channel - min: {r.min()}, max: {r.max()}, mean: {r.mean():.1f}, std: {r.std():.1f}") | |
| print(f"Green channel - min: {g.min()}, max: {g.max()}, mean: {g.mean():.1f}") | |
| print(f"Blue channel - min: {b.min()}, max: {b.max()}, mean: {b.mean():.1f}") | |
| # Step 2: Use red channel as grayscale | |
| gray = r.copy() | |
| cv2.imwrite(str(output_dir / "02_gray_from_red.png"), gray) | |
| print(f"Gray (red channel) - shape: {gray.shape}") | |
| # Step 3: Scale up by 4x | |
| scale_factor = 4 | |
| scaled = cv2.resize(gray, None, fx=scale_factor, fy=scale_factor, interpolation=cv2.INTER_LINEAR) | |
| cv2.imwrite(str(output_dir / "03_scaled.png"), scaled) | |
| print(f"Scaled - shape: {scaled.shape}, min: {scaled.min()}, max: {scaled.max()}, mean: {scaled.mean():.1f}") | |
| # Step 4: Otsu's thresholding | |
| threshold, binary_otsu = cv2.threshold(scaled, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) | |
| cv2.imwrite(str(output_dir / "04_otsu_binary.png"), binary_otsu) | |
| print(f"Otsu threshold: {threshold}") | |
| print(f"Binary (Otsu) - white pixels: {(binary_otsu == 255).sum()}, black pixels: {(binary_otsu == 0).sum()}") | |
| # Step 4b: Try different fixed thresholds | |
| for thresh_val in [30, 50, 70, 90]: | |
| _, binary_fixed = cv2.threshold(scaled, thresh_val, 255, cv2.THRESH_BINARY) | |
| cv2.imwrite(str(output_dir / f"04_fixed_thresh_{thresh_val}.png"), binary_fixed) | |
| white_pix = (binary_fixed == 255).sum() | |
| black_pix = (binary_fixed == 0).sum() | |
| print(f"Fixed threshold {thresh_val}: white={white_pix}, black={black_pix}") | |
| # Step 5: Check mean intensity and decide on inversion | |
| binary = binary_otsu.copy() | |
| mean_intensity = np.mean(binary) | |
| print(f"Mean intensity after Otsu: {mean_intensity:.1f}") | |
| if mean_intensity < 128: | |
| print("Mean < 128, inverting image") | |
| binary = cv2.bitwise_not(binary) | |
| cv2.imwrite(str(output_dir / "05_after_inversion_check.png"), binary) | |
| # Step 6: Morphological operations | |
| kernel = np.ones((2, 2), np.uint8) | |
| binary = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel) | |
| cv2.imwrite(str(output_dir / "06_after_morph_close.png"), binary) | |
| binary = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel) | |
| cv2.imwrite(str(output_dir / "06_after_morph_open.png"), binary) | |
| # Step 7: Add padding | |
| padding = 10 | |
| binary = cv2.copyMakeBorder(binary, padding, padding, padding, padding, cv2.BORDER_CONSTANT, value=255) | |
| cv2.imwrite(str(output_dir / "07_final_with_padding.png"), binary) | |
| print(f"\nFinal image shape: {binary.shape}") | |
| print(f"Output saved to: {output_dir}") | |
| # Also compare with standard grayscale approach | |
| print("\n--- Comparing with standard grayscale ---") | |
| gray_standard = cv2.cvtColor(region, cv2.COLOR_BGR2GRAY) | |
| cv2.imwrite(str(output_dir / "compare_standard_gray.png"), gray_standard) | |
| print(f"Standard grayscale - min: {gray_standard.min()}, max: {gray_standard.max()}, mean: {gray_standard.mean():.1f}") | |
| scaled_standard = cv2.resize(gray_standard, None, fx=scale_factor, fy=scale_factor, interpolation=cv2.INTER_LINEAR) | |
| threshold_std, binary_standard = cv2.threshold(scaled_standard, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) | |
| cv2.imwrite(str(output_dir / "compare_standard_otsu.png"), binary_standard) | |
| print(f"Standard grayscale Otsu threshold: {threshold_std}") | |
| if __name__ == "__main__": | |
| main() | |