beertoshi commited on
Commit
920f263
·
verified ·
1 Parent(s): da348cc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +167 -115
app.py CHANGED
@@ -1,195 +1,247 @@
1
  import gradio as gr
2
  import torch
3
- from diffusers import StableDiffusionInpaintPipeline
4
- from PIL import Image, ImageDraw, ImageFilter
5
  import numpy as np
6
  import spaces
7
 
8
- # Initialize model globally (loaded on CPU first)
9
- print("Loading model on CPU first (ZeroGPU will move it to GPU when needed)...")
10
-
11
- pipe = StableDiffusionInpaintPipeline.from_pretrained(
12
  "stabilityai/stable-diffusion-2-inpainting",
13
  torch_dtype=torch.float16,
14
  safety_checker=None,
15
  requires_safety_checker=False
16
  )
 
 
 
17
 
18
- # Don't move to GPU yet - ZeroGPU will handle this
19
- pipe.enable_attention_slicing()
20
-
21
- print("✅ Model loaded! ZeroGPU will activate when generating.")
22
 
23
- # Clothing prompts
24
  CLOTHING_PROMPTS = {
25
- "Indian Sari": "woman wearing beautiful red and gold silk sari, traditional Indian saree dress, intricate embroidery",
26
- "Japanese Kimono": "person wearing elegant floral kimono with obi belt, traditional Japanese clothing, silk fabric",
27
- "African Dashiki": "person wearing colorful African dashiki with geometric patterns, traditional clothing, vibrant",
28
- "Chinese Qipao": "woman wearing elegant red qipao cheongsam dress, traditional Chinese dress, silk with gold patterns",
29
- "Scottish Kilt": "man wearing traditional Scottish kilt with tartan pattern, highland dress, sporran",
30
- "Middle Eastern Thobe": "person wearing white thobe robe, traditional Middle Eastern clothing, flowing fabric"
31
  }
32
 
33
- def create_body_mask(image):
34
- """Create mask for clothing area"""
35
  width, height = image.size
 
 
36
  mask = Image.new('L', (width, height), 0)
37
  draw = ImageDraw.Draw(mask)
38
 
39
- # Body area ellipse
40
- left = width * 0.2
41
- top = height * 0.25
42
- right = width * 0.8
43
- bottom = height * 0.95
 
 
 
 
 
44
 
45
- draw.ellipse([left, top, right, bottom], fill=255)
46
- mask = mask.filter(ImageFilter.GaussianBlur(radius=20))
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
  return mask
49
 
50
- @spaces.GPU(duration=60) # Request GPU for 60 seconds
51
- def generate_clothing(input_image, clothing_type, num_steps=25, guidance_scale=7.5):
52
- """Generate traditional clothing with ZeroGPU"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
  if input_image is None:
55
- return None, "Please upload an image first"
56
 
57
  try:
58
- # Move model to GPU (ZeroGPU allocates it now)
59
- pipe.to("cuda")
60
 
61
- # Convert to PIL if needed
62
  if isinstance(input_image, np.ndarray):
63
  image = Image.fromarray(input_image).convert("RGB")
64
  else:
65
  image = input_image.convert("RGB")
66
 
67
- # Store original size
 
68
  original_size = image.size
69
 
 
 
 
 
 
 
 
 
 
70
  # Resize for processing
71
- max_size = 512
72
- if max(image.size) > max_size:
73
- ratio = max_size / max(image.size)
74
  new_size = tuple(int(dim * ratio) for dim in image.size)
75
  image = image.resize(new_size, Image.Resampling.LANCZOS)
 
 
 
 
 
 
76
 
77
- # Create mask
78
- mask = create_body_mask(image)
79
 
80
- # Get prompt
81
  prompt = CLOTHING_PROMPTS[clothing_type]
82
- negative_prompt = "nude, naked, nsfw, bad quality, blurry, distorted"
83
 
84
- # Generate with GPU
85
  with torch.autocast("cuda"):
86
- result = pipe(
87
  prompt=prompt,
88
  negative_prompt=negative_prompt,
89
  image=image,
90
  mask_image=mask,
91
- num_inference_steps=num_steps,
92
- guidance_scale=guidance_scale,
93
- strength=0.95
 
 
94
  ).images[0]
95
 
96
- # Resize back
97
- if result.size != original_size:
98
- result = result.resize(original_size, Image.Resampling.LANCZOS)
99
 
100
- # Move model back to CPU to free GPU
101
- pipe.to("cpu")
 
 
 
 
 
 
 
102
  torch.cuda.empty_cache()
103
 
104
- return result, f"✅ Successfully added {clothing_type}!"
105
 
106
  except Exception as e:
107
- print(f"Generation error: {e}")
108
  return None, f"Error: {str(e)}"
109
 
110
- # Create interface
111
- with gr.Blocks(title="Traditional Clothing AI - ZeroGPU", theme=gr.themes.Soft()) as app:
112
  gr.Markdown("""
