primerz commited on
Commit
2799929
·
verified ·
1 Parent(s): 59a395a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -351
app.py CHANGED
@@ -5,428 +5,155 @@ from model import ModelHandler
5
  from generator import Generator
6
  from config import Config
7
 
8
- # ============================================================================
9
- # INITIALIZATION
10
- # ============================================================================
11
-
12
- print("🚀 Initializing Enhanced Face To Style Application...")
13
  handler = ModelHandler()
14
-
15
- # Load with default edge type (can be changed via environment variable)
16
- import os
17
- edge_type = os.getenv("EDGE_TYPE", Config.DEFAULT_EDGE_TYPE)
18
- print(f"Loading models with edge type: {edge_type}")
19
- handler.load_models(edge_type=edge_type)
20
-
21
  gen = Generator(handler)
22
- print("✅ Application Ready!\n")
23
-
24
- # ============================================================================
25
- # INFERENCE FUNCTION
26
- # ============================================================================
27
 
 
28
  @spaces.GPU(duration=20)
29
  def process_img(
30
  image,
31
  prompt,
32
  negative_prompt,
33
- cfg_scale,
34
  steps,
35
  img_strength,
36
  depth_strength,
37
  edge_strength,
38
- instantid_strength,
39
- canny_low,
40
- canny_high,
41
- eta,
42
- seed,
43
- show_controls
44
  ):
45
- """Enhanced processing with control image preview option"""
46
  if image is None:
47
  raise gr.Error("Please upload an image first.")
48
 
49
  try:
50
- print("=" * 70)
51
- print("STARTING GENERATION")
52
- print("=" * 70)
53
-
54
  result = gen.predict(
55
  image,
56
  prompt,
57
  negative_prompt=negative_prompt,
58
- guidance_scale=cfg_scale,
59
  num_inference_steps=steps,
60
  img2img_strength=img_strength,
61
  depth_strength=depth_strength,
62
- edge_strength=edge_strength,
63
- instantid_strength=instantid_strength,
64
- canny_low_threshold=canny_low,
65
- canny_high_threshold=canny_high,
66
- eta=eta,
67
- seed=seed,
68
- return_control_images=show_controls
69
  )
70
-
71
- print("=" * 70)
72
- print("✅ GENERATION COMPLETE")
73
- print("=" * 70)
74
-
75
- if show_controls:
76
- output_image, control_dict = result
77
- # Create a preview grid of control images
78
- controls_preview = create_control_preview(control_dict)
79
- return output_image, controls_preview
80
- else:
81
- return result, None
82
 
83
  except Exception as e:
84
- print(f"Error during generation: {e}")
85
- import traceback
86
- traceback.print_exc()
87
  raise gr.Error(f"An error occurred: {str(e)}")
88
 
