File size: 3,309 Bytes
20d7fde
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import os
import random
import glob
import numpy as np
from PIL import Image, ImageFilter
import cv2

INGREDIENTS_PATH = "ingredients"
OUTPUT_PATH = "train_data2"
BOX_HEIGHT = 40
BOX_WIDTH = 80
SAMPLES_PER_CLASS = 300 

move_classes = [f"{s}{e}" for s in range(1, 10) for e in range(1, 10)] + \
               [f"{s}{e}x" for s in range(1, 10) for e in range(1, 10)]
classes = move_classes + ['empty']

os.makedirs(OUTPUT_PATH, exist_ok=True)

def crop_and_center_ink(cv2_gray_img, target_w=80, target_h=40, margin=4):
    ink_mask = cv2.bitwise_not(cv2_gray_img)
    coords = cv2.findNonZero(ink_mask)
    if coords is not None:
        x, y, w, h = cv2.boundingRect(coords)
        crop = cv2_gray_img[y:y+h, x:x+w]
        scale = min((target_w - 2*margin) / w, (target_h - 2*margin) / h)
        new_w, new_h = max(1, int(w * scale)), max(1, int(h * scale))
        resized_crop = cv2.resize(crop, (new_w, new_h), interpolation=cv2.INTER_AREA)
        canvas = np.full((target_h, target_w), 255, dtype=np.uint8)
        start_x, start_y = (target_w - new_w) // 2, (target_h - new_h) // 2
        canvas[start_y:start_y+new_h, start_x:start_x+new_w] = resized_crop
        return canvas
    return np.full((target_h, target_w), 255, dtype=np.uint8)

def create_move_image(class_name):
    if class_name == 'empty':
        return Image.new('L', (BOX_WIDTH, BOX_HEIGHT), color=255)

    # Start with a clean canvas
    img = Image.new('L', (200, 200), color=255)
    current_x = 40 
    for char in class_name:
        files = glob.glob(os.path.join(INGREDIENTS_PATH, char, "*.png"))
        char_img = Image.open(random.choice(files))
        size = random.randint(22, 28) if char == 'x' else random.randint(32, 42)
        char_img = char_img.resize((size, size), Image.Resampling.LANCZOS)
        char_img = char_img.rotate(random.randint(-12, 12), expand=True, fillcolor=0)
        bbox = char_img.getbbox()
        if bbox: char_img = char_img.crop(bbox)
        
        ink_layer = Image.new('L', char_img.size, color=0)
        paste_y = 100 - (char_img.height // 2) + random.randint(-5, 5)
        img.paste(ink_layer, (current_x, paste_y), mask=char_img)
        current_x += char_img.width + random.randint(-1, 4)

    # --- THE CRITICAL FIX: Center FIRST, then Dilate ---
    temp_arr = np.array(img)
    centered = crop_and_center_ink(temp_arr, BOX_WIDTH, BOX_HEIGHT)
    
    # Randomly vary thickness (Some thin, some thick)
    ink_is_white = cv2.bitwise_not(centered)
    thickness = random.choice([1, 2, 2]) # Weight it towards thicker lines
    kernel = np.ones((thickness, thickness), np.uint8)
    thick_ink = cv2.dilate(ink_is_white, kernel, iterations=1)
    
    # Add a tiny bit of blur/noise to simulate real camera focus
    final_img = cv2.bitwise_not(thick_ink)
    pil_final = Image.fromarray(final_img)
    if random.random() > 0.5:
        pil_final = pil_final.filter(ImageFilter.GaussianBlur(radius=0.3))
        
    return pil_final

# ... Execution loop remains same as previous ...
print("Generating centered data with variable thickness...")
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):
        create_move_image(cls).save(os.path.join(class_dir, f"{cls}_{i}.png"))