qbhf2 commited on
Commit
cc32783
·
1 Parent(s): 2ef8895

new file: GarmentCode/gradio_config.yml

Browse files
Files changed (2) hide show
  1. GarmentCode/gradio_config.yml +25 -0
  2. app.py +333 -178
GarmentCode/gradio_config.yml ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # config.yml
2
+
3
+ defaults:
4
+ pattern_spec: "assets/Patterns/shirt_mean_specification.json"
5
+ sim_config: "assets/Sim_props/default_sim_props.yaml"
6
+ body_config: "./assets/bodies/mean_female.yaml"
7
+ design_config: "./assets/design_params/t-shirt.yaml"
8
+ system_config: "system.json"
9
+
10
+ body_model_files:
11
+ neutral: "assets/bodies/mean_all.stl"
12
+ mean_female: "assets/bodies/mean_female.obj"
13
+ mean_male: "assets/bodies/mean_male.obj"
14
+ f_smpl: "assets/bodies/f_smpl_average_A40.stl"
15
+ m_smpl: "assets/bodies/m_smpl_average_A40.stl"
16
+ mean_T_pose: "assets/bodies/mean_all_tpose.stl"
17
+ custom_female: "utils/model/womanfree.obj"
18
+
19
+ assets_paths:
20
+ design_params: "assets/design_params/"
21
+ patterns: "assets/Patterns/"
22
+ sim_props: "assets/Sim_props/"
23
+ bodies: "assets/bodies/"
24
+ garment_programs: "assets/garment_programs/"
25
+ images: "assets/img/"
app.py CHANGED
@@ -3,67 +3,26 @@ import asyncio
3
  import os
4
  import subprocess
5
  import shutil
6
- import threading
7
- from concurrent.futures import ThreadPoolExecutor
8
  import logging
9
  import json
 
 
 
 
10
 
11
 
12
- logging.basicConfig(level=logging.INFO)
 
 
 
 
 
13
 
 
 
 
14
 
15
- iframe_html = """
16
- <iframe src="http://0.0.0.0:80" width="100%" height="500" style="border:none;"></iframe>
17
- """
18
- DEFAULT_PATTERN_SPEC = "GarmentCode/assets/Patterns/shirt_mean_specification.json"
19
- DEFAULT_SIM_CONFIG = "GarmentCode/assets/Sim_props/default_sim_props.yaml"
20
-
21
-
22
-
23
- async def run_simulation(data_path, config_path):
24
- proc = await asyncio.create_subprocess_exec(
25
- "python3", "GarmentCode/pattern_data_sim.py",
26
- "--data", data_path,
27
- "--config", config_path
28
- )
29
- await proc.wait() # дождаться завершения процесса
30
- return
31
-
32
- async def run_garment_sim(pattern_spec_file, sim_config_file):
33
- pattern_path = getattr(pattern_spec_file, 'name', pattern_spec_file) if pattern_spec_file else DEFAULT_PATTERN_SPEC
34
- config_path = getattr(sim_config_file, 'name', sim_config_file) if sim_config_file else DEFAULT_SIM_CONFIG
35
- if not pattern_path or not config_path:
36
- logging.critical(ValueError, "Не выбран файл спецификации паттерна или конфигурации симуляции.")
37
- proc = await asyncio.create_subprocess_exec(
38
- "python3", "GarmentCode/test_garment_sim.py",
39
- "-p", pattern_path,
40
- "-s", config_path,
41
- stdout=asyncio.subprocess.PIPE,
42
- stderr=asyncio.subprocess.PIPE
43
- )
44
- stdout, stderr = await proc.communicate()
45
- if proc.returncode != 0:
46
- print(stderr.decode())
47
- raise RuntimeError("Simulation failed")
48
- # Найти последнюю строку с JSON
49
- lines = stdout.decode().splitlines()
50
- for line in reversed(lines):
51
- try:
52
- result = json.loads(line)
53
- return gr.Files(result["result_dir"])
54
- except Exception:
55
- continue
56
- raise RuntimeError("Result path not found in output")
57
-
58
-
59
- async def run_fitting(data_path, config_path):
60
- proc = await asyncio.create_subprocess_exec(
61
- "python3", "GarmentCode/pattern_fitter.py",
62
- "--data", data_path,
63
- "--config", config_path
64
- )
65
- await proc.wait() # дождаться завершения процесса
66
- return
67
 