89
- def create_control_preview(control_dict):
90
- """Create a preview grid of control images"""
91
- from PIL import Image
92
- import numpy as np
93
-
94
- images = []
95
- labels = []
96
-
97
- if control_dict.get('processed_input'):
98
- images.append(control_dict['processed_input'])
99
- labels.append("Processed Input")
100
-
101
- if control_dict.get('depth'):
102
- images.append(control_dict['depth'])
103
- labels.append("Depth Map")
104
-
105
- if control_dict.get('edges'):
106
- for i, edge in enumerate(control_dict['edges']):
107
- images.append(edge)
108
- edge_type = "Canny" if i == 0 else "LineArt"
109
- labels.append(f"{edge_type} Edges")
110
-
111
- if control_dict.get('face_kps'):
112
- images.append(control_dict['face_kps'])
113
- labels.append("Face Keypoints")
114
-
115
- # Create grid
116
- if not images:
117
- return None
118
-
119
- # Simple horizontal concatenation for now
120
- # You could make this fancier with a proper grid layout
121
- return images[0] # Just return first for now - can be enhanced
122
-
123
- # ============================================================================
124
- # PRESET CONFIGURATIONS
125
- # ============================================================================
126
-
127
- PRESETS = {
128
- "Balanced (Default)": {
129
- "cfg_scale": 4.0,
130
- "steps": 8,
131
- "img_strength": 0.8,
132
- "depth_strength": 0.5,
133
- "edge_strength": 0.5,
134
- "instantid_strength": 0.8,
135
- "eta": 0.45
136
- },
137
- "Fast": {
138
- "cfg_scale": 3.0,
139
- "steps": 4,
140
- "img_strength": 0.7,
141
- "depth_strength": 0.4,
142
- "edge_strength": 0.4,
143
- "instantid_strength": 0.7,
144
- "eta": 0.5
145
- },
146
- "Quality": {
147
- "cfg_scale": 5.0,
148
- "steps": 12,
149
- "img_strength": 0.85,
150
- "depth_strength": 0.6,
151
- "edge_strength": 0.6,
152
- "instantid_strength": 0.85,
153
- "eta": 0.3
154
- },
155
- "Strong Style": {
156
- "cfg_scale": 7.0,
157
- "steps": 10,
158
- "img_strength": 0.75,
159
- "depth_strength": 0.4,
160
- "edge_strength": 0.4,
161
- "instantid_strength": 0.6,
162
- "eta": 0.4
163
- },
164
- "Preserve Structure": {
165
- "cfg_scale": 4.0,
166
- "steps": 8,
167
- "img_strength": 0.9,
168
- "depth_strength": 0.8,
169
- "edge_strength": 0.8,
170
- "instantid_strength": 0.9,
171
- "eta": 0.3
172
- }
173
- }
174
-
175
- def apply_preset(preset_name):
176
- """Apply preset configuration"""
177
- if preset_name in PRESETS:
178
- preset = PRESETS[preset_name]
179
- return [
180
- preset["cfg_scale"],
181
- preset["steps"],
182
- preset["img_strength"],
183
- preset["depth_strength"],
184
- preset["edge_strength"],
185
- preset["instantid_strength"],
186
- preset["eta"]
187
- ]
188
- return [4.0, 8, 0.8, 0.5, 0.5, 0.8, 0.45] # Default
189
-
190
- # ============================================================================
191
- # GRADIO INTERFACE
192
- # ============================================================================
193
-
194
- with gr.Blocks(title="Enhanced Face To Style", theme=gr.themes.Soft()) as demo:
195
  gr.Markdown(
196
  """
197
- # 🎨 Enhanced Face to Style
198
-
199
- Upload any image and transform it with AI-powered style transfer!
200
- - **With Face**: Preserves identity using InstantID
201
- - **Without Face**: Pure artistic stylization
202
- - **TCD Accelerated**: Ultra-fast generation (4-12 steps)
203
 
204
- ---
205
  """
206
  )
207
 
208
  with gr.Row():
209
- # ===== LEFT COLUMN: INPUTS =====
210
  with gr.Column(scale=2):
211
- input_img = gr.Image(type="pil", label="📸 Input Image")
212
-
213
  prompt = gr.Textbox(
214
- label="✍️ Prompt (Optional)",
215
  placeholder="Leave empty for auto-captioning...",
216
- info=f"Trigger words '{Config.STYLE_TRIGGER}' are added automatically.",
217
- lines=2
218
  )
219
 
220
  negative_prompt = gr.Textbox(
221
- label="🚫 Negative Prompt",
222
  placeholder="e.g., blurry, text, watermark, bad art...",
223
- value=Config.DEFAULT_NEGATIVE_PROMPT,
224
- lines=2
225
  )
226
 
227
- # Preset Selector
228
- with gr.Row():
229
- preset_dropdown = gr.Dropdown(
230
- choices=list(PRESETS.keys()),
231
- value="Balanced (Default)",
232
- label="🎛️ Presets",
233
- info="Quick configurations for different use cases"
234
  )
