gk2291 commited on
Commit
0698e90
Β·
verified Β·
1 Parent(s): 1fc4116

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +77 -120
app.py CHANGED
@@ -6,188 +6,145 @@ import logging
6
  import tempfile
7
  import os
8
 
 
 
 
9
  logging.basicConfig(level=logging.INFO)
10
  logger = logging.getLogger(__name__)
11
 
12
  vton_client = None
13
 
 
 
 
 
14
  def init_client():
15
  global vton_client
16
  try:
17
- logger.info("Connecting to IDM-VTON...")
18
- vton_client = Client("yisol/IDM-VTON")
19
- logger.info("βœ… Connected!")
 
20
  return True
21
  except Exception as e:
22
- logger.error(f"Failed: {e}")
 
23
  return False
24
 
 
25
  model_ready = init_client()
26
 
 
 
 
 
27
  @spaces.GPU(duration=180)
28
  def virtual_tryon(person_image, garment_image, progress=gr.Progress()):
29
  global vton_client
30
-
31
  try:
32
  if not person_image or not garment_image:
33
  raise gr.Error("Please upload both images!")
34
-
35
  if not vton_client:
36
  if not init_client():
37
- raise gr.Error("Service unavailable. Try again.")
38
-
39
- logger.info("Starting try-on...")
40
- progress(0.2, desc="Preparing...")
41
-
42
- person_img = person_image.convert('RGB')
43
- garment_img = garment_image.convert('RGB')
44
-
45
  person_tmp = tempfile.NamedTemporaryFile(delete=False, suffix='.jpg')
46
  garment_tmp = tempfile.NamedTemporaryFile(delete=False, suffix='.jpg')
47
-
48
- person_img.save(person_tmp.name, 'JPEG', quality=95)
49
- garment_img.save(garment_tmp.name, 'JPEG', quality=95)
50
-
51
- person_tmp.close()
52
- garment_tmp.close()
53
-
54
- progress(0.5, desc="Processing (60-90s)...")
55
-
56
  result = vton_client.predict(
57
  handle_file(person_tmp.name),
58
  handle_file(garment_tmp.name),
59
- "a garment",
60
  True,
61
  True,
62
  30,
63
  42,
64
  api_name="/tryon"
65
  )
66
-
67
- progress(0.9, desc="Getting result...")
68
-
69
  result_path = result[0] if isinstance(result, (tuple, list)) else result
70
  result_image = Image.open(result_path)
71
-
72
- try:
73
- os.unlink(person_tmp.name)
74
- os.unlink(garment_tmp.name)
75
- except:
76
- pass
77
-
78
- progress(1.0, desc="Done!")
79
- logger.info("βœ… Complete!")
80
-
81
  return result_image
82
-
83
  except Exception as e:
84
- logger.error(f"Error: {e}")
 
 
 
 
85
  raise gr.Error(f"Failed: {str(e)}")
86
 
87
- # UI with Gradio 5.x syntax
 
 
 
88
  with gr.Blocks(title="Mirro Virtual Try-On", theme=gr.themes.Soft()) as demo:
89
-
90
- gr.Markdown("# πŸ‘— Mirro Virtual Try-On\n### πŸ†“ Free AI-Powered Virtual Try-On")
91
-
92
  if model_ready:
93
- gr.Markdown("🟒 **Ready!** Upload images to start.")
94
  else:
95
- gr.Markdown("🟑 **Connecting...** Try in a moment.")
96
-
97
  with gr.Row():
98
  with gr.Column():
99
  gr.Markdown("### πŸ“Έ Upload Images")
100
- person_input = gr.Image(
101
- label="πŸ‘€ Person Photo",
102
- type="pil",
103
- sources=["upload", "webcam"]
104
- )
105
- garment_input = gr.Image(
106
- label="πŸ‘” Garment Photo",
107
- type="pil",
108
- sources=["upload", "webcam"]
109
- )
110
  btn = gr.Button("✨ Generate Try-On", variant="primary")
111
-
112
  with gr.Column():
113
  gr.Markdown("### 🎯 Result")
114
  output_image = gr.Image(label="Virtual Try-On Result", type="pil")
115
-
116
  with gr.Accordion("πŸ’‘ Tips for Best Results", open=False):