68
  def organize_images_into_structure(source_folder, new_folder):
69
  os.makedirs(new_folder, exist_ok=True)
@@ -76,36 +35,59 @@ def organize_images_into_structure(source_folder, new_folder):
76
  destination_file = os.path.join(subfolder_path, file_name)
77
  shutil.copy(source_file, destination_file)
78
 
79
- smpl_thread = None
80
- smpl_process = None
81
-
82
- def run_smpl():
83
- global smpl_process
84
- # Запускаем процесс и храним ссылку на него
85
- smpl_process = subprocess.Popen([
86
- "python3", "custom_utils/smpl_visualizer.py",
87
- "--model-path", "SMPL_FEMALE.npz"
88
- ])
89
- smpl_process.wait() # Ждём завершения процесса
90
-
91
- def stop_smpl():
92
- global smpl_process
93
- if smpl_process and smpl_process.poll() is None:
94
- smpl_process.terminate() # Мягко завершить
95
- try:
96
- smpl_process.wait(timeout=1)
97
- except subprocess.TimeoutExpired:
98
- smpl_process.kill() # Форсированно убить, если не завершился
99
- smpl_process = None
100
-
101
- def clear_render():
102
- global smpl_thread
103
- stop_smpl()
104
- if smpl_thread and smpl_thread.is_alive():
105
- smpl_thread.join()
106
- smpl_thread = threading.Thread(target=run_smpl, daemon=True)
107
- smpl_thread.start()
108
- return gr.skip()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
 
110
  def update_submenu(clothing_type):
111
  if clothing_type == "Top":
@@ -140,101 +122,274 @@ def update_submenu(clothing_type):
140
  )
141
 
142
 
143
- with gr.Blocks(title="3D Garment Generator", theme=gr.themes.Default(text_size="sm")) as demo:
144
- front_collar = gr.State()
145
- back_collar = gr.State()
146
-
147
- with gr.Row():
148
- # Левая колонка: рендер и кнопки
149
- with gr.Column(scale=3):
150
- viewer = gr.HTML(iframe_html, label="3D Рендер")
151
- sim_button = gr.Button("Запустить симуляцию",variant="primary",size="sm",
152
- inputs=[gr.State("GarmentCode/pattern_data_sim.py"),
153
- gr.State("GarmentCode/configs/pattern_data_sim.json")],
154
- )
155
- fit_button = gr.Button("Запустить фитинг",variant="primary",size="sm",
156
- inputs=[gr.State("GarmentCode/pattern_fitter.py"),
157
- gr.State("GarmentCode/configs/pattern_fitter.json")],
158
- )
159
- with gr.Row():
160
- save_render_btn = gr.Button("Сохранить рендер")
161
- save_obj_btn = gr.Button("Сохранить OBJ")
162
- clear_button = gr.Button("Очистить")
163
- zip_file = gr.File(label="Download Zip File")
164
-
165
- # Правая колонка: загрузки и параметры
166
- with gr.Column(scale=1):
167
- gr.Markdown("### Параметры генерации")
168
- with gr.Row():
169
- pattern_upload = gr.File(
170
- label="1. Лекала (JSON/SVG)",
171
- file_types=[".json", ".svg"],
172
- height=120
173
-
174
- )
175
- # body_upload = gr.File(
176
- # label="2. Тело (OBJ/GLB/GLTF/FBX)",
177
- # file_types=[".obj", ".glb", ".gltf", ".fbx"],
178
- # height=120
179
- # )
180
- with gr.Row():
181
- pattern_specs = gr.File(
182
- label="3. Спецификация паттерна (JSON/YAML)",
183
- file_types=[".json", ".yaml"],
184
- height=120
185
- )
186
- with gr.Row():
187
- sim_config = gr.File(
188
- label="4. Конфигурация симуляции (JSON/YAML)",
189
- file_types=[".json", ".yaml"],
190
- height=120
191
- )
192
- with gr.Accordion("5. Параметры генерации", open=True):
193
- clothing_type_dropdown = gr.Dropdown(
194
- label="Тип одежды",
195
- choices=["Top", "Down", "Full body"],
196
- value="Top",
197
- interactive=True
198
- )
199
- front_dropdown = gr.Dropdown(
200
- visible=False,
201
- label="Front Collar",
202
- choices=[],
203
- interactive=True
204
- )
205
- back_dropdown = gr.Dropdown(
206
- visible=False,
207
- label="Back Collar",
208
- choices=[],
209
- interactive=True
210
- )
211
- overall_length = gr.Slider(
212
- 1, 50, value=25, label="Длина одежды",
213
- info="Выберите значение от 1 до 50",
214
- interactive=True
215
- )
216
- clothing_type_dropdown.change(
217
- fn=update_submenu,
218
- inputs=clothing_type_dropdown,
219
- outputs=[front_dropdown, back_dropdown]
220
- )
221
- ## Button callbacks ##
222
- sim_button.click(
223
- fn=run_garment_sim,
224
- inputs=[pattern_specs, sim_config],
225
- outputs=viewer
226
  )
