Spaces:
Sleeping
Sleeping
File size: 4,262 Bytes
d51bea3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | """
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()
|