117
  gr.Markdown("""
118
- ### Person Photo:
119
- - Face forward, arms slightly away from body
120
- - Clear, well-lit photo
121
- - Plain background preferred
122
-
123
- ### Garment Photo:
124
- - Clear photo of garment (flat lay or on hanger)
125
- - Full garment visible
126
- - Good lighting
127
-
128
- ### Processing:
129
- - Takes 60-90 seconds
130
- - Realistic results (not overlay)
131
- - Preserves face and pose
132
  """)
133
-
134
- with gr.Accordion("πŸ“± iOS API Integration", open=False):
135
- gr.Markdown("""
136
- ## REST API Endpoint
137
- ```
138
- POST https://gk2291-mirro-app-server.hf.space/api/predict
139
- ```
140
-
141
- ### Request Format (JSON):
142
- ```json
143
- {
144
- "data": [
145
- "data:image/jpeg;base64,<person_base64>",
146
- "data:image/jpeg;base64,<garment_base64>"
147
- ]
148
- }
149
- ```
150
-
151
- ### Response Format (JSON):
152
- ```json
153
- {
154
- "data": ["data:image/png;base64,<result_base64>"]
155
- }
156
- ```
157
-
158
- ### Swift Example:
159
- ```swift
160
- let url = URL(string: "https://gk2291-mirro-app-server.hf.space/api/predict")!
161
- var request = URLRequest(url: url)
162
- request.httpMethod = "POST"
163
- request.setValue("application/json", forHTTPHeaderField: "Content-Type")
164
-
165
- let payload: [String: Any] = [
166
- "data": [personBase64, garmentBase64]
167
- ]
168
- request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
169
-
170
- URLSession.shared.dataTask(with: request) { data, response, error in
171
- // Handle response
172
- }.resume()
173
- ```
174
- """)
175
-
176
  btn.click(
177
  fn=virtual_tryon,
178
  inputs=[person_input, garment_input],
179
  outputs=output_image,
180
  api_name="predict"
181
  )
182
-
183
  gr.Markdown("""
184
  ---
185
- <div style="text-align: center; color: #666; padding: 20px;">
186
- <p>πŸ†“ 100% FREE | ⚑ Powered by IDM-VTON | 🎨 Production Quality</p>
187
- <p style="font-size: 0.9em;">Perfect for iOS App MVP</p>
188
  </div>
189
  """)
190
 
191
  if __name__ == "__main__":
192
  demo.queue(max_size=20)
193
- demo.launch(server_name="0.0.0.0", server_port=7860)
 
6
  import tempfile
7
  import os
8
 
9
+ # ==========================================================
10
+ # Setup
11
+ # ==========================================================
12
  logging.basicConfig(level=logging.INFO)
13
  logger = logging.getLogger(__name__)
14
 
15
  vton_client = None
16
 
17
+
18
+ # ==========================================================
19
+ # Init Remote Try-On Model (API Endpoint)
20
+ # ==========================================================
21
  def init_client():
22
  global vton_client
23
  try:
24
+ logger.info("πŸ”— Connecting to IDM-VTON API...")
25
+ # βœ… Use the maintained API Space (not model repo)
26
+ vton_client = Client("yisol-idm-vton-api.hf.space")
27
+ logger.info("βœ… Connected to yisol-idm-vton-api.hf.space")
28
  return True
29
  except Exception as e:
30
+ logger.error(f"❌ Connection failed: {e}")
31
+ vton_client = None
32
  return False
33
 
34
+
35
  model_ready = init_client()
36
 
37
+
38
+ # ==========================================================
39
+ # GPU Accelerated Try-On Function
40
+ # ==========================================================
41
  @spaces.GPU(duration=180)
42
  def virtual_tryon(person_image, garment_image, progress=gr.Progress()):
43
  global vton_client
44
+
45
  try:
46
  if not person_image or not garment_image:
47
  raise gr.Error("Please upload both images!")
48
+
49
  if not vton_client:
50
  if not init_client():
51
+ raise gr.Error("⚠️ Model API unavailable. Try again later.")
52
+
53
+ logger.info("🎯 Starting try-on pipeline...")
54
+ progress(0.2, desc="πŸ“Έ Preparing images...")
55
+
56
+ # Save temporary input files
 
 
57
  person_tmp = tempfile.NamedTemporaryFile(delete=False, suffix='.jpg')