113
- # 👘 Traditional Clothing Addition Tool
114
-
115
- **Powered by ZeroGPU** 🚀 - Free GPU acceleration!
116
-
117
- Add beautiful traditional clothing from various cultures to your photos.
118
- Generation takes about 30-45 seconds per image.
119
  """)
120
 
121
  with gr.Row():
122
  with gr.Column():
123
- input_image = gr.Image(
124
- label="Upload Your Photo",
125
- type="pil"
126
- )
127
 
128
  clothing_type = gr.Dropdown(
129
  choices=list(CLOTHING_PROMPTS.keys()),
130
  value="Indian Sari",
131
- label="Select Traditional Clothing"
132
  )
133
 
134
- with gr.Accordion("Advanced Settings", open=False):
135
- num_steps = gr.Slider(
136
- minimum=15,
137
- maximum=50,
138
- value=25,
139
- step=5,
140
- label="Quality Steps",
141
- info="More steps = better quality but slower"
 
 
 
 
142
  )
143
 
144
- guidance_scale = gr.Slider(
145
- minimum=5,
146
- maximum=15,
147
- value=7.5,
148
- step=0.5,
149
- label="Guidance Scale",
150
- info="Higher = more adherence to prompt"
151
  )
152
 
153
- generate_btn = gr.Button(
154
- "🎨 Add Traditional Clothing",
155
- variant="primary",
156
- size="lg"
157
- )
158
 
159
  with gr.Column():
160
- output_image = gr.Image(
161
- label="Result"
162
- )
163
-
164
- status_text = gr.Textbox(
165
- label="Status",
166
- placeholder="Upload an image and click generate..."
167
- )
168
 
169
  gr.Markdown("""