227
- fit_button.click(
228
- fn=run_fitting,
229
- inputs=[gr.State("GarmentCode/pattern_fitter.py"), gr.State("GarmentCode/configs/pattern_fitter.json")],
230
- outputs=viewer
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  )
232
- clear_button.click(
233
- fn=clear_render,
234
- outputs=viewer
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
 
237
  if __name__ == "__main__":
238
- smpl_thread = threading.Thread(target=run_smpl)
239
- smpl_thread.start()
240
- demo.launch(share=True)
 
3
  import os
4
  import subprocess
5
  import shutil
 
 
6
  import logging
7
  import json
8
+ from pathlib import Path
9
+ import yaml
10
+ import coloredlogs
11
+ import re
12
 
13
 
14
+ logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
15
+ coloredlogs.install(level='INFO', fmt='%(levelname)s: %(message)s',
16
+ level_styles={'info': {'color': 'green'},
17
+ 'error':{'color':'red'}
18
+ }
19
+ )
20
 
21
+ # === Загрузка конфига ===
22
+ with open("GarmentCode/gradio_config.yml", "r") as f:
23
+ config = yaml.safe_load(f)
24
 
25
+ # === Вспомогательные функции ===
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
  def organize_images_into_structure(source_folder, new_folder):
28
  os.makedirs(new_folder, exist_ok=True)
 
35
  destination_file = os.path.join(subfolder_path, file_name)
36
  shutil.copy(source_file, destination_file)
37
 
38
+
39
+ def update_body_model(selected_key):
40
+ return config['body_model_files'].get(selected_key, config['defaults']['body_config'])
41
+
42
+
43
+ def get_design_choices():
44
+ design_dir = config['assets_paths']['design_params'] # "assets/design_params/"
45
+ design_choices = []
46
+ for fname in os.listdir(design_dir):
47
+ if fname.endswith(".yaml"):
48
+ design_choices.append(os.path.splitext(fname)[0])
49
+ return design_choices
50
+
51
+ def get_sim_props_choices():
52
+ sim_props_dir=config['assets_paths']['sim_props']
53
+ sim_props_choices_yaml, sim_props_choices_json=[],[]
54
+ for fname in os.listdir(sim_props_dir):
55
+ if fname.endswith(".yaml"):
56
+ sim_props_choices_yaml.append(os.path.splitext(fname)[0])
57
+ elif fname.endswith(".json"):
58
+ sim_props_choices_json.append(os.path.splitext(fname)[0])
59
+ return sim_props_choices_yaml, sim_props_choices_json
60
+
61
+ def extract_dataset_path(stdout: str) -> str:
62
+ # Ищем строку с "Result saved to:"
63
+ match = re.search(r"Result saved to: (.+)", stdout)
64
+ if match:
65
+ path = match.group(1).strip()
66
+ # Убираем подкаталог default_body, если он есть в конце пути
67
+ if path.endswith('/default_body') or path.endswith('\\default_body'):
68
+ path = os.path.dirname(path)
69
+ return path
70
+ return None
71
+
72
+ def get_png_path(folder: str):
73
+ basename = os.path.basename(folder)
74
+ png_path = os.path.join(folder, f"{basename}_pattern.png")
75
+
76
+ if os.path.isfile(png_path):
77
+ logging.info(f"PNG FILE LOCATED AT {png_path}")
78
+ return png_path
79
+ return None
80
+
81
+
82
+ def zip_folder(folder_path: str) -> str:
83
+ folder_path_obj = Path(folder_path)
84
+ zip_path = str(folder_path_obj) + '.zip'
85
+ shutil.make_archive(str(folder_path_obj), 'zip', folder_path)
86
+ return zip_path
87
+
88
+ def show_button_if_both_uploaded(front_img, back_img):
89
+ return gr.update(visible=front_img is not None and back_img is not None)
90
+
91
 
92
  def update_submenu(clothing_type):
93
  if clothing_type == "Top":
 
122
  )