235
- apply_preset_btn = gr.Button("Apply Preset", size="sm")
236
-
237
- # Advanced Settings
238
- with gr.Accordion("🔧 Advanced Settings", open=False):
239
- with gr.Row():
240
- seed = gr.Number(
241
- label="🎲 Seed",
242
- value=-1,
243
- info="-1 for random",
244
- precision=0
245
- )
246
- show_controls = gr.Checkbox(
247
- label="Show Control Images",
248
- value=False,
249
- info="Display depth/edge maps"
250
- )
251
 
252
- gr.Markdown("### Core Parameters")
253
- with gr.Row():
254
- cfg_scale = gr.Slider(
255
- minimum=1.0,
256
- maximum=10.0,
257
- step=0.1,
258
- value=4.0,
259
- label="🎨 Style Strength (CFG)",
260
- info="Higher = stronger style adherence"
261
- )
262
-
263
- steps = gr.Slider(
264
- minimum=1,
265
- maximum=20,
266
- step=1,
267
- value=8,
268
- label="⚡ Steps",
269
- info="TCD works well with 4-12"
270
- )
271
-
272
- with gr.Row():
273
- img_strength = gr.Slider(
274
- minimum=0.1,
275
- maximum=1.0,
276
- step=0.05,
277
- value=0.8,
278
- label="🖼️ Image Strength",
279
- info="Higher = more transformation"
280
- )
281
-
282
- eta = gr.Slider(
283
- minimum=0.0,
284
- maximum=1.0,
285
- step=0.05,
286
- value=0.45,
287
- label="🎲 Eta (Randomness)",
288
- info="TCD stochasticity parameter"
289
- )
290
-
291
- gr.Markdown("### Control Strengths")
292
- with gr.Row():
293
- depth_strength = gr.Slider(
294
- minimum=0.0,
295
- maximum=1.0,
296
- step=0.05,
297
- value=0.5,
298
- label="🗺️ Depth Strength",
299
- info="Spatial structure preservation"
300
- )
301
-
302
- edge_strength = gr.Slider(
303
- minimum=0.0,
304
- maximum=1.0,
305
- step=0.05,
306
- value=0.5,
307
- label="✏️ Edge Strength",
308
- info="Boundary/detail preservation"
309
- )
310
-
311
- instantid_strength = gr.Slider(
312
- minimum=0.0,
313
- maximum=1.0,
314
- step=0.05,
315
- value=0.8,
316
- label="👤 Face Preservation (InstantID)",
317
- info="Only applies if face detected"
318
  )
319
 
320
- # Canny-specific controls (only show if using canny)
321
- if edge_type in ["canny", "both"]:
322
- gr.Markdown("### Canny Edge Detection")
323
- with gr.Row():
324
- canny_low = gr.Slider(
325
- minimum=0,
326
- maximum=255,
327
- step=1,
328
- value=100,
329
- label="Low Threshold",
330
- info="Lower = more edges"
331
- )
332
- canny_high = gr.Slider(
333
- minimum=0,
334
- maximum=255,
335
- step=1,
336
- value=200,
337
- label="High Threshold",
338
- info="Higher = only strong edges"
339
- )
340
- else:
341
- # Hidden sliders with default values
342
- canny_low = gr.Slider(value=100, visible=False)
343
- canny_high = gr.Slider(value=200, visible=False)
 
 
 
 
 
 
 
 
344
 
345
- run_btn = gr.Button("Generate", variant="primary", size="lg")
346
 
347
- # ===== RIGHT COLUMN: OUTPUTS =====
348
  with gr.Column(scale=1):
