Stylique commited on
Commit
9d498fa
·
verified ·
1 Parent(s): ae1a175

Upload 2 files

Browse files
Files changed (1) hide show
  1. app.py +246 -61
app.py CHANGED
@@ -8,6 +8,7 @@ import gradio as gr
8
  from pathlib import Path
9
  import tempfile
10
  import shutil
 
11
 
12
  # Add the current directory to Python path
13
  sys.path.append(os.path.dirname(os.path.abspath(__file__)))
@@ -125,19 +126,83 @@ DEFAULT_CONFIG = {
125
  'log_light_power': 3.0
126
  }
127
 
128
- def process_garment(text_prompt, base_text_prompt, epochs, learning_rate, clip_weight, delta_clip_weight, progress=gr.Progress()):
129
  """
130
  Main function to process garment generation
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  """
132
  try:
133
  # Create a temporary output directory
134
  with tempfile.TemporaryDirectory() as temp_dir:
135
  # Update configuration
136
  config = DEFAULT_CONFIG.copy()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  config.update({
138
  'output_path': temp_dir,
139
- 'text_prompt': text_prompt,
140
- 'base_text_prompt': base_text_prompt,
141
  'epochs': int(epochs),
142
  'lr': float(learning_rate),
143
  'clip_weight': float(clip_weight),
@@ -160,14 +225,43 @@ def process_garment(text_prompt, base_text_prompt, epochs, learning_rate, clip_w
160
 
161
  progress(0.9, desc="Processing complete, preparing output...")
162
 
163
- # Look for output files
164
- output_files = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  for file_path in Path(temp_dir).rglob("*"):
166
- if file_path.is_file() and file_path.suffix.lower() in ['.obj', '.png', '.jpg', '.jpeg', '.gif', '.mp4']:
167
- output_files.append(str(file_path))
168
 
169
- if output_files:
170
- return output_files[0] if len(output_files) == 1 else output_files
 
 
 
 
 
171
  else:
172
  return "Processing completed but no output files found."
173
 
@@ -182,13 +276,15 @@ def create_interface():
182
  gr.Markdown("""
183
  # Garment3DGen: 3D Garment Stylization and Texture Generation
184
 
185
- This tool allows you to stylize 3D garments using text prompts. Upload a 3D mesh and describe the desired style to generate a new 3D garment.
 
186
 
187
  ## How to use:
188
- 1. Enter a text prompt describing the target style (e.g., "leather jacket with studs")
189
- 2. Enter a base text prompt describing the input mesh (e.g., "simple t-shirt")
190
- 3. Adjust the parameters as needed
191
- 4. Click "Generate" to start the process
 
192
 
193
  **Note:** Processing may take several minutes depending on the number of epochs.
194
  """)
@@ -197,76 +293,162 @@ def create_interface():
197
  with gr.Column(scale=1):
198
  gr.Markdown("### Input Parameters")
199
 
200
- text_prompt = gr.Textbox(
201
- label="Target Text Prompt",
202
- placeholder="e.g., leather jacket with studs, denim jacket with patches",
203
- value="leather jacket with studs"
 
 
204
  )
205
 
206
- base_text_prompt = gr.Textbox(
207
- label="Base Text Prompt",
208
- placeholder="e.g., simple t-shirt, basic long sleeve shirt",
209
- value="simple t-shirt"
210
- )
 
 
 
 
 
 
 
 
 
 
211
 
212
- epochs = gr.Slider(
213
- minimum=100,
214
- maximum=3000,
215
- value=1800,
216
- step=100,
217
- label="Number of Epochs",
218
- info="More epochs = better quality but longer processing time"
219
- )
 
 
 
 
 
220
 
221
- learning_rate = gr.Slider(
222
- minimum=0.0001,
223
- maximum=0.01,
224
- value=0.0025,
225
- step=0.0001,
226
- label="Learning Rate"
227
  )
228
 
229
- clip_weight = gr.Slider(
230
- minimum=0.1,
231
- maximum=10.0,
232
- value=2.5,
233
- step=0.1,
234
- label="CLIP Weight"
235
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
 
237
- delta_clip_weight = gr.Slider(
238
- minimum=0.1,
239
- maximum=20.0,
240
- value=5.0,
241
- step=0.1,
242
- label="Delta CLIP Weight"
243
- )
244
-
245
- generate_btn = gr.Button("Generate 3D Garment", variant="primary")
246
 
247
  with gr.Column(scale=1):
248
  gr.Markdown("### Output")
249
- output = gr.File(label="Generated 3D Garment")
250
- status = gr.Textbox(label="Status", interactive=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
 
252
  # Connect the button to the processing function
253
  generate_btn.click(
254
  fn=process_garment,
255
- inputs=[text_prompt, base_text_prompt, epochs, learning_rate, clip_weight, delta_clip_weight],
 
 
 
 
 
 
 
 
 
 
 
256
  outputs=[output]
257
  )
258
 
259
  gr.Markdown("""
260
  ## Tips for better results:
261
- - Be specific in your text prompts
 
 
262
  - Use descriptive terms for materials, colors, and styles
263
  - The base text prompt should accurately describe your input mesh
 
 
 
 
 
 
 
 
264
  - Higher epoch counts generally produce better results but take longer
 
265
  - Experiment with different CLIP weights for different effects
266
 
267
  ## Technical Details:
268
- This tool uses Neural Jacobian Fields and CLIP embeddings to deform and stylize 3D garment meshes.
269
- The process involves optimizing the mesh geometry and texture to match the target text description.
270
  """)
271
 
272
  return interface
@@ -278,5 +460,8 @@ if __name__ == "__main__":
278
  server_name="0.0.0.0",
279
  server_port=7860,
280
  share=False,
281
- debug=True
282
- )
 
 
 
 
8
  from pathlib import Path
9
  import tempfile
10
  import shutil
11
+ from PIL import Image
12
 
13
  # Add the current directory to Python path
14
  sys.path.append(os.path.dirname(os.path.abspath(__file__)))
 
126
  'log_light_power': 3.0
127
  }
128
 
129
+ def process_garment(input_type, text_prompt, base_text_prompt, target_image, base_image, custom_mesh, epochs, learning_rate, clip_weight, delta_clip_weight, progress=gr.Progress()):
130
  """
131
  Main function to process garment generation
132
+
133
+ Args:
134
+ input_type: Either "Text" or "Image" to determine the processing mode
135
+ text_prompt: Text description of target garment (for text mode)
136
+ base_text_prompt: Text description of base garment (for text mode)
137
+ target_image: Image of target garment style (for image mode)
138
+ base_image: Optional image of base garment (for image mode)
139
+ custom_mesh: Optional custom source mesh file (.obj)
140
+ epochs: Number of optimization epochs
141
+ learning_rate: Optimization learning rate
142
+ clip_weight: Weight for CLIP loss
143
+ delta_clip_weight: Weight for delta CLIP loss
144
+ progress: Gradio progress tracking object
145
  """
146
  try:
147
  # Create a temporary output directory
148
  with tempfile.TemporaryDirectory() as temp_dir:
149
  # Update configuration
150
  config = DEFAULT_CONFIG.copy()
151
+
152
+ # Set up input parameters based on mode
153
+ if input_type == "Image" and target_image is not None:
154
+ # Image-based processing
155
+ progress(0.05, desc="Preparing image inputs...")
156
+
157
+ # Save target image to temp directory
158
+ target_image_path = os.path.join(temp_dir, "target_image.jpg")
159
+ if isinstance(target_image, str):
160
+ shutil.copy(target_image, target_image_path)
161
+ else:
162
+ target_image.save(target_image_path)
163
+
164
+ # Save base image if provided, or use default
165
+ if base_image is not None:
166
+ base_image_path = os.path.join(temp_dir, "base_image.jpg")
167
+ if isinstance(base_image, str):
168
+ shutil.copy(base_image, base_image_path)
169
+ else:
170
+ base_image.save(base_image_path)
171
+ else:
172
+ # If no base image, use a placeholder or default
173
+ base_image_path = target_image_path
174
+
175
+ # Configure for image-based processing
176
+ config.update({
177
+ 'image_prompt': target_image_path,
178
+ 'base_image_prompt': base_image_path,
179
+ 'fashion_image': True,
180
+ 'fashion_text': False
181
+ })
182
+ else:
183
+ # Text-based processing
184
+ if not text_prompt or len(text_prompt.strip()) == 0:
185
+ return "Error: Text prompt is required for text-based generation."
186
+
187
+ if not base_text_prompt or len(base_text_prompt.strip()) == 0:
188
+ base_text_prompt = "simple t-shirt" # Default base prompt
189
+
190
+ config.update({
191
+ 'text_prompt': text_prompt,
192
+ 'base_text_prompt': base_text_prompt,
193
+ 'fashion_image': False,
194
+ 'fashion_text': True
195
+ })
196
+
197
+ # Handle custom mesh if provided
198
+ if custom_mesh is not None:
199
+ custom_mesh_path = os.path.join(temp_dir, "custom_mesh.obj")
200
+ shutil.copy(custom_mesh, custom_mesh_path)
201
+ config['mesh'] = custom_mesh_path
202
+
203
+ # Update optimization parameters
204
  config.update({
205
  'output_path': temp_dir,
 
 
206
  'epochs': int(epochs),
207
  'lr': float(learning_rate),
208
  'clip_weight': float(clip_weight),
 
225
 
226
  progress(0.9, desc="Processing complete, preparing output...")
227
 
228
+ # Look for output files, prioritize mesh files
229
+ obj_files = []
230
+ glb_files = []
231
+ image_files = []
232
+
233
+ # First check for mesh files in mesh_final directory (priority)
234
+ mesh_final_dir = Path(temp_dir) / "mesh_final"
235
+ if mesh_final_dir.exists():
236
+ for file_path in mesh_final_dir.rglob("*"):
237
+ if file_path.is_file():
238
+ if file_path.suffix.lower() == '.obj':
239
+ obj_files.append(str(file_path))
240
+ elif file_path.suffix.lower() == '.glb':
241
+ glb_files.append(str(file_path))
242
+
243
+ # Check other mesh directories
244
+ for mesh_dir in Path(temp_dir).glob("mesh_*"):
245
+ if mesh_dir.is_dir() and mesh_dir.name != 'mesh_final':
246
+ for file_path in mesh_dir.rglob("*"):
247
+ if file_path.is_file():
248
+ if file_path.suffix.lower() == '.obj':
249
+ obj_files.append(str(file_path))
250
+ elif file_path.suffix.lower() == '.glb':
251
+ glb_files.append(str(file_path))
252
+
253
+ # Collect image files for visualization
254
  for file_path in Path(temp_dir).rglob("*"):
255
+ if file_path.is_file() and file_path.suffix.lower() in ['.png', '.jpg', '.jpeg', '.gif', '.mp4']:
256
+ image_files.append(str(file_path))
257
 
258
+ # Prioritize output: GLB, OBJ, then images
259
+ if glb_files:
260
+ return glb_files[0] # Return first GLB file (best for web viewing)
261
+ elif obj_files:
262
+ return obj_files[0] # Return first OBJ file
263
+ elif image_files:
264
+ return image_files[0] # Return an image if no mesh was found
265
  else:
266
  return "Processing completed but no output files found."
267
 
 
276
  gr.Markdown("""
277
  # Garment3DGen: 3D Garment Stylization and Texture Generation
278
 
279
+ This tool allows you to stylize 3D garments using text prompts or images. Generate a new 3D garment mesh (.obj/.glb)
280
+ that can be used for virtual try-on applications.
281
 
282
  ## How to use:
283
+ 1. Choose your input method: Text Prompt or Image Upload
284
+ 2. Enter parameters or upload images based on your selection
285
+ 3. Optionally upload a custom mesh as your starting point
286
+ 4. Adjust the optimization parameters as needed
287
+ 5. Click "Generate" to start the process
288
 
289
  **Note:** Processing may take several minutes depending on the number of epochs.
290
  """)
 
293
  with gr.Column(scale=1):
294
  gr.Markdown("### Input Parameters")
295
 
296
+ # Input type selector
297
+ input_type = gr.Radio(
298
+ choices=["Text", "Image"],
299
+ value="Text",
300
+ label="Generation Method",
301
+ info="Choose whether to generate from text descriptions or from images"
302
  )
303
 
304
+ # Text-based inputs
305
+ with gr.Group() as text_input_group:
306
+ text_prompt = gr.Textbox(
307
+ label="Target Text Prompt",
308
+ placeholder="e.g., leather jacket with studs, denim jacket with patches",
309
+ value="leather jacket with studs",
310
+ info="Describe the garment style you want to create"
311
+ )
312
+
313
+ base_text_prompt = gr.Textbox(
314
+ label="Base Text Prompt",
315
+ placeholder="e.g., simple t-shirt, basic long sleeve shirt",
316
+ value="simple t-shirt",
317
+ info="Describe the starting garment style (default source mesh)"
318
+ )
319
 
320
+ # Image-based inputs
321
+ with gr.Group(visible=False) as image_input_group:
322
+ target_image = gr.Image(
323
+ label="Target Garment Image",
324
+ type="filepath",
325
+ info="Upload an image of the garment style you want to create"
326
+ )
327
+
328
+ base_image = gr.Image(
329
+ label="Base Garment Image (Optional)",
330
+ type="filepath",
331
+ info="Optionally upload an image of the starting garment style"
332
+ )
333
 
334
+ # Common inputs
335
+ custom_mesh = gr.File(
336
+ label="Custom Source Mesh (Optional)",
337
+ file_types=[".obj"],
338
+ info="Optionally upload your own .obj file as the source mesh"
 
339
  )
340
 
341
+ # Advanced parameters section
342
+ with gr.Accordion("Advanced Parameters", open=False):
343
+ epochs = gr.Slider(
344
+ minimum=100,
345
+ maximum=3000,
346
+ value=1800,
347
+ step=100,
348
+ label="Number of Epochs",
349
+ info="More epochs = better quality but longer processing time"
350
+ )
351
+
352
+ learning_rate = gr.Slider(
353
+ minimum=0.0001,
354
+ maximum=0.01,
355
+ value=0.0025,
356
+ step=0.0001,
357
+ label="Learning Rate",
358
+ info="Controls optimization speed and stability"
359
+ )
360
+
361
+ clip_weight = gr.Slider(
362
+ minimum=0.1,
363
+ maximum=10.0,
364
+ value=2.5,
365
+ step=0.1,
366
+ label="CLIP Weight",
367
+ info="Controls the influence of semantic features"
368
+ )
369
+
370
+ delta_clip_weight = gr.Slider(
371
+ minimum=0.1,
372
+ maximum=20.0,
373
+ value=5.0,
374
+ step=0.1,
375
+ label="Delta CLIP Weight",
376
+ info="Controls the strength of style transfer"
377
+ )
378
 
379
+ generate_btn = gr.Button("Generate 3D Garment", variant="primary", size="lg")
 
 
 
 
 
 
 
 
380
 
381
  with gr.Column(scale=1):
382
  gr.Markdown("### Output")
383
+ output = gr.File(label="Generated 3D Garment (.obj/.glb)")
384
+ status = gr.Textbox(label="Status", value="Ready to generate", interactive=False)
385
+
386
+ # Preview section
387
+ gr.Markdown("#### Mesh Preview")
388
+ gr.Markdown("""
389
+ The generated mesh can be:
390
+ - Imported into 3D software like Blender
391
+ - Used for virtual try-on applications
392
+ - Integrated with animation systems
393
+ - Used for digital fashion design
394
+
395
+ Download the .obj file to use the mesh with your preferred 3D tools.
396
+ """)
397
+
398
+ # Function to toggle between text and image inputs
399
+ def update_input_visibility(input_type):
400
+ if input_type == "Text":
401
+ return gr.Group.update(visible=True), gr.Group.update(visible=False)
402
+ else: # Image
403
+ return gr.Group.update(visible=False), gr.Group.update(visible=True)
404
+
405
+ # Set up the visibility toggle
406
+ input_type.change(
407
+ fn=update_input_visibility,
408
+ inputs=[input_type],
409
+ outputs=[text_input_group, image_input_group]
410
+ )
411
 
412
  # Connect the button to the processing function
413
  generate_btn.click(
414
  fn=process_garment,
415
+ inputs=[
416
+ input_type,
417
+ text_prompt,
418
+ base_text_prompt,
419
+ target_image,
420
+ base_image,
421
+ custom_mesh,
422
+ epochs,
423
+ learning_rate,
424
+ clip_weight,
425
+ delta_clip_weight
426
+ ],
427
  outputs=[output]
428
  )
429
 
430
  gr.Markdown("""
431
  ## Tips for better results:
432
+
433
+ ### Text Mode:
434
+ - Be specific in your text prompts (e.g., "red leather biker jacket with metal studs" is better than "jacket")
435
  - Use descriptive terms for materials, colors, and styles
436
  - The base text prompt should accurately describe your input mesh
437
+
438
+ ### Image Mode:
439
+ - Use clear, well-lit images of garments
440
+ - Front-facing or 3/4 view images work best
441
+ - Images should show the complete garment
442
+ - Higher quality images produce better results
443
+
444
+ ### General Tips:
445
  - Higher epoch counts generally produce better results but take longer
446
+ - Similar garment types work better (e.g., jacket→jacket works better than shirt→pants)
447
  - Experiment with different CLIP weights for different effects
448
 
449
  ## Technical Details:
450
+ This tool uses Neural Jacobian Fields and Fashion-CLIP embeddings to deform and stylize 3D garment meshes.
451
+ The process involves optimizing mesh geometry to match the target style while preserving garment structure.
452
  """)
453
 
454
  return interface
 
460
  server_name="0.0.0.0",
461
  server_port=7860,
462
  share=False,
463
+ debug=False,
464
+ max_threads=16, # Optimize thread usage for Hugging Face
465
+ show_error=True, # Show detailed errors for better debugging
466
+ favicon_path="asset_visualization/armor.gif" # Set a nice favicon
467
+ )