123
 
124
 
125
+ # === Симуляция/сэмплирование ===
126
+
127
+ # TODO: recreate fitting. Is it strictly necessary?
128
+
129
+ async def run_dataset_fitting(design_file: str, size: int, name: str, replicate: bool) -> str:
130
+ return
131
+
132
+ async def run_pattern_sampler(size: int, dataset_name: str, replicate: bool, pattern_config_name: str, body_file:str):
133
+ pattern_config_path = f"assets/design_params/{pattern_config_name}.yaml"
134
+ body_path = getattr(body_file, 'name', body_file) if body_file else "mean_female"
135
+
136
+ cmd = [
137
+ "python3", "GarmentCode/pattern_sampler.py",
138
+ "-s", str(size),
139
+ "--name", dataset_name,
140
+ "--pattern-config", pattern_config_path,
141
+ "--body", body_path
142
+ ]
143
+ if replicate:
144
+ cmd.append("--replicate")
145
+
146
+ proc = await asyncio.create_subprocess_exec(
147
+ *cmd,
148
+ stdout=asyncio.subprocess.PIPE,
149
+ stderr=asyncio.subprocess.PIPE
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  )
151
+ stdout, stderr = await proc.communicate()
152
+ logging.info(stdout.decode())
153
+ log = stdout.decode()
154
+ if proc.returncode != 0:
155
+ logging.error(f"Ошибка при генерации датасета:{stderr.decode()}")
156
+ return f"Ошибка при генерации датасета:\n{stderr.decode()}", gr.update(visible=False), None
157
+ dataset_path = (extract_dataset_path(log))
158
+ zip_folder_path = f"{zip_folder(dataset_path)}"
159
+ return stdout.decode(), gr.update(visible=True), dataset_path, zip_folder_path
160
+
161
+
162
+ async def run_pattern_data_sim(dataset_path: str, clothing_spec: str, default_body: bool = False):
163
+ dataset_path = dataset_path.replace("datasets/", "", 1)
164
+ clothing_spec=clothing_spec+".yaml"
165
+
166
+ cmd = [
167
+ "python3", "GarmentCode/pattern_data_sim.py",
168
+ "--data", dataset_path,
169
+ "-c", clothing_spec
170
+ ]
171
+ # Добавляем флаг только если default_body=True
172
+ if default_body:
173
+ cmd.append("--default_body")
174
+
175
+ proc = await asyncio.create_subprocess_exec(
176
+ *cmd,
177
+ stdout=asyncio.subprocess.PIPE,
178
+ stderr=asyncio.subprocess.PIPE
179
  )
180
+ stdout, stderr = await proc.communicate()
181
+ if proc.returncode != 0:
182
+ logging.error(f"Ошибка при симуляции: {stderr.decode()}")
183
+ return f"Ошибка при симуляции:\n{stderr.decode()}"
184
+ dataset_sim_path = "datasets_sim/" + dataset_path
185
+ zip_file_path = f"{zip_folder(dataset_sim_path)}"
186
+ return zip_file_path
187
+
188
+
189
+ async def simulation(pattern_spec_path:str, sim_props_path:str):
190
+ cmd = [
191
+ "python3", "GarmentCode/test_garment_sim.py",
192
+ "-p", pattern_spec_path,
193
+ "-s", sim_props_path,
194
+ ]
195
+
196
+
197
+ async def create_pattern(
198
+ body_config_file, # gr.File или None
199
+ design_config_file, # gr.File или None
200
+ body_to_use=None, # str или None
201
+ design_to_use=None # str или None
202
+ ):
203
+ # Если файл не выбран - используем дефолт из конфига
204
+ body_config_path = getattr(body_config_file, 'name', body_config_file) if body_config_file else config['defaults'][
205
+ 'body_config']
206
+ design_config_path = getattr(design_config_file, 'name', design_config_file) if design_config_file else \
207
+ config['defaults']['design_config']
208
+ logging.info("CREATION OF PATTERN FILES...")
209
+ cmd = [
210
+ "python3", "test_garmentcode.py",
211
+ "--body-config", body_config_path,
212
+ "--design-config", design_config_path,
213
+ ]
214
+ if body_to_use:
215
+ cmd += ["--body-to-use", body_to_use]
216
+ if design_to_use:
217
+ cmd += ["--design-to-use", design_to_use]
218
+
219
+ proc = await asyncio.create_subprocess_exec(
220
+ *cmd,
221
+ stdout=asyncio.subprocess.PIPE,
222
+ stderr=asyncio.subprocess.PIPE
223
  )
224
+ stdout, stderr = await proc.communicate()
225
+ if proc.returncode != 0:
226
+ logging.error(f"Pattern creation failed:\n{stderr.decode()}")
227
+ return f"Pattern creation failed:\n{stderr.decode()}"
228
+
229
+ result_str = stdout.decode()
230
+ folder = None
231
+ for line in result_str.splitlines():
232
+ if "saved to" in line:
233
+ folder = line.split("saved to")[-1].strip()
234
+ break
235
+ if not folder or not os.path.isdir(folder):
236
+ logging.error("Ошибка: не удалось найти папку с результатом.")
237
+ return "Ошибка: не удалось найти папку с результатом.", None, None
238
+
239
+ png_file = get_png_path(folder)
240
+ if not png_file:
241
+ logging.error("Ошибка: PNG-файл не найден.")
242
+ return "Ошибка: PNG-файл не найден.", None, None
243
+
244
+ zip_path = zip_folder(folder)
245
+ logging.info("PATTERN CREATION ENDED SUCCESSFULLY")
246
+ return result_str, zip_path, png_file
247
+
248
+
249
+ with gr.Blocks(title="3D Garment Generator", theme=gr.themes.Default(text_size="sm")) as demo:
250
+ with gr.Tabs():
251
+ with gr.Tab("Генератор одежды"):
252
+ front_collar = gr.State()
253
+ back_collar = gr.State()
254
+
255
+ with gr.Row():
256
+ with gr.Column(scale=1):
257
+ with gr.Accordion("Инференс",open=False):
258
+ front_img = gr.Image(label="Добавьте фотографию впереди")
259
+ back_img = gr.Image(label="Добавьте фотографию сзади")
260
+ create_pattern_btn = gr.Button("Создать паттерн", visible=False)
261
+
262
+ with gr.Accordion("1. Пресеты", open=False):
263
+ gr.Markdown("### Параметры генерации")
264
+ with gr.Accordion("Загрузить файлы", open=False):
265
+ body_config_file = gr.File(label="Body config (YAML)")
266
+ design_config_file = gr.File(label="Design config (YAML)")
267
+ system_config_file = gr.File(label="System config (JSON)")
268
+ body_to_use_dropdown = gr.Dropdown(
269
+ choices=list(config['body_model_files'].keys()),
270
+ label="Body key", value="mean_female")
271
+ design_to_use_dropdown = gr.Dropdown(
272
+ choices=["t-shirt"], label="Design key", value="t-shirt")
273
+ create_pattern_btn = gr.Button("Создать паттерн")
274
+ result_box = gr.Textbox(label="Результат")
275
+ image_result = gr.Image(label="Результат PNG")
276
+
277
+ with gr.Accordion("2. Параметры генерации", open=True):
278
+ clothing_type_dropdown = gr.Dropdown(
279
+ label="Тип одежды",
280
+ choices=["Top", "Down", "Full body"],
281
+ value="Top",
282
+ interactive=True
283
+ )
284
+ front_dropdown = gr.Dropdown(
285
+ visible=False,
286
+ label="Front Collar",
287
+ choices=[],
288
+ interactive=True
289
+ )
290
+ back_dropdown = gr.Dropdown(
291
+ visible=False,
292
+ label="Back Collar",
293
+ choices=[],
294
+ interactive=True
295
+ )
296
+ overall_length = gr.Slider(
297
+ 1, 50, value=25, label="Длина одежды",
298
+ info="Выберите значение от 1 до 50",
299
+ interactive=True
300
+ )
301
+ clothing_type_dropdown.change(
302
+ fn=update_submenu,
303
+ inputs=clothing_type_dropdown,
304
+ outputs=[front_dropdown, back_dropdown]
305
+ )
306
+ with gr.Accordion("3. Дополнительные инструменты", open=False):
307
+ with gr.Accordion("Генерация датасета", open=False):
308
+ dataset_size = gr.Slider(1, 5000, value=1, label="Размер датасета",
309
+ info="Выберите значение от 1 до 5000", interactive=True)
310
+ replicate_checkbox = gr.Checkbox(label="Репликация", value=False)
311
+ dataset_name_box = gr.Textbox(label="Название датасета", max_lines=1)
312
+
313
+ pattern_config_choices = get_design_choices()
314
+ pattern_config_file = gr.Radio(
315
+ label="Config",
316
+ choices=pattern_config_choices,
317
+ value=pattern_config_choices[0] if pattern_config_choices else None
318
+ )
319
+ body_file = gr.File(label="Body config (YAML)")
320
+ pattern_sampler_run_button = gr.Button("Сгенерировать паттерны", size="sm")
321
+ pattern_result_box = gr.Textbox(label="Лог генерации")
322
+ # sim_props_gen_choices_yaml = gr.Radio(label="Properties config",
323
+ # choices=get_sim_props_choices()[0],
324
+ # interactive=True,
325
+ # value=pattern_config_choices[
326
+ # 0] if pattern_config_choices else None
327
+ #
328
+ # )
329
+ sim_props_gen_choices_json = gr.Radio(label="Clothing config",
330
+ choices=get_sim_props_choices()[0],
331
+ interactive=True,
332
+ value=pattern_config_choices[
333
+ 0] if pattern_config_choices else None
334
+
335
+ )
336
+ dataset_path_box = gr.Textbox(visible=False)
337
+ default_body_checkbox = gr.Checkbox(label="default body",value=False)
338
+ dataset_gen_button = gr.Button("Генерация датасета",
339
+ variant="primary", visible=False)
340
+
341
+ ## Button callbacks ##
342
+ with gr.Column(scale=3):
343
+ viewer = gr.Model3D(
344
+ config['body_model_files']['custom_female'],
345
+ display_mode="solid", label="3D Рендер",
346
+ height=500, container=True, camera_position=(90, None, None),
347
+ interactive=False, clear_color=(0.85, 0.85, 0.85, 1)
348
+ )
349
+ fit_button = gr.Button("Запустить симуляцию", variant="primary", size="sm")
350
+ with gr.Row():
351
+ save_render_btn = gr.Button("Сохранить рендер")
352
+ save_obj_btn = gr.Button("Сохранить OBJ")
353
+ clear_button = gr.Button("Очистить")
354
+ zip_file = gr.File(label="Download Zip File", file_count="multiple",
355
+ file_types=[".zip"], height=50, interactive=False)
356
+
357
+ create_pattern_btn.click(
358
+ fn=create_pattern,
359
+ inputs=[body_config_file, design_config_file, body_to_use_dropdown, design_to_use_dropdown],
360
+ outputs=[result_box, zip_file, image_result]
361
+ )
362
+ body_to_use_dropdown.change(
363
+ fn=update_body_model,
364
+ inputs=body_to_use_dropdown,
365
+ outputs=viewer
366
+ )
367
+ pattern_sampler_run_button.click(
368
+ fn=run_pattern_sampler,
369
+ inputs=[dataset_size, dataset_name_box, replicate_checkbox, pattern_config_file,
370
+ body_file],
371
+ outputs=[pattern_result_box, dataset_gen_button, dataset_path_box, zip_file]
372
+ )
373
+ dataset_gen_button.click(
374
+ fn=run_pattern_data_sim,
375
+ inputs=[dataset_path_box, sim_props_gen_choices_json, default_body_checkbox],
376
+ outputs=[zip_file],
377
+ )
378
+ front_img.change(
379
+ fn=show_button_if_both_uploaded,
380
+ inputs=[front_img, back_img],
381
+ outputs=create_pattern_btn
382
+ )
383
+ back_img.change(
384
+ fn=show_button_if_both_uploaded,
385
+ inputs=[front_img, back_img],
386
+ outputs=create_pattern_btn
387
+ )
388
+
389
+ with gr.Tab("SewFormer"):
390
+ gr.Markdown("Photo to pattern")
391
+ with gr.Tab("Image to Pattern"):
392
+ gr.Markdown("JPG to PBR")
393
 
394
  if __name__ == "__main__":
395
+ demo.launch(share=True, server_port=7860, server_name="0.0.0.0")