349
- output_img = gr.Image(label="🎨 Styled Result")
350
- control_preview = gr.Image(label="🔍 Control Images Preview", visible=False)
351
-
352
- # Info Section
353
- with gr.Row():
354
- gr.Markdown(
355
- f"""
356
- ### 💡 Tips
357
- - **Fast Preview**: Use 4-6 steps with Fast preset
358
- - **Best Quality**: Use 10-12 steps with Quality preset
359
- - **Strong Stylization**: Increase CFG scale and decrease control strengths
360
- - **Preserve Details**: Increase depth/edge strengths
361
- - **Edge Type**: Currently using **{edge_type.upper()}** detection
362
-
363
- ### ⚙️ Current Configuration
364
- - **LoRA**: {Config.LORA_FILENAME} (strength: {Config.LORA_STRENGTH})
365
- - **Trigger**: `{Config.STYLE_TRIGGER}`
366
- - **Scheduler**: TCD (Trajectory Consistency Distillation)
367
- """
368
- )
369
-
370
- # ===== EVENT HANDLERS =====
371
-
372
- # Collect all inputs
373
  all_inputs = [
374
  input_img,
375
  prompt,
376
  negative_prompt,
377
- cfg_scale,
378
  steps,
379
  img_strength,
380
  depth_strength,
381
  edge_strength,
382
- instantid_strength,
383
- canny_low,
384
- canny_high,
385
- eta,
386
- seed,
387
- show_controls
388
  ]
389
 
390
- # Generate button
391
  run_btn.click(
392
  fn=process_img,
393
  inputs=all_inputs,
394
- outputs=[output_img, control_preview]
395
- )
396
-
397
- # Preset application
398
- preset_outputs = [
399
- cfg_scale,
400
- steps,
401
- img_strength,
402
- depth_strength,
403
- edge_strength,
404
- instantid_strength,
405
- eta
406
- ]
407
-
408
- apply_preset_btn.click(
409
- fn=apply_preset,
410
- inputs=[preset_dropdown],
411
- outputs=preset_outputs
412
- )
413
-
414
- # Show/hide control preview based on checkbox
415
- show_controls.change(
416
- fn=lambda x: gr.update(visible=x),
417
- inputs=[show_controls],
418
- outputs=[control_preview]
419
  )
420
 
421
- # ============================================================================
422
- # LAUNCH
423
- # ============================================================================
424
 
 
425
  if __name__ == "__main__":
426
  demo.queue(max_size=20, api_open=True)
427
  demo.launch(
428
  server_name="0.0.0.0",
429
  server_port=7860,
430
- show_api=True,
431
- share=False
432
  )
 
5
  from generator import Generator
6
  from config import Config
7
 
8
+ # 1. Initialize Models Globally
9
+ print("Initializing Application...")
 
 
 
10
  handler = ModelHandler()
11
+ handler.load_models()
 
 
 
 
 
 
12
  gen = Generator(handler)
 
 
 
 
 
13
 
14
+ # 2. Define GPU-enabled Inference Function
15
  @spaces.GPU(duration=20)
16
  def process_img(
17
  image,
18
  prompt,
19
  negative_prompt,
20
+ cfg_scale, # <-- RE-ENABLED
21
  steps,
22
  img_strength,
23
  depth_strength,
24
  edge_strength,
25
+ seed
 
 
 
 
 
26
  ):
 
27
  if image is None:
28
  raise gr.Error("Please upload an image first.")
29
 
30
  try:
31
+ print("--- Starting Generation ---")
 
 
 
32
  result = gen.predict(
33
  image,
34
  prompt,
35
  negative_prompt=negative_prompt,
36
+ guidance_scale=cfg_scale, # <-- RE-ENABLED
37
  num_inference_steps=steps,
38
  img2img_strength=img_strength,
39
  depth_strength=depth_strength,
40
+ lineart_strength=edge_strength,
41
+ seed=seed
 
 
 
 
 
42
  )
43
+ print("--- Generation Complete ---")
44
+ return result
 
 
 
 
 
 
 
 
 
 
45
 
46
  except Exception as e:
47
+ print(f"Error during generation: {e}")
 
 
48
  raise gr.Error(f"An error occurred: {str(e)}")