170
- ---
171
- ### 💡 Tips for Best Results:
172
- - Use clear, front-facing photos
173
- - Good lighting improves results
174
- - The person should be fully visible
175
- - Processing uses free GPU via ZeroGPU
176
-
177
- ### 🌍 Cultural Note:
178
- This tool celebrates cultural diversity through traditional clothing.
179
- AI-generated results are artistic interpretations.
180
- Please use respectfully.
181
-
182
- ### ⚡ About ZeroGPU:
183
- This Space uses Hugging Face's free ZeroGPU feature.
184
- GPU is allocated only during generation, which saves resources!
185
  """)
186
 
187
- # Connect button
188
  generate_btn.click(
189
- fn=generate_clothing,
190
- inputs=[input_image, clothing_type, num_steps, guidance_scale],
191
- outputs=[output_image, status_text]
192
  )
193
 
194
- if __name__ == "__main__":
195
- app.launch()
 
1
  import gradio as gr
2
  import torch
3
+ from diffusers import StableDiffusionInpaintPipeline, StableDiffusionImg2ImgPipeline
4
+ from PIL import Image, ImageDraw, ImageFilter, ImageEnhance
5
  import numpy as np
6
  import spaces
7
 
8
+ # Load models
9
+ inpaint_pipe = StableDiffusionInpaintPipeline.from_pretrained(
 
 
10
  "stabilityai/stable-diffusion-2-inpainting",
11
  torch_dtype=torch.float16,
12
  safety_checker=None,
13
  requires_safety_checker=False
14
  )
15
+ inpaint_pipe.enable_attention_slicing()
16
+ inpaint_pipe.enable_vae_slicing()
17
+ inpaint_pipe.enable_vae_tiling() # For high-res
18
 
19
+ print("✅ Model loaded with high-res support!")
 
 
 
20
 
 
21
  CLOTHING_PROMPTS = {
22
+ "Indian Sari": "woman wearing luxurious red and gold silk sari with intricate embroidery, traditional Indian saree, professional fashion photography, studio lighting, ultra detailed fabric texture, 8k quality",
23
+ "Japanese Kimono": "person wearing exquisite silk kimono with cherry blossom patterns, traditional Japanese formal wear, professional portrait, studio lighting, highly detailed fabric, photorealistic",
24
+ "African Dashiki": "person wearing vibrant African dashiki with authentic kente patterns, traditional clothing, professional photography, rich colors, detailed textile work, high resolution",
25
+ "Chinese Qipao": "elegant woman in traditional Chinese qipao cheongsam, silk dress with intricate patterns, professional fashion shoot, studio lighting, ultra high quality",
 
 
26
  }
27
 
28
+ def create_professional_mask(image, face_margin=0.35):
29
+ """Create professional mask with precise face avoidance"""
30
  width, height = image.size
31
+
32
+ # Create multiple mask layers
33
  mask = Image.new('L', (width, height), 0)
34
  draw = ImageDraw.Draw(mask)
35
 
36
+ # Calculate face-safe area
37
+ face_bottom = height * face_margin
38
+
39
+ # Primary body mask
40
+ body_coords = [
41
+ width * 0.1, # left
42
+ face_bottom, # top (below face)
43
+ width * 0.9, # right
44
+ height * 0.98 # bottom
45
+ ]
46
 
47
+ # Draw main body area
48
+ draw.ellipse(body_coords, fill=255)
49
+
50
+ # Create smooth transition gradient
51
+ gradient_layers = 30
52
+ for i in range(gradient_layers):
53
+ opacity = int(255 * (i / gradient_layers))
54
+ y = face_bottom - (gradient_layers - i)
55
+ if y >= 0:
56
+ draw.rectangle([body_coords[0], y, body_coords[2], y + 1], fill=opacity)
57
+
58
+ # Multi-stage blur for ultra-smooth edges
59
+ mask = mask.filter(ImageFilter.GaussianBlur(radius=15))
60
+ mask = mask.filter(ImageFilter.GaussianBlur(radius=25))
61
 
62
  return mask
63
 
64
+ def enhance_for_processing(image):
65
+ """Enhance image before processing"""
66
+ # Sharpness
67
+ enhancer = ImageEnhance.Sharpness(image)
68
+ image = enhancer.enhance(1.3)
69
+
70
+ # Color
71
+ enhancer = ImageEnhance.Color(image)
72
+ image = enhancer.enhance(1.1)
73
+
74
+ # Contrast
75
+ enhancer = ImageEnhance.Contrast(image)
76
+ image = enhancer.enhance(1.05)
77
+
78
+ return image
79
+
80
+ def professional_blend(original, generated, mask, blend_mode="smooth"):
81
+ """Professional multi-layer blending"""
82
+ # Convert to RGBA
83
+ original_rgba = original.convert("RGBA")
84
+ generated_rgba = generated.convert("RGBA")
85
+
86
+ if blend_mode == "smooth":
87
+ # Create multiple blend masks for smoother transition
88
+ blend_mask1 = mask.filter(ImageFilter.GaussianBlur(radius=40))
89
+ blend_mask2 = mask.filter(ImageFilter.GaussianBlur(radius=60))
90
+
91
+ # First blend pass
92
+ result = Image.composite(generated_rgba, original_rgba, blend_mask1)
93
+
94
+ # Second blend pass for ultra-smooth transition
95
+ result = Image.composite(result, original_rgba, blend_mask2)
96
+ else:
97
+ # Standard blend
98
+ result = Image.composite(generated_rgba, original_rgba, mask)
99
+
100
+ return result.convert("RGB")
101
+
102
+ @spaces.GPU(duration=120)
103
+ def generate_professional_quality(
104
+ input_image,
105
+ clothing_type,
106
+ face_margin=0.35,
107
+ quality_preset="ultra",
108
+ blend_mode="smooth"
109
+ ):
110
+ """Professional workflow with maximum quality"""
111
 
112
  if input_image is None:
113
+ return None, "Please upload an image"
114
 
115
  try:
116
+ # Move to GPU
117
+ inpaint_pipe.to("cuda")
118
 
119
+ # Prepare image
120
  if isinstance(input_image, np.ndarray):
121
  image = Image.fromarray(input_image).convert("RGB")
122
  else:
123
  image = input_image.convert("RGB")
124
 
125
+ # Store originals
126
+ original_image = image.copy()
127
  original_size = image.size
128
 
129
+ # Quality presets
130
+ quality_settings = {
131
+ "fast": {"size": 512, "steps": 30, "guidance": 7.5},
132
+ "balanced": {"size": 768, "steps": 50, "guidance": 8.0},
133
+ "ultra": {"size": 1024, "steps": 75, "guidance": 8.5}
134
+ }
135
+
136
+ settings = quality_settings[quality_preset]
137
+
138
  # Resize for processing
139
+ if max(image.size) > settings["size"]:
140
+ ratio = settings["size"] / max(image.size)
 
141
  new_size = tuple(int(dim * ratio) for dim in image.size)
142
  image = image.resize(new_size, Image.Resampling.LANCZOS)
143
+ original_resized = original_image.resize(new_size, Image.Resampling.LANCZOS)
144
+ else:
145
+ original_resized = original_image
146
+
147
+ # Enhance image
148
+ image = enhance_for_processing(image)
149
 
150
+ # Create professional mask
151
+ mask = create_professional_mask(image, face_margin)
152
 
153
+ # Generate with optimal settings
154
  prompt = CLOTHING_PROMPTS[clothing_type]
155
+ negative_prompt = "blurry, low quality, distorted face, bad anatomy, ugly, amateur"
156
 
 
157
  with torch.autocast("cuda"):
158
+ result = inpaint_pipe(
159
  prompt=prompt,
160
  negative_prompt=negative_prompt,
161
  image=image,
162
  mask_image=mask,
163
+ num_inference_steps=settings["steps"],
164
+ guidance_scale=settings["guidance"],
165
+ strength=0.88, # Optimal for preservation
166
+ height=image.height,
167
+ width=image.width
168
  ).images[0]
169
 
170
+ # Professional blending
171
+ final = professional_blend(original_resized, result, mask, blend_mode)
 
172
 
173
+ # Final enhancement
174
+ final = enhance_for_processing(final)
175
+
176
+ # Resize to original
177
+ if final.size != original_size:
178
+ final = final.resize(original_size, Image.Resampling.LANCZOS)
179
+
180
+ # Cleanup
181
+ inpaint_pipe.to("cpu")
182
  torch.cuda.empty_cache()
183
 
184
+ return final, f"✅ Professional quality {clothing_type} applied!"
185
 
186
  except Exception as e:
 
187
  return None, f"Error: {str(e)}"
188
 
189
+ # Professional UI
190
+ with gr.Blocks(title="Professional Clothing AI", theme=gr.themes.Soft()) as app:
191
  gr.Markdown("""
