Srish117 commited on
Commit
cb47756
·
verified ·
1 Parent(s): 0ab566b

main commit

Browse files
Files changed (1) hide show
  1. app.py +131 -80
app.py CHANGED
@@ -1,80 +1,131 @@
1
- import gradio as gr
2
- import torch
3
- import torch.nn as nn
4
- import torchvision.utils as vutils
5
- from torchvision import transforms
6
- from PIL import Image
7
-
8
- # --- 1. Define the Brain Structure (Must match your training code!) ---
9
- class Generator(nn.Module):
10
- def __init__(self, ngpu):
11
- super(Generator, self).__init__()
12
- self.ngpu = ngpu
13
- nz = 100 # Noise size
14
- self.main = nn.Sequential(
15
- # Input is Z (Noise Vector)
16
- nn.ConvTranspose2d(nz, 512, 4, 1, 0, bias=False),
17
- nn.BatchNorm2d(512),
18
- nn.ReLU(True),
19
- # 4x4 -> 8x8
20
- nn.ConvTranspose2d(512, 256, 4, 2, 1, bias=False),
21
- nn.BatchNorm2d(256),
22
- nn.ReLU(True),
23
- # 8x8 -> 16x16
24
- nn.ConvTranspose2d(256, 128, 4, 2, 1, bias=False),
25
- nn.BatchNorm2d(128),
26
- nn.ReLU(True),
27
- # 16x16 -> 32x32
28
- nn.ConvTranspose2d(128, 64, 4, 2, 1, bias=False),
29
- nn.BatchNorm2d(64),
30
- nn.ReLU(True),
31
- # 32x32 -> 64x64
32
- nn.ConvTranspose2d(64, 3, 4, 2, 1, bias=False),
33
- nn.Tanh()
34
- )
35
-
36
- def forward(self, input):
37
- return self.main(input)
38
-
39
- # --- 2. Load the Model ---
40
- device = torch.device("cpu") # Spaces run on CPU by default
41
- model = Generator(ngpu=0).to(device)
42
-
43
- # Load weights (map_location is vital for CPU spaces)
44
- model.load_state_dict(torch.load("generator_final.pth", map_location=device))
45
- model.eval()
46
-
47
- # --- 3. The Generation Function ---
48
- def generate_art(seed, noise_level):
49
- torch.manual_seed(int(seed))
50
-
51
- # Create noise vector
52
- noise = torch.randn(1, 100, 1, 1, device=device)
53
-
54
- # Generate image
55
- with torch.no_grad():
56
- fake = model(noise).detach().cpu()
57
-
58
- # Process image (Un-normalize from -1,1 to 0,1)
59
- img_tensor = (fake[0] * 0.5) + 0.5
60
- img_pil = transforms.ToPILImage()(img_tensor)
61
-
62
- # Upscale nicely for the web
63
- img_pil = img_pil.resize((256, 256), resample=Image.NEAREST)
64
- return img_pil
65
-
66
- # --- 4. The Interface ---
67
- with gr.Blocks() as demo:
68
- gr.Markdown("# 👾 8-Bit Hero Generator (2025 Edition)")
69
- gr.Markdown("I trained this AI from scratch on New Year's Eve 2025 using PyTorch & DCGAN.")
70
-
71
- with gr.Row():
72
- with gr.Column():
73
- seed_slider = gr.Slider(0, 9999, label="Character DNA (Seed)", value=42)
74
- btn = gr.Button("Generate New Hero")
75
- with gr.Column():
76
- output_image = gr.Image(label="Result", type="pil")
77
-
78
- btn.click(fn=generate_art, inputs=[seed_slider, seed_slider], outputs=output_image)
79
-
80
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ import torch.nn as nn
4
+ import torchvision.utils as vutils
5
+ from torchvision import transforms
6
+ from PIL import Image, ImageOps, ImageEnhance
7
+ import numpy as np
8
+ import random
9
+
10
+ # --- 1. The Brain (Same as before) ---
11
+ class Generator(nn.Module):
12
+ def __init__(self, ngpu):
13
+ super(Generator, self).__init__()
14
+ self.ngpu = ngpu
15
+ nz = 100
16
+ self.main = nn.Sequential(
17
+ nn.ConvTranspose2d(nz, 512, 4, 1, 0, bias=False),
18
+ nn.BatchNorm2d(512),
19
+ nn.ReLU(True),
20
+ nn.ConvTranspose2d(512, 256, 4, 2, 1, bias=False),
21
+ nn.BatchNorm2d(256),
22
+ nn.ReLU(True),
23
+ nn.ConvTranspose2d(256, 128, 4, 2, 1, bias=False),
24
+ nn.BatchNorm2d(128),
25
+ nn.ReLU(True),
26
+ nn.ConvTranspose2d(128, 64, 4, 2, 1, bias=False),
27
+ nn.BatchNorm2d(64),
28
+ nn.ReLU(True),
29
+ nn.ConvTranspose2d(64, 3, 4, 2, 1, bias=False),
30
+ nn.Tanh()
31
+ )
32
+
33
+ def forward(self, input):
34
+ return self.main(input)
35
+
36
+ # --- 2. Load Model ---
37
+ device = torch.device("cpu")
38
+ model = Generator(ngpu=0).to(device)
39
+ model.load_state_dict(torch.load("generator_final.pth", map_location=device))
40
+ model.eval()
41
+
42
+ # --- 3. Advanced Generation Logic ---
43
+ def generate_hero(seed_A, seed_B, morph_factor, clean_up, retro_mode, resolution):
44
+ # Set seeds
45
+ torch.manual_seed(int(seed_A))
46
+ noise_A = torch.randn(1, 100, 1, 1, device=device)
47
+
48
+ torch.manual_seed(int(seed_B))
49
+ noise_B = torch.randn(1, 100, 1, 1, device=device)
50
+
51
+ # MORPHING: Mix the two DNA seeds based on the slider
52
+ # If factor is 0, it's 100% A. If 1, it's 100% B.
53
+ final_noise = (1 - morph_factor) * noise_A + (morph_factor) * noise_B
54
+
55
+ with torch.no_grad():
56
+ fake = model(final_noise).detach().cpu()
57
+
58
+ # CLEANUP FILTER: Remove weak pixels (noise removal)
59
+ if clean_up:
60
+ # If a pixel is very dark, make it pure black (-1.0)
61
+ fake = torch.where(fake < -0.7, torch.tensor(-1.0), fake)
62
+
63
+ # Process to Image
64
+ img_tensor = (fake[0] * 0.5) + 0.5
65
+ img_pil = transforms.ToPILImage()(img_tensor)
66
+
67
+ # RETRO GAMEBOY FILTER
68
+ if retro_mode:
69
+ # Convert to grayscale then tint green
70
+ img_pil = ImageOps.grayscale(img_pil)
71
+ img_pil = ImageOps.colorize(img_pil, black="#0f380f", white="#9bbc0f") # Gameboy Palette
72
+
73
+ # RESOLUTION SCALING
74
+ size = int(resolution)
75
+ img_pil = img_pil.resize((size, size), resample=Image.NEAREST)
76
+
77
+ return img_pil
78
+
79
+ # --- 4. The "Pro" Interface ---
80
+ css = """
81
+ body {background-color: #121212; color: white;}
82
+ .gradio-container {font-family: 'Courier New', monospace;}
83
+ """
84
+
85
+ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
86
+ gr.Markdown("# ⚔️ 8-Bit Hero Forge (Ultimate Edition)")
87
+ gr.Markdown("Create, Morph, and Polish unique pixel characters. Trained on Dec 31, 2025.")
88
+
89
+ with gr.Row():
90
+ # LEFT COLUMN: Controls
91
+ with gr.Column(scale=1):
92
+ gr.Markdown("### 🧬 DNA Mixer")
93
+ with gr.Row():
94
+ seed_A = gr.Number(label="Hero A ID", value=42, precision=0)
95
+ seed_B = gr.Number(label="Hero B ID", value=999, precision=0)
96
+
97
+ morph = gr.Slider(0.0, 1.0, value=0.0, step=0.01, label="Morph Slider (Mix A & B)")
98
+
99
+ gr.Markdown("### 🛠️ Polish Lab")
100
+ clean_btn = gr.Checkbox(label="Auto-Clean Noise", value=True)
101
+ retro_btn = gr.Checkbox(label="GameBoy Retro Mode", value=False)
102
+ res_drop = gr.Dropdown([64, 256, 512, 1024], value=512, label="Output Size (px)")
103
+
104
+ gen_btn = gr.Button("✨ Forge Hero", variant="primary", size="lg")
105
+
106
+ # Randomizer Button Logic
107
+ def randomize():
108
+ return random.randint(0, 9999), random.randint(0, 9999)
109
+
110
+ rand_btn = gr.Button("🎲 Randomize IDs")
111
+ rand_btn.click(fn=randomize, inputs=None, outputs=[seed_A, seed_B])
112
+
113
+ # RIGHT COLUMN: Output
114
+ with gr.Column(scale=1):
115
+ output_img = gr.Image(label="Your Hero", type="pil", interactive=False)
116
+
117
+ # Connect the logic
118
+ gen_btn.click(
119
+ fn=generate_hero,
120
+ inputs=[seed_A, seed_B, morph, clean_btn, retro_btn, res_drop],
121
+ outputs=output_img
122
+ )
123
+
124
+ # Live update when dragging morph slider
125
+ morph.change(
126
+ fn=generate_hero,
127
+ inputs=[seed_A, seed_B, morph, clean_btn, retro_btn, res_drop],
128
+ outputs=output_img
129
+ )
130
+
131
+ demo.launch()