49
 
50
+ # 3. Build Gradio Interface
51
+ with gr.Blocks(title="Face To Style", theme=gr.themes.Soft()) as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  gr.Markdown(
53
  """
54
+ # 🎨 Face to Style
55
+ Upload any image. If there is a face, we'll keep the identity. If not, we'll stylize the scene!
 
 
 
 
56
 
57
+ **Using DPMSolver++ scheduler with Karras sigmas for high-quality results.**
58
  """
59
  )
60
 
61
  with gr.Row():
 
62
  with gr.Column(scale=2):
63
+ input_img = gr.Image(type="pil", label="Input Image")
 
64
  prompt = gr.Textbox(
65
+ label="Prompt (Optional)",
66
  placeholder="Leave empty for auto-captioning...",
67
+ info=f"The trigger words '{Config.STYLE_TRIGGER}' are added automatically."
 
68
  )
69
 
70
  negative_prompt = gr.Textbox(
71
+ label="Negative Prompt (Optional)",
72
  placeholder="e.g., blurry, text, watermark, bad art...",
73
+ value=Config.DEFAULT_NEGATIVE_PROMPT
 
74
  )
75
 
76
+ with gr.Accordion("Advanced Settings", open=False):
77
+ seed = gr.Number(
78
+ label="Seed",
79
+ value=-1,
80
+ info="-1 for random",
81
+ precision=0
 
82
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
 
84
+ # --- CFG/GUIDANCE SLIDER ---
85
+ cfg_scale = gr.Slider(
86
+ elem_id="cfg_scale",
87
+ minimum=1.0,
88
+ maximum=15.0,
89
+ step=0.5,
90
+ value=Config.CGF_SCALE, # Default 7.0
91
+ label="Guidance Scale (CFG)"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  )
93
 
94
+ steps = gr.Slider(
95
+ elem_id="steps",
96
+ minimum=15,
97
+ maximum=50,
98
+ step=1,
99
+ value=20, # DPMSolver++ default
100
+ label="Steps Number"
101
+ )
102
+ img_strength = gr.Slider(
103
+ elem_id="img_strength",
104
+ minimum=0.5,
105
+ maximum=1.0,
106
+ step=0.05,
107
+ value=Config.IMG_STRENGTH,
108
+ label="Image Strength (Img2Img)"
109
+ )
110
+ depth_strength = gr.Slider(
111
+ elem_id="depth_strength",
112
+ minimum=0.0,
113
+ maximum=1.0,
114
+ step=0.05,
115
+ value=Config.DEPTH_STRENGTH,
116
+ label="DepthMap Strength"
117
+ )
118
+ edge_strength = gr.Slider(
119
+ elem_id="edge_strength",
120
+ minimum=0.0,
121
+ maximum=1.0,
122
+ step=0.05,
123
+ value=Config.EDGE_STRENGTH,
124
+ label="EdgeMap Strength (LineArt)"
125
+ )
126
 
127
+ run_btn = gr.Button("Generate", variant="primary")
128
 
 
129
  with gr.Column(scale=1):
130
+ output_img = gr.Image(label="Styled Result")
131
+
132
+ # Event Handler
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  all_inputs = [
134
  input_img,
135
  prompt,
136
  negative_prompt,
137
+ cfg_scale, # <-- RE-ENABLED
138
  steps,
139
  img_strength,
140
  depth_strength,
141
  edge_strength,
142
+ seed
 
 
 
 
 
143
  ]
144
 
 
145
  run_btn.click(
146
  fn=process_img,
147
  inputs=all_inputs,
148
+ outputs=[output_img]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  )
150
 
 
 
 
151
 
152
+ # 4. Launch the App
153
  if __name__ == "__main__":
154
  demo.queue(max_size=20, api_open=True)
155
  demo.launch(
156
  server_name="0.0.0.0",
157
  server_port=7860,
158
+ show_api=True
 
159
  )