192
+ # 👘 Professional Traditional Clothing AI
193
+ ### Maximum Quality • Perfect Face Preservation • Studio Results
 
 
 
 
194
  """)
195
 
196
  with gr.Row():
197
  with gr.Column():
198
+ input_image = gr.Image(type="pil", label="Upload High-Res Photo")
 
 
 
199
 
200
  clothing_type = gr.Dropdown(
201
  choices=list(CLOTHING_PROMPTS.keys()),
202
  value="Indian Sari",
203
+ label="Traditional Clothing"
204
  )
205
 
206
+ with gr.Accordion("Professional Settings", open=True):
207
+ face_margin = gr.Slider(
208
+ 0.25, 0.45, 0.35, 0.05,
209
+ label="Face Safety Margin",
210
+ info="Higher = more face protection"
211
+ )
212
+
213
+ quality_preset = gr.Radio(
214
+ ["fast", "balanced", "ultra"],
215
+ value="ultra",
216
+ label="Quality Preset",
217
+ info="Ultra = best quality (2-3 min)"
218
  )
219
 
220
+ blend_mode = gr.Radio(
221
+ ["smooth", "standard"],
222
+ value="smooth",
223
+ label="Blend Mode",
224
+ info="Smooth = seamless transitions"
 
 
225
  )
226
 
227
+ generate_btn = gr.Button("🎨 Generate Professional", variant="primary", size="lg")
 
 
 
 
228
 
229
  with gr.Column():
230
+ output_image = gr.Image(label="Result")
231
+ status = gr.Textbox(label="Status")
 
 
 
 
 
 
232
 
233
  gr.Markdown("""
234
+ ### 🏆 Professional Tips:
235
+ - Use photos 1000px+ for best results
236
+ - Face margin 0.35 preserves faces perfectly
237
+ - Ultra mode takes 2-3 minutes but worth it
238
+ - Smooth blending eliminates all artifacts
 
 
 
 
 
 
 
 
 
 
239
  """)
240
 
 
241
  generate_btn.click(
242
+ generate_professional_quality,
243
+ inputs=[input_image, clothing_type, face_margin, quality_preset, blend_mode],
244
+ outputs=[output_image, status]
245
  )
246
 
247
+ app.launch()