Spaces:
Sleeping
Sleeping
| """ | |
| Procedurally generate a synthetic texture dataset for DCGAN training. | |
| Generates 5 texture types: wood, marble, fabric, brick, noise. | |
| Each type produces 200 images → 1000 total, saved to data/textures/<type>/. | |
| """ | |
| import os | |
| import random | |
| import numpy as np | |
| from PIL import Image, ImageFilter, ImageDraw | |
| IMG_SIZE = 64 | |
| NUM_PER_CLASS = 200 | |
| OUTPUT_DIR = os.path.join("data", "textures") | |
| TEXTURE_TYPES = ["wood", "marble", "fabric", "brick", "noise"] | |
| def generate_wood(size=IMG_SIZE): | |
| """Simulate wood grain using sine waves + noise.""" | |
| arr = np.zeros((size, size, 3), dtype=np.uint8) | |
| freq = random.uniform(3, 8) | |
| phase = random.uniform(0, np.pi * 2) | |
| for y in range(size): | |
| for x in range(size): | |
| grain = np.sin(freq * y / size * np.pi * 2 + phase + random.gauss(0, 0.05)) | |
| r = int(np.clip(120 + 60 * grain + random.randint(-10, 10), 80, 200)) | |
| g = int(np.clip(70 + 30 * grain + random.randint(-10, 10), 40, 130)) | |
| b = int(np.clip(30 + 10 * grain + random.randint(-5, 5), 10, 70)) | |
| arr[y, x] = [r, g, b] | |
| img = Image.fromarray(arr) | |
| img = img.filter(ImageFilter.GaussianBlur(radius=0.5)) | |
| return img | |
| def generate_marble(size=IMG_SIZE): | |
| """Simulate marble veins using Perlin-like noise.""" | |
| arr = np.zeros((size, size, 3), dtype=np.uint8) | |
| scale = random.uniform(0.05, 0.15) | |
| for y in range(size): | |
| for x in range(size): | |
| val = np.sin(x * scale + y * scale * 0.5 + random.gauss(0, 0.3)) * 0.5 + 0.5 | |
| base = int(200 + 40 * val) | |
| r = int(np.clip(base + random.randint(-5, 5), 150, 255)) | |
| g = int(np.clip(base - 10 + random.randint(-5, 5), 140, 245)) | |
| b = int(np.clip(base - 5 + random.randint(-5, 5), 145, 250)) | |
| arr[y, x] = [r, g, b] | |
| img = Image.fromarray(arr) | |
| img = img.filter(ImageFilter.GaussianBlur(radius=0.3)) | |
| return img | |
| def generate_fabric(size=IMG_SIZE): | |
| """Simulate woven fabric using a grid pattern.""" | |
| arr = np.zeros((size, size, 3), dtype=np.uint8) | |
| thread_size = random.randint(3, 6) | |
| hue_r = random.randint(50, 200) | |
| hue_g = random.randint(50, 200) | |
| hue_b = random.randint(50, 200) | |
| for y in range(size): | |
| for x in range(size): | |
| is_warp = (x // thread_size) % 2 == 0 | |
| is_weft = (y // thread_size) % 2 == 0 | |
| if is_warp and not is_weft: | |
| factor = 1.2 | |
| elif not is_warp and is_weft: | |
| factor = 0.8 | |
| else: | |
| factor = 1.0 | |
| r = int(np.clip(hue_r * factor + random.randint(-5, 5), 0, 255)) | |
| g = int(np.clip(hue_g * factor + random.randint(-5, 5), 0, 255)) | |
| b = int(np.clip(hue_b * factor + random.randint(-5, 5), 0, 255)) | |
| arr[y, x] = [r, g, b] | |
| return Image.fromarray(arr) | |
| def generate_brick(size=IMG_SIZE): | |
| """Simulate brick wall pattern.""" | |
| img = Image.new("RGB", (size, size), color=(180, 80, 50)) | |
| draw = ImageDraw.Draw(img) | |
| brick_h = random.randint(8, 12) | |
| brick_w = random.randint(16, 24) | |
| mortar_color = (200, 190, 180) | |
| for row in range(size // brick_h + 1): | |
| y = row * brick_h | |
| offset = (brick_w // 2) if row % 2 else 0 | |
| # Horizontal mortar line | |
| draw.line([(0, y), (size, y)], fill=mortar_color, width=1) | |
| # Vertical mortar lines | |
| for col in range(-1, size // brick_w + 2): | |
| x = col * brick_w + offset | |
| draw.line([(x, y), (x, y + brick_h)], fill=mortar_color, width=1) | |
| # Add slight noise | |
| arr = np.array(img) | |
| noise = np.random.randint(-15, 15, arr.shape, dtype=np.int16) | |
| arr = np.clip(arr.astype(np.int16) + noise, 0, 255).astype(np.uint8) | |
| return Image.fromarray(arr) | |
| def generate_noise(size=IMG_SIZE): | |
| """Generate colorful noise texture.""" | |
| mode = random.choice(["perlin_like", "color_bands", "static"]) | |
| if mode == "static": | |
| arr = np.random.randint(0, 255, (size, size, 3), dtype=np.uint8) | |
| elif mode == "color_bands": | |
| arr = np.zeros((size, size, 3), dtype=np.uint8) | |
| for y in range(size): | |
| r = int((np.sin(y * 0.3) * 0.5 + 0.5) * 255) | |
| g = int((np.cos(y * 0.2) * 0.5 + 0.5) * 255) | |
| b = int((np.sin(y * 0.5 + 1) * 0.5 + 0.5) * 255) | |
| arr[y, :] = [r, g, b] | |
| noise = np.random.randint(-30, 30, arr.shape, dtype=np.int16) | |
| arr = np.clip(arr.astype(np.int16) + noise, 0, 255).astype(np.uint8) | |
| else: | |
| arr = np.zeros((size, size, 3), dtype=np.uint8) | |
| scale = random.uniform(0.1, 0.3) | |
| for y in range(size): | |
| for x in range(size): | |
| v = int((np.sin(x * scale) * np.cos(y * scale) * 0.5 + 0.5) * 255) | |
| arr[y, x] = [v, int(v * 0.7), int(v * 0.4)] | |
| img = Image.fromarray(arr) | |
| img = img.filter(ImageFilter.GaussianBlur(radius=0.5)) | |
| return img | |
| GENERATORS = { | |
| "wood": generate_wood, | |
| "marble": generate_marble, | |
| "fabric": generate_fabric, | |
| "brick": generate_brick, | |
| "noise": generate_noise, | |
| } | |
| def main(): | |
| total = 0 | |
| for texture_type in TEXTURE_TYPES: | |
| out_dir = os.path.join(OUTPUT_DIR, texture_type) | |
| os.makedirs(out_dir, exist_ok=True) | |
| gen_fn = GENERATORS[texture_type] | |
| print(f"Generating {NUM_PER_CLASS} '{texture_type}' textures...") | |
| for i in range(NUM_PER_CLASS): | |
| img = gen_fn(IMG_SIZE) | |
| img.save(os.path.join(out_dir, f"{texture_type}_{i:04d}.png")) | |
| total += 1 | |
| print(f" OK Saved {NUM_PER_CLASS} images to {out_dir}") | |
| print(f"\n Dataset generation complete! Total images: {total}") | |
| print(f" Saved to: {os.path.abspath(OUTPUT_DIR)}") | |
| if __name__ == "__main__": | |
| main() | |