58
  garment_tmp = tempfile.NamedTemporaryFile(delete=False, suffix='.jpg')
59
+
60
+ person_image.convert('RGB').save(person_tmp.name, 'JPEG', quality=95)
61
+ garment_image.convert('RGB').save(garment_tmp.name, 'JPEG', quality=95)
62
+
63
+ progress(0.5, desc="πŸͺ„ Running AI model (60-90s)...")
64
+
65
+ # Call remote API Space
 
 
66
  result = vton_client.predict(
67
  handle_file(person_tmp.name),
68
  handle_file(garment_tmp.name),
69
+ "universal garment", # πŸ‘— supports saree, kurta, dress, etc.
70
  True,
71
  True,
72
  30,
73
  42,
74
  api_name="/tryon"
75
  )
76
+
77
+ progress(0.9, desc="🎨 Generating result...")
78
+
79
  result_path = result[0] if isinstance(result, (tuple, list)) else result
80
  result_image = Image.open(result_path)
81
+
82
+ # Cleanup temp files
83
+ for tmp in [person_tmp.name, garment_tmp.name]:
84
+ try:
85
+ os.unlink(tmp)
86
+ except:
87
+ pass
88
+
89
+ progress(1.0, desc="βœ… Done!")
90
+ logger.info("βœ… Try-on complete!")
91
  return result_image
92
+
93
  except Exception as e:
94
+ if "ZeroGPU" in str(e):
95
+ raise gr.Error(
96
+ "⚠️ GPU quota exceeded. Log in to Hugging Face or retry later."
97
+ )
98
+ logger.error(f"❌ Error: {e}")
99
  raise gr.Error(f"Failed: {str(e)}")
100
 
101
+
102
+ # ==========================================================
103
+ # Gradio Interface
104
+ # ==========================================================
105
  with gr.Blocks(title="Mirro Virtual Try-On", theme=gr.themes.Soft()) as demo:
106
+
107
+ gr.Markdown("# πŸ‘— Mirro Virtual Try-On\n### πŸ†“ AI-Powered Outfit Fitting (All Garments)")
108
+
109
  if model_ready:
110
+ gr.Markdown("🟒 **Model ready!** Upload your photos below.")
111
  else:
112
+ gr.Markdown("🟑 **Connecting...** Try again in a moment.")
113
+
114
  with gr.Row():
115
  with gr.Column():
116
  gr.Markdown("### πŸ“Έ Upload Images")
117
+ person_input = gr.Image(label="πŸ‘€ Person Photo", type="pil", sources=["upload", "webcam"])
118
+ garment_input = gr.Image(label="πŸ‘” Garment Photo", type="pil", sources=["upload", "webcam"])
 
 
 
 
 
 
 
 
119
  btn = gr.Button("✨ Generate Try-On", variant="primary")
120
+
121
  with gr.Column():
122
  gr.Markdown("### 🎯 Result")
123
  output_image = gr.Image(label="Virtual Try-On Result", type="pil")
124
+
125
  with gr.Accordion("πŸ’‘ Tips for Best Results", open=False):
126
  gr.Markdown("""
127
+ - Clear, front-facing full-body person photo
128
+ - Plain background recommended
129
+ - Any garment type: saree, kurta, dress, jeans, jacket, etc.
130
+ - Processing takes ~60-90 seconds on ZeroGPU
 
 
 
 
 
 
 
 
 
 
131
  """)
132
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  btn.click(
134
  fn=virtual_tryon,
135
  inputs=[person_input, garment_input],
136
  outputs=output_image,
137
  api_name="predict"
138
  )
139
+
140
  gr.Markdown("""
141
  ---
142
+ <div style="text-align:center; color:#666; padding:15px;">
143
+ <p>πŸ†“ Powered by Hugging Face ZeroGPU + IDM-VTON API</p>
144
+ <p style="font-size:0.9em;">Supports all garment categories β€” production ready for iOS integration</p>
145
  </div>
146
  """)
147
 
148
  if __name__ == "__main__":
149
  demo.queue(max_size=20)
150
+ demo.launch(server_name="0.0.0.0", server_port=7860)