Spaces:
Sleeping
Sleeping
Download legacy/b2.py from ansarzeinulla/9OCR: direct link, hf CLI and curl.
- Browser
- Download file 4.13 kB
-
https://huggingface.co/spaces/ansarzeinulla/9OCR/resolve/1b69166ff3b566e4c64f3a39f6730abc742e6bf4/legacy/b2.py
- Command line
-
hf download hf://spaces/ansarzeinulla/9OCR@1b69166ff3b566e4c64f3a39f6730abc742e6bf4/legacy/b2.py
-
curl -L -o b2.py https://huggingface.co/spaces/ansarzeinulla/9OCR/resolve/1b69166ff3b566e4c64f3a39f6730abc742e6bf4/legacy/b2.py
4.13 kB
| import os | |
| import random | |
| import glob | |
| import numpy as np | |
| from PIL import Image, ImageOps, ImageFilter | |
| import cv2 | |
| # --- CONFIGURATION --- | |
| INGREDIENTS_PATH = "ingredients" | |
| OUTPUT_PATH = "train_data2" | |
| BOX_HEIGHT = 40 | |
| BOX_WIDTH = 120 # 3:1 Proportion | |
| SAMPLES_PER_CLASS = 300 # Adjust based on your disk space | |
| # 1. Generate the 163 Class Names | |
| move_classes = [] | |
| for start_hole in range(1, 10): | |
| for end_hole in range(1, 10): | |
| move_classes.append(f"{start_hole}{end_hole}") # e.g., "72" | |
| move_classes.append(f"{start_hole}{end_hole}x") # e.g., "72x" | |
| classes = move_classes + ['empty'] | |
| os.makedirs(OUTPUT_PATH, exist_ok=True) | |
| def get_random_ingredient(char): | |
| files = glob.glob(os.path.join(INGREDIENTS_PATH, char, "*.png")) | |
| if not files: | |
| raise ValueError(f"No images found for character: {char}") | |
| return Image.open(random.choice(files)) | |
| def create_move_image(class_name): | |
| # 1. Create a pure, solid white paper background (255) | |
| # This matches the clean white background of the post-processed real photos | |
| img = Image.new('L', (BOX_WIDTH, BOX_HEIGHT), color=255) | |
| if class_name == 'empty': | |
| return img | |
| chars_to_draw = list(class_name) | |
| prepared_chars = [] | |
| total_width = 0 | |
| gaps = [] | |
| # --- STEP 1: PREPARE AND MEASURE ALL CHARACTERS --- | |
| for i, char in enumerate(chars_to_draw): | |
| char_img = get_random_ingredient(char) | |
| # Make 'x' slightly smaller than numbers | |
| if char == 'x': | |
| size = random.randint(20, 26) | |
| else: | |
| size = random.randint(28, 36) | |
| char_img = char_img.resize((size, size), Image.Resampling.LANCZOS) | |
| char_img = char_img.rotate(random.randint(-10, 10), expand=False, fillcolor=0) | |
| # Crop the black space around the EMNIST digit | |
| bbox = char_img.getbbox() | |
| if bbox: | |
| char_img = char_img.crop(bbox) | |
| prepared_chars.append(char_img) | |
| total_width += char_img.width | |
| # Calculate random gap | |
| if i < len(chars_to_draw) - 1: | |
| gap = random.randint(-2, 5) | |
| gaps.append(gap) | |
| total_width += gap | |
| # --- STEP 2: RANDOM TRANSLATION --- | |
| max_start_x = BOX_WIDTH - total_width | |
| if max_start_x <= 2: | |
| start_x = 2 | |
| else: | |
| start_x = random.randint(2, max_start_x - 2) | |
| # --- STEP 3: PASTE THE CHARACTERS (Using Solid Black Ink) --- | |
| current_x = start_x | |
| for i, char_img in enumerate(prepared_chars): | |
| # We use solid pure black ink (0) to match post-threshold images | |
| ink_layer = Image.new('L', char_img.size, color=0) | |
| max_y = BOX_HEIGHT - char_img.height | |
| paste_y = random.randint(2, max(2, max_y - 2)) | |
| img.paste(ink_layer, (current_x, paste_y), mask=char_img) | |
| if i < len(gaps): | |
| current_x += char_img.width + gaps[i] | |
| # --- STEP 4: DILATION ALIGNMENT --- | |
| # Convert to numpy array for OpenCV | |
| arr = np.array(img) | |
| # Invert the image so the ink is white (required for dilation) | |
| ink_is_white = cv2.bitwise_not(arr) | |
| # Apply a 3x3 dilation kernel to thicken the strokes | |
| # This matches the dilated thickness of the real-world processed pen strokes! | |
| kernel = np.ones((3,3), np.uint8) | |
| thick_ink = cv2.dilate(ink_is_white, kernel, iterations=1) | |
| # Invert back: Ink is Black (0), Background is Pure White (255) | |
| final_img = cv2.bitwise_not(thick_ink) | |
| return Image.fromarray(final_img) | |
| # --- EXECUTION --- | |
| print(f"Generating {len(classes)} classes with Dynamic Spacing...") | |
| for cls in classes: | |
| class_dir = os.path.join(OUTPUT_PATH, cls) | |
| os.makedirs(class_dir, exist_ok=True) | |
| for i in range(SAMPLES_PER_CLASS): | |
| box_img = create_move_image(cls) | |
| box_img.save(os.path.join(class_dir, f"{cls}_{i}.png")) | |
| # Optional print to track progress | |
| if (classes.index(cls) + 1) % 10 == 0: | |
| print(f"Generated {classes.index(cls) + 1}/{len(classes)} classes...") | |
| print(f"\nSuccess! Generated {len(classes)} folders in {OUTPUT_PATH}") |