doosa.ganesh commited on
Commit
f7dc3cc
·
1 Parent(s): 79f180b
Files changed (2) hide show
  1. app.py +53 -115
  2. app_deprecated.py +318 -0
app.py CHANGED
@@ -1,3 +1,4 @@
 
1
  import os
2
  import json
3
  import gradio as gr
@@ -5,9 +6,20 @@ import argparse
5
  from huggingface_hub import snapshot_download
6
 
7
  HF_DATA_REPO = "doosaganesh/virtual-tryon-data"
8
-
9
  DATA_ROOT = None
10
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
  def get_data_root():
13
  global DATA_ROOT
@@ -19,7 +31,7 @@ def get_data_root():
19
  DATA_ROOT = snapshot_download(
20
  repo_id=HF_DATA_REPO,
21
  repo_type="dataset",
22
- token=os.environ["HF_TOKEN"],
23
  local_dir="/tmp/tryon-data",
24
  local_dir_use_symlinks=False
25
  )
@@ -34,7 +46,6 @@ def get_outfits(json_path):
34
  data = json.load(f)
35
 
36
  outfits = data.get('recommendedOutfits', [])
37
-
38
  json_dir = os.path.dirname(os.path.abspath(json_path))
39
  prod_to_ext = {}
40
 
@@ -105,18 +116,13 @@ def build_ui(site_id, person_image="source_models/female/asian/model_1.png"):
105
  DATA_ROOT = get_data_root()
106
 
107
  json_path = os.path.join(DATA_ROOT, "datasets", site_id, f"{site_id}_processed.json")
108
-
109
  results_dir = os.path.join(DATA_ROOT, "generated_tryon", site_id, "batch_results")
110
 
111
- if not os.path.exists(json_path):
112
- print(f"Warning: {json_path} not found")
113
-
114
  outfits = get_outfits(json_path)
115
 
116
  with gr.Blocks(title=f"Try-On Viewer: Site {site_id}") as demo:
117
 
118
  gr.Markdown(f"# Virtual Try-On Validator: Site {site_id}")
119
- gr.Markdown(f"Viewing results from `{results_dir}`")
120
 
121
  reviews_file = f"reviews_{site_id}.json"
122
 
@@ -144,15 +150,6 @@ def build_ui(site_id, person_image="source_models/female/asian/model_1.png"):
144
  next_btn = gr.Button("Next Outfit ➡️")
145
 
146
  with gr.Row():
147
- load_from_urls = gr.Checkbox(
148
- label="Load missing garment images from URLs (Internet)",
149
- value=True
150
- )
151
-
152
- refresh_btn = gr.Button("Refresh Generated Outputs", variant="secondary")
153
-
154
- with gr.Row():
155
-
156
  review_radio = gr.Radio(
157
  choices=["Pending", "✅ Good", "❌ Bad"],
158
  label="Review Status",
@@ -163,35 +160,23 @@ def build_ui(site_id, person_image="source_models/female/asian/model_1.png"):
163
 
164
  with gr.Column(scale=1):
165
 
166
- seed_info_md = gr.Markdown("### Input Garments\n**Seed Product:** N/A")
167
-
168
  garments_gallery = gr.Gallery(
169
  label="Outfit Pieces",
170
  columns=2,
171
  object_fit="contain"
172
  )
173
 
174
- gr.Markdown("### Input Model")
175
-
176
- person_img = gr.Image(
177
- value=person_image,
178
- label="Base Person",
179
- interactive=False
180
- )
181
-
182
  with gr.Column(scale=2):
183
 
184
- gr.Markdown("### Gemini Generated Result")
185
-
186
  result_img = gr.Image(
187
- label="Generated Output (Waiting...)",
188
  interactive=False
189
  )
190
 
191
- def update_view(index, load_urls):
192
 
193
  if index is None or not outfits:
194
- return None, None, "Pending", "### Input Garments\n**Seed Product:** N/A"
195
 
196
  o = outfits[index]
197
  outfit_id = o['id']
@@ -202,85 +187,22 @@ def build_ui(site_id, person_image="source_models/female/asian/model_1.png"):
202
  gallery_items = []
203
 
204
  for g in o['garments']:
205
-
206
- img_data = g['image']
207
-
208
- if not img_data and load_urls and g.get('url'):
209
-
210
- try:
211
- import requests as req
212
- from io import BytesIO
213
- from PIL import Image
214
-
215
- headers = {"User-Agent": "Mozilla/5.0"}
216
-
217
- resp = req.get(g['url'], timeout=5, headers=headers)
218
-
219
- if resp.status_code == 200:
220
- img_data = Image.open(BytesIO(resp.content))
221
-
222
- except Exception:
223
- pass
224
-
225
- if img_data:
226
- label = f"{g['type']}: {g['name']}\nProdID: {g.get('prod_id')} | ExtID: {g.get('ext_id')}"
227
- gallery_items.append((img_data, label))
228
 
229
  output_path = os.path.join(results_dir, f"{outfit_id}.jpg")
230
 
231
  if os.path.exists(output_path):
232
  res = output_path
233
- res_label = f"Generated Output ({outfit_id}.jpg)"
234
  else:
235
  res = None
236
- res_label = f"Not generated yet ({output_path} not found)"
237
 
238
- seed_text = f"### Input Garments\n**Seed Product:** ProdID: {o.get('seed_prod_id', 'N/A')} | ExtID: {o.get('seed_ext_id', 'N/A')}"
239
-
240
- return gallery_items, gr.update(value=res, label=res_label), current_review, gr.update(value=seed_text)
241
-
242
- def go_prev(index):
243
- if index is None:
244
- return 0
245
- return max(0, index - 1)
246
-
247
- def go_next(index):
248
- if index is None:
249
- return 0
250
- return min(len(outfits) - 1, index + 1)
251
-
252
- def on_review_change(index, status):
253
- if index is not None and outfits:
254
- outfit_id = outfits[index]['id']
255
- save_review(outfit_id, status)
256
 
257
  outfit_selector.change(
258
  fn=update_view,
259
- inputs=[outfit_selector, load_from_urls],
260
- outputs=[garments_gallery, result_img, review_radio, seed_info_md]
261
- )
262
-
263
- load_from_urls.change(
264
- fn=update_view,
265
- inputs=[outfit_selector, load_from_urls],
266
- outputs=[garments_gallery, result_img, review_radio, seed_info_md]
267
- )
268
-
269
- refresh_btn.click(
270
- fn=update_view,
271
- inputs=[outfit_selector, load_from_urls],
272
- outputs=[garments_gallery, result_img, review_radio, seed_info_md]
273
- )
274
-
275
- prev_btn.click(fn=go_prev, inputs=[outfit_selector], outputs=[outfit_selector])
276
- next_btn.click(fn=go_next, inputs=[outfit_selector], outputs=[outfit_selector])
277
-
278
- review_radio.change(fn=on_review_change, inputs=[outfit_selector, review_radio])
279
-
280
- demo.load(
281
- fn=update_view,
282
- inputs=[outfit_selector, load_from_urls],
283
- outputs=[garments_gallery, result_img, review_radio, seed_info_md]
284
  )
285
 
286
  return demo
@@ -289,30 +211,46 @@ def build_ui(site_id, person_image="source_models/female/asian/model_1.png"):
289
  if __name__ == "__main__":
290
 
291
  parser = argparse.ArgumentParser(description="Virtual Try-On UI Viewer")
292
-
293
  parser.add_argument("--site-id", default="1415")
294
  parser.add_argument("--person", default="source_models/female/asian/model_1.png")
295
  parser.add_argument("--port", type=int, default=7860)
296
- parser.add_argument("--share", action="store_true")
297
- parser.add_argument("--username")
298
- parser.add_argument("--password")
299
 
300
  args = parser.parse_args()
301
 
302
- auth = None
303
 
304
- if args.username and args.password:
305
- auth = (args.username, args.password)
306
- print(f"Authentication enabled for user: {args.username}")
307
 
308
- print(f"Starting Viewer for Site: {args.site_id}")
309
 
310
- demo = build_ui(site_id=args.site_id, person_image=args.person)
311
 
312
- DATA_ROOT = get_data_root()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
 
314
  demo.launch(
315
- server_name="0.0.0.0",
316
- server_port=args.port,
317
- auth=auth
318
- )
 
1
+
2
  import os
3
  import json
4
  import gradio as gr
 
6
  from huggingface_hub import snapshot_download
7
 
8
  HF_DATA_REPO = "doosaganesh/virtual-tryon-data"
 
9
  DATA_ROOT = None
10
 
11
+ # -----------------------------
12
+ # Simple user database from Space secrets
13
+ # -----------------------------
14
+ VALID_USERS = {
15
+ os.getenv("APP_USERNAME"): os.getenv("APP_PASSWORD")
16
+ }
17
+
18
+ def check_login(username, password):
19
+ if username in VALID_USERS and VALID_USERS[username] == password:
20
+ return True
21
+ return False
22
+
23
 
24
  def get_data_root():
25
  global DATA_ROOT
 
31
  DATA_ROOT = snapshot_download(
32
  repo_id=HF_DATA_REPO,
33
  repo_type="dataset",
34
+ token=os.environ.get("HF_TOKEN"),
35
  local_dir="/tmp/tryon-data",
36
  local_dir_use_symlinks=False
37
  )
 
46
  data = json.load(f)
47
 
48
  outfits = data.get('recommendedOutfits', [])
 
49
  json_dir = os.path.dirname(os.path.abspath(json_path))
50
  prod_to_ext = {}
51
 
 
116
  DATA_ROOT = get_data_root()
117
 
118
  json_path = os.path.join(DATA_ROOT, "datasets", site_id, f"{site_id}_processed.json")
 
119
  results_dir = os.path.join(DATA_ROOT, "generated_tryon", site_id, "batch_results")
120
 
 
 
 
121
  outfits = get_outfits(json_path)
122
 
123
  with gr.Blocks(title=f"Try-On Viewer: Site {site_id}") as demo:
124
 
125
  gr.Markdown(f"# Virtual Try-On Validator: Site {site_id}")
 
126
 
127
  reviews_file = f"reviews_{site_id}.json"
128
 
 
150
  next_btn = gr.Button("Next Outfit ➡️")
151
 
152
  with gr.Row():
 
 
 
 
 
 
 
 
 
153
  review_radio = gr.Radio(
154
  choices=["Pending", "✅ Good", "❌ Bad"],
155
  label="Review Status",
 
160
 
161
  with gr.Column(scale=1):
162
 
 
 
163
  garments_gallery = gr.Gallery(
164
  label="Outfit Pieces",
165
  columns=2,
166
  object_fit="contain"
167
  )
168
 
 
 
 
 
 
 
 
 
169
  with gr.Column(scale=2):
170
 
 
 
171
  result_img = gr.Image(
172
+ label="Generated Output",
173
  interactive=False
174
  )
175
 
176
+ def update_view(index):
177
 
178
  if index is None or not outfits:
179
+ return None, None, "Pending"
180
 
181
  o = outfits[index]
182
  outfit_id = o['id']
 
187
  gallery_items = []
188
 
189
  for g in o['garments']:
190
+ if g['image']:
191
+ gallery_items.append((g['image'], g['name']))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
 
193
  output_path = os.path.join(results_dir, f"{outfit_id}.jpg")
194
 
195
  if os.path.exists(output_path):
196
  res = output_path
 
197
  else:
198
  res = None
 
199
 
200
+ return gallery_items, res, current_review
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
 
202
  outfit_selector.change(
203
  fn=update_view,
204
+ inputs=[outfit_selector],
205
+ outputs=[garments_gallery, result_img, review_radio]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  )
207
 
208
  return demo
 
211
  if __name__ == "__main__":
212
 
213
  parser = argparse.ArgumentParser(description="Virtual Try-On UI Viewer")
 
214
  parser.add_argument("--site-id", default="1415")
215
  parser.add_argument("--person", default="source_models/female/asian/model_1.png")
216
  parser.add_argument("--port", type=int, default=7860)
 
 
 
217
 
218
  args = parser.parse_args()
219
 
220
+ DATA_ROOT = get_data_root()
221
 
222
+ viewer = build_ui(site_id=args.site_id, person_image=args.person)
 
 
223
 
224
+ with gr.Blocks(title="Virtual Try-On Login") as demo:
225
 
226
+ login_state = gr.State(False)
227
 
228
+ with gr.Column(visible=True) as login_panel:
229
+
230
+ gr.Markdown("# 🔐 Login Required")
231
+
232
+ username = gr.Textbox(label="Username")
233
+ password = gr.Textbox(label="Password", type="password")
234
+
235
+ login_btn = gr.Button("Login")
236
+ login_status = gr.Markdown()
237
+
238
+ with gr.Column(visible=False) as app_panel:
239
+ viewer.render()
240
+
241
+ def login(user, pwd):
242
+ if check_login(user, pwd):
243
+ return True, gr.update(visible=False), gr.update(visible=True), "✅ Login successful"
244
+ else:
245
+ return False, gr.update(visible=True), gr.update(visible=False), "❌ Invalid credentials"
246
+
247
+ login_btn.click(
248
+ login,
249
+ inputs=[username, password],
250
+ outputs=[login_state, login_panel, app_panel, login_status]
251
+ )
252
 
253
  demo.launch(
254
+ server_name="0.0.0.0",
255
+ server_port=args.port
256
+ )
 
app_deprecated.py ADDED
@@ -0,0 +1,318 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import gradio as gr
4
+ import argparse
5
+ from huggingface_hub import snapshot_download
6
+
7
+ HF_DATA_REPO = "doosaganesh/virtual-tryon-data"
8
+
9
+ DATA_ROOT = None
10
+
11
+
12
+ def get_data_root():
13
+ global DATA_ROOT
14
+
15
+ if DATA_ROOT is None:
16
+
17
+ print("Downloading dataset from Hugging Face...")
18
+
19
+ DATA_ROOT = snapshot_download(
20
+ repo_id=HF_DATA_REPO,
21
+ repo_type="dataset",
22
+ token=os.environ["HF_TOKEN"],
23
+ local_dir="/tmp/tryon-data",
24
+ local_dir_use_symlinks=False
25
+ )
26
+
27
+ print("Dataset downloaded to:", DATA_ROOT)
28
+
29
+ return DATA_ROOT
30
+
31
+
32
+ def get_outfits(json_path):
33
+ with open(json_path, 'r') as f:
34
+ data = json.load(f)
35
+
36
+ outfits = data.get('recommendedOutfits', [])
37
+
38
+ json_dir = os.path.dirname(os.path.abspath(json_path))
39
+ prod_to_ext = {}
40
+
41
+ for fname in os.listdir(json_dir):
42
+ if fname.endswith('products.txt'):
43
+ with open(os.path.join(json_dir, fname), 'r', encoding='utf-8') as pf:
44
+ first_line = pf.readline().strip()
45
+ if not first_line:
46
+ continue
47
+
48
+ delimiter = '\x01' if '\x01' in first_line else '\t'
49
+ header = first_line.split(delimiter)
50
+
51
+ if 'id' in header and 'external_id' in header:
52
+ id_idx = header.index('id')
53
+ ext_idx = header.index('external_id')
54
+
55
+ for line in pf:
56
+ parts = line.strip().split(delimiter)
57
+ if len(parts) > max(id_idx, ext_idx):
58
+ prod_to_ext[str(parts[id_idx])] = str(parts[ext_idx])
59
+ break
60
+
61
+ outfits_data = []
62
+
63
+ for idx, o in enumerate(outfits):
64
+
65
+ outfit_id = o.get('outfitId', o.get('styleId', idx))
66
+ style_name = o.get('styleName', 'Unknown Style')
67
+
68
+ garment_data = []
69
+
70
+ for g in o.get('garments', []):
71
+
72
+ prod_id = str(g.get('prodId', ''))
73
+ ext_id = prod_to_ext.get(prod_id, prod_id)
74
+
75
+ img_path = os.path.join(json_dir, 'images', f"{ext_id}.jpg")
76
+
77
+ if not os.path.exists(img_path):
78
+ img_path = os.path.join(json_dir, 'images', f"{prod_id}.jpg")
79
+
80
+ garment_data.append({
81
+ 'type': g.get('tryonType', 'unknown'),
82
+ 'name': g.get('prodName', 'Unknown'),
83
+ 'image': img_path if os.path.exists(img_path) else None,
84
+ 'url': g.get('imageUrl'),
85
+ 'prod_id': prod_id,
86
+ 'ext_id': ext_id
87
+ })
88
+
89
+ seed_prod_id = str(o.get('seedProduct', ''))
90
+ seed_ext_id = prod_to_ext.get(seed_prod_id, seed_prod_id) if seed_prod_id else 'N/A'
91
+
92
+ outfits_data.append({
93
+ 'id': f"outfit-{outfit_id}",
94
+ 'name': style_name,
95
+ 'garments': garment_data,
96
+ 'seed_prod_id': seed_prod_id,
97
+ 'seed_ext_id': seed_ext_id
98
+ })
99
+
100
+ return outfits_data
101
+
102
+
103
+ def build_ui(site_id, person_image="source_models/female/asian/model_1.png"):
104
+
105
+ DATA_ROOT = get_data_root()
106
+
107
+ json_path = os.path.join(DATA_ROOT, "datasets", site_id, f"{site_id}_processed.json")
108
+
109
+ results_dir = os.path.join(DATA_ROOT, "generated_tryon", site_id, "batch_results")
110
+
111
+ if not os.path.exists(json_path):
112
+ print(f"Warning: {json_path} not found")
113
+
114
+ outfits = get_outfits(json_path)
115
+
116
+ with gr.Blocks(title=f"Try-On Viewer: Site {site_id}") as demo:
117
+
118
+ gr.Markdown(f"# Virtual Try-On Validator: Site {site_id}")
119
+ gr.Markdown(f"Viewing results from `{results_dir}`")
120
+
121
+ reviews_file = f"reviews_{site_id}.json"
122
+
123
+ def load_reviews():
124
+ if os.path.exists(reviews_file):
125
+ with open(reviews_file, 'r') as f:
126
+ return json.load(f)
127
+ return {}
128
+
129
+ def save_review(outfit_id, status):
130
+ reviews = load_reviews()
131
+ reviews[outfit_id] = status
132
+ with open(reviews_file, 'w') as f:
133
+ json.dump(reviews, f, indent=2)
134
+
135
+ with gr.Row():
136
+ prev_btn = gr.Button("⬅️ Previous Outfit")
137
+
138
+ outfit_selector = gr.Dropdown(
139
+ choices=[(f"{o['id']} ({o['name']})", i) for i, o in enumerate(outfits)],
140
+ label="Select Outfit",
141
+ value=0 if outfits else None
142
+ )
143
+
144
+ next_btn = gr.Button("Next Outfit ➡️")
145
+
146
+ with gr.Row():
147
+ load_from_urls = gr.Checkbox(
148
+ label="Load missing garment images from URLs (Internet)",
149
+ value=True
150
+ )
151
+
152
+ refresh_btn = gr.Button("Refresh Generated Outputs", variant="secondary")
153
+
154
+ with gr.Row():
155
+
156
+ review_radio = gr.Radio(
157
+ choices=["Pending", "✅ Good", "❌ Bad"],
158
+ label="Review Status",
159
+ value="Pending"
160
+ )
161
+
162
+ with gr.Row():
163
+
164
+ with gr.Column(scale=1):
165
+
166
+ seed_info_md = gr.Markdown("### Input Garments\n**Seed Product:** N/A")
167
+
168
+ garments_gallery = gr.Gallery(
169
+ label="Outfit Pieces",
170
+ columns=2,
171
+ object_fit="contain"
172
+ )
173
+
174
+ gr.Markdown("### Input Model")
175
+
176
+ person_img = gr.Image(
177
+ value=person_image,
178
+ label="Base Person",
179
+ interactive=False
180
+ )
181
+
182
+ with gr.Column(scale=2):
183
+
184
+ gr.Markdown("### Gemini Generated Result")
185
+
186
+ result_img = gr.Image(
187
+ label="Generated Output (Waiting...)",
188
+ interactive=False
189
+ )
190
+
191
+ def update_view(index, load_urls):
192
+
193
+ if index is None or not outfits:
194
+ return None, None, "Pending", "### Input Garments\n**Seed Product:** N/A"
195
+
196
+ o = outfits[index]
197
+ outfit_id = o['id']
198
+
199
+ reviews = load_reviews()
200
+ current_review = reviews.get(outfit_id, "Pending")
201
+
202
+ gallery_items = []
203
+
204
+ for g in o['garments']:
205
+
206
+ img_data = g['image']
207
+
208
+ if not img_data and load_urls and g.get('url'):
209
+
210
+ try:
211
+ import requests as req
212
+ from io import BytesIO
213
+ from PIL import Image
214
+
215
+ headers = {"User-Agent": "Mozilla/5.0"}
216
+
217
+ resp = req.get(g['url'], timeout=5, headers=headers)
218
+
219
+ if resp.status_code == 200:
220
+ img_data = Image.open(BytesIO(resp.content))
221
+
222
+ except Exception:
223
+ pass
224
+
225
+ if img_data:
226
+ label = f"{g['type']}: {g['name']}\nProdID: {g.get('prod_id')} | ExtID: {g.get('ext_id')}"
227
+ gallery_items.append((img_data, label))
228
+
229
+ output_path = os.path.join(results_dir, f"{outfit_id}.jpg")
230
+
231
+ if os.path.exists(output_path):
232
+ res = output_path
233
+ res_label = f"Generated Output ({outfit_id}.jpg)"
234
+ else:
235
+ res = None
236
+ res_label = f"Not generated yet ({output_path} not found)"
237
+
238
+ seed_text = f"### Input Garments\n**Seed Product:** ProdID: {o.get('seed_prod_id', 'N/A')} | ExtID: {o.get('seed_ext_id', 'N/A')}"
239
+
240
+ return gallery_items, gr.update(value=res, label=res_label), current_review, gr.update(value=seed_text)
241
+
242
+ def go_prev(index):
243
+ if index is None:
244
+ return 0
245
+ return max(0, index - 1)
246
+
247
+ def go_next(index):
248
+ if index is None:
249
+ return 0
250
+ return min(len(outfits) - 1, index + 1)
251
+
252
+ def on_review_change(index, status):
253
+ if index is not None and outfits:
254
+ outfit_id = outfits[index]['id']
255
+ save_review(outfit_id, status)
256
+
257
+ outfit_selector.change(
258
+ fn=update_view,
259
+ inputs=[outfit_selector, load_from_urls],
260
+ outputs=[garments_gallery, result_img, review_radio, seed_info_md]
261
+ )
262
+
263
+ load_from_urls.change(
264
+ fn=update_view,
265
+ inputs=[outfit_selector, load_from_urls],
266
+ outputs=[garments_gallery, result_img, review_radio, seed_info_md]
267
+ )
268
+
269
+ refresh_btn.click(
270
+ fn=update_view,
271
+ inputs=[outfit_selector, load_from_urls],
272
+ outputs=[garments_gallery, result_img, review_radio, seed_info_md]
273
+ )
274
+
275
+ prev_btn.click(fn=go_prev, inputs=[outfit_selector], outputs=[outfit_selector])
276
+ next_btn.click(fn=go_next, inputs=[outfit_selector], outputs=[outfit_selector])
277
+
278
+ review_radio.change(fn=on_review_change, inputs=[outfit_selector, review_radio])
279
+
280
+ demo.load(
281
+ fn=update_view,
282
+ inputs=[outfit_selector, load_from_urls],
283
+ outputs=[garments_gallery, result_img, review_radio, seed_info_md]
284
+ )
285
+
286
+ return demo
287
+
288
+
289
+ if __name__ == "__main__":
290
+
291
+ parser = argparse.ArgumentParser(description="Virtual Try-On UI Viewer")
292
+
293
+ parser.add_argument("--site-id", default="1415")
294
+ parser.add_argument("--person", default="source_models/female/asian/model_1.png")
295
+ parser.add_argument("--port", type=int, default=7860)
296
+ parser.add_argument("--share", action="store_true")
297
+ parser.add_argument("--username")
298
+ parser.add_argument("--password")
299
+
300
+ args = parser.parse_args()
301
+
302
+ auth = None
303
+
304
+ if args.username and args.password:
305
+ auth = (args.username, args.password)
306
+ print(f"Authentication enabled for user: {args.username}")
307
+
308
+ print(f"Starting Viewer for Site: {args.site_id}")
309
+
310
+ demo = build_ui(site_id=args.site_id, person_image=args.person)
311
+
312
+ DATA_ROOT = get_data_root()
313
+
314
+ demo.launch(
315
+ server_name="0.0.0.0",
316
+ server_port=args.port,
317
+ auth=auth
318
+ )