Update app.py
Browse files
app.py
CHANGED
|
@@ -89,10 +89,10 @@ CUSTOM_LABELS = {
|
|
| 89 |
"zh": "自定义(用中文输入)",
|
| 90 |
}
|
| 91 |
|
| 92 |
-
# i18n 辞書
|
| 93 |
I18N = {
|
| 94 |
"title": {
|
| 95 |
-
"en": "Camera Work
|
| 96 |
"ja": "カメラワーク",
|
| 97 |
"zh": "镜头控制",
|
| 98 |
},
|
|
@@ -103,14 +103,14 @@ I18N = {
|
|
| 103 |
},
|
| 104 |
"input_image": {"en": "Input image", "ja": "入力画像", "zh": "输入图像"},
|
| 105 |
"dropdown_label": {
|
| 106 |
-
"en": "Camera work
|
| 107 |
-
"ja": "カメラワーク
|
| 108 |
-
"zh": "镜头操作
|
| 109 |
},
|
| 110 |
"custom_cn_label": {
|
| 111 |
-
"en": "Custom Chinese
|
| 112 |
-
"ja": "自由入力の
|
| 113 |
-
"zh": "自定义
|
| 114 |
},
|
| 115 |
"custom_cn_ph": {
|
| 116 |
"en": "e.g., 将镜头转为斜俯视 并 拉远镜头",
|
|
@@ -118,14 +118,14 @@ I18N = {
|
|
| 118 |
"zh": "例如:将镜头转为斜俯视 并 拉远镜头",
|
| 119 |
},
|
| 120 |
"extra_label": {
|
| 121 |
-
"en": "Extra prompt (optional, appended at end)",
|
| 122 |
-
"ja": "追加プロンプト(任意・末尾に付加)",
|
| 123 |
-
"zh": "附加提示词(可选,追加在末尾)",
|
| 124 |
},
|
| 125 |
"extra_ph": {
|
| 126 |
-
"en": "e.g.,
|
| 127 |
-
"ja": "例:
|
| 128 |
-
"zh": "例如:
|
| 129 |
},
|
| 130 |
"accordion": {"en": "Show advanced settings", "ja": "詳細設定を開く", "zh": "展开高级设置"},
|
| 131 |
"seed": {"en": "Seed", "ja": "Seed", "zh": "Seed"},
|
|
@@ -133,23 +133,12 @@ I18N = {
|
|
| 133 |
"tgs": {"en": "True guidance scale", "ja": "True guidance scale", "zh": "True guidance scale"},
|
| 134 |
"steps": {"en": "Steps", "ja": "生成ステップ数", "zh": "生成步数"},
|
| 135 |
"run": {"en": "Generate", "ja": "生成", "zh": "生成"},
|
| 136 |
-
"sel_cn": {
|
| 137 |
-
"en": "Selected camera prompt (to be sent, Chinese)",
|
| 138 |
-
"ja": "選択中のカメラプロンプト(送信対象・中国語)",
|
| 139 |
-
"zh": "所选镜头提示(发送内容,中文)",
|
| 140 |
-
},
|
| 141 |
-
"final_prev": {
|
| 142 |
-
"en": "Final prompt to be sent (Chinese + extra)",
|
| 143 |
-
"ja": "最終的に送信されるプロンプト(中国語+追記)",
|
| 144 |
-
"zh": "最终发送的提示(中文+附加)",
|
| 145 |
-
},
|
| 146 |
"output": {"en": "Output image", "ja": "出力画像", "zh": "输出图像"},
|
| 147 |
"status": {"en": "Status", "ja": "ステータス", "zh": "状态"},
|
| 148 |
-
"sent_hdr": {"en": "**Prompt sent (for reference)**", "ja": "**送信プロンプト(確認用)**", "zh": "**已发送提示(供参考)**"},
|
| 149 |
"status_ok": {
|
| 150 |
-
"en": "
|
| 151 |
-
"ja": "
|
| 152 |
-
"zh": "
|
| 153 |
},
|
| 154 |
"err_no_img": {
|
| 155 |
"en": "Error: Please upload an input image.",
|
|
@@ -157,9 +146,9 @@ I18N = {
|
|
| 157 |
"zh": "错误:请先上传输入图像。",
|
| 158 |
},
|
| 159 |
"err_no_custom": {
|
| 160 |
-
"en": "Error: Please enter a custom
|
| 161 |
-
"ja": "エラー: 自由入力の
|
| 162 |
-
"zh": "错误:请输入自定义
|
| 163 |
},
|
| 164 |
"lang_label": {"en": "UI Language", "ja": "UI言語", "zh": "界面语言"},
|
| 165 |
}
|
|
@@ -168,13 +157,13 @@ def t(key, lang):
|
|
| 168 |
return I18N[key][lang]
|
| 169 |
|
| 170 |
def build_dropdown_choices(lang):
|
| 171 |
-
#
|
| 172 |
if lang not in ("en", "ja", "zh"):
|
| 173 |
lang = "en"
|
| 174 |
ch = []
|
| 175 |
for item in CAMERA_OPTIONS:
|
| 176 |
-
label =
|
| 177 |
-
ch.append((label, item["cn"]))
|
| 178 |
ch.append((CUSTOM_LABELS[lang], CUSTOM_OPTION_VALUE))
|
| 179 |
return ch
|
| 180 |
|
|
@@ -212,7 +201,7 @@ def generate_from_dropdown(
|
|
| 212 |
seed = random.randint(0, MAX_SEED)
|
| 213 |
|
| 214 |
if image is None:
|
| 215 |
-
return None, t("err_no_img", lang)
|
| 216 |
|
| 217 |
if isinstance(image, Image.Image):
|
| 218 |
input_image = image.convert("RGB")
|
|
@@ -224,7 +213,7 @@ def generate_from_dropdown(
|
|
| 224 |
if dropdown_value_cn == CUSTOM_OPTION_VALUE:
|
| 225 |
base_cn = (custom_cn or "").strip()
|
| 226 |
if not base_cn:
|
| 227 |
-
return None, t("err_no_custom", lang)
|
| 228 |
else:
|
| 229 |
base_cn = dropdown_value_cn or CAMERA_OPTIONS[0]["cn"]
|
| 230 |
|
|
@@ -234,7 +223,7 @@ def generate_from_dropdown(
|
|
| 234 |
out = generate_single_view(pil_images, final_prompt, seed, num_inference_steps, true_guidance_scale)
|
| 235 |
progress(1.0, desc="Done" if lang=="en" else ("完了" if lang=="ja" else "完成"))
|
| 236 |
|
| 237 |
-
return out, t("status_ok", lang)
|
| 238 |
|
| 239 |
# --- UI ---
|
| 240 |
css = """
|
|
@@ -289,7 +278,7 @@ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
|
|
| 289 |
dropdown = gr.Dropdown(
|
| 290 |
label=I18N["dropdown_label"]["en"],
|
| 291 |
choices=build_dropdown_choices("en"),
|
| 292 |
-
value=CAMERA_OPTIONS[0]["cn"],
|
| 293 |
allow_custom_value=False,
|
| 294 |
interactive=True,
|
| 295 |
)
|
|
@@ -316,42 +305,34 @@ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
|
|
| 316 |
|
| 317 |
run_button = gr.Button(I18N["run"]["en"], variant="primary")
|
| 318 |
|
| 319 |
-
selected_cn = gr.Textbox(label=I18N["sel_cn"]["en"], value=CAMERA_OPTIONS[0]["cn"], interactive=False)
|
| 320 |
-
final_prompt_preview = gr.Textbox(label=I18N["final_prev"]["en"], value="", interactive=False)
|
| 321 |
-
|
| 322 |
-
# 選択/入力のたびにプレビュー更新 & 自由入力欄の表示切替
|
| 323 |
-
def _sync(v_cn, extra, custom_text):
|
| 324 |
-
is_custom = (v_cn == CUSTOM_OPTION_VALUE)
|
| 325 |
-
base = (custom_text.strip() if is_custom else (v_cn or CAMERA_OPTIONS[0]["cn"]))
|
| 326 |
-
final = _append_prompt(base, extra) if base else ""
|
| 327 |
-
return base, final, gr.update(visible=is_custom)
|
| 328 |
-
|
| 329 |
-
dropdown.change(
|
| 330 |
-
fn=_sync,
|
| 331 |
-
inputs=[dropdown, extra_prompt, custom_cn],
|
| 332 |
-
outputs=[selected_cn, final_prompt_preview, custom_cn]
|
| 333 |
-
)
|
| 334 |
-
extra_prompt.change(
|
| 335 |
-
fn=_sync,
|
| 336 |
-
inputs=[dropdown, extra_prompt, custom_cn],
|
| 337 |
-
outputs=[selected_cn, final_prompt_preview, custom_cn]
|
| 338 |
-
)
|
| 339 |
-
custom_cn.change(
|
| 340 |
-
fn=_sync,
|
| 341 |
-
inputs=[dropdown, extra_prompt, custom_cn],
|
| 342 |
-
outputs=[selected_cn, final_prompt_preview, custom_cn]
|
| 343 |
-
)
|
| 344 |
-
|
| 345 |
with gr.Row():
|
| 346 |
with gr.Column(scale=1, elem_classes=["card"]):
|
| 347 |
result_image = gr.Image(label=I18N["output"]["en"], type="pil", format="png", height=520, show_download_button=True)
|
| 348 |
status_text = gr.Textbox(label=I18N["status"]["en"], interactive=False)
|
| 349 |
-
sent_hdr_md = gr.Markdown(I18N["sent_hdr"]["en"])
|
| 350 |
-
final_prompt_small = gr.Textbox(show_label=False, interactive=False, elem_classes=["preview", "small"])
|
| 351 |
|
| 352 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 353 |
def _switch_lang(lang, current_dropdown_value):
|
| 354 |
-
# ラベル/見出し/プレースホルダの更新 + ドロップダンのchoicesの再構築
|
| 355 |
return (
|
| 356 |
gr.update(label=I18N["lang_label"][lang]), # lang_selector label
|
| 357 |
I18N["title"][lang], # title_md value
|
|
@@ -365,13 +346,10 @@ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
|
|
| 365 |
gr.update(label=I18N["seed"][lang]), # seed
|
| 366 |
gr.update(label=I18N["rand"][lang]), # randomize_seed
|
| 367 |
gr.update(label=I18N["tgs"][lang]), # true_guidance_scale
|
| 368 |
-
gr.update(label=I18N["steps"][lang]),
|
| 369 |
gr.update(value=I18N["run"][lang]), # run_button text
|
| 370 |
-
gr.update(label=I18N["sel_cn"][lang]), # selected_cn
|
| 371 |
-
gr.update(label=I18N["final_prev"][lang]), # final_prompt_preview
|
| 372 |
gr.update(label=I18N["output"][lang]), # result_image
|
| 373 |
gr.update(label=I18N["status"][lang]), # status_text
|
| 374 |
-
I18N["sent_hdr"][lang], # sent_hdr_md
|
| 375 |
)
|
| 376 |
|
| 377 |
lang_selector.change(
|
|
@@ -390,19 +368,16 @@ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
|
|
| 390 |
true_guidance_scale, # tgs label
|
| 391 |
num_inference_steps, # steps label
|
| 392 |
run_button, # button text
|
| 393 |
-
selected_cn, # label
|
| 394 |
-
final_prompt_preview, # label
|
| 395 |
result_image, # label
|
| 396 |
status_text, # label
|
| 397 |
-
sent_hdr_md, # markdown content
|
| 398 |
],
|
| 399 |
)
|
| 400 |
|
| 401 |
-
# 実行
|
| 402 |
run_button.click(
|
| 403 |
fn=generate_from_dropdown,
|
| 404 |
inputs=[input_image, dropdown, custom_cn, extra_prompt, seed, randomize_seed, true_guidance_scale, num_inference_steps, lang_selector],
|
| 405 |
-
outputs=[result_image, status_text
|
| 406 |
)
|
| 407 |
|
| 408 |
if __name__ == "__main__":
|
|
|
|
| 89 |
"zh": "自定义(用中文输入)",
|
| 90 |
}
|
| 91 |
|
| 92 |
+
# i18n 辞書(表示は単言語)
|
| 93 |
I18N = {
|
| 94 |
"title": {
|
| 95 |
+
"en": "Camera Work",
|
| 96 |
"ja": "カメラワーク",
|
| 97 |
"zh": "镜头控制",
|
| 98 |
},
|
|
|
|
| 103 |
},
|
| 104 |
"input_image": {"en": "Input image", "ja": "入力画像", "zh": "输入图像"},
|
| 105 |
"dropdown_label": {
|
| 106 |
+
"en": "Camera work",
|
| 107 |
+
"ja": "カメラワーク",
|
| 108 |
+
"zh": "镜头操作",
|
| 109 |
},
|
| 110 |
"custom_cn_label": {
|
| 111 |
+
"en": "Custom prompt(English and Chinese recommended)",
|
| 112 |
+
"ja": "自由入力のプロンプト(英語、中国語がおすすめ)",
|
| 113 |
+
"zh": "自定义提示词(推荐英文和中文)",
|
| 114 |
},
|
| 115 |
"custom_cn_ph": {
|
| 116 |
"en": "e.g., 将镜头转为斜俯视 并 拉远镜头",
|
|
|
|
| 118 |
"zh": "例如:将镜头转为斜俯视 并 拉远镜头",
|
| 119 |
},
|
| 120 |
"extra_label": {
|
| 121 |
+
"en": "Extra prompt (optional, appended at end)(English and Chinese recommended)",
|
| 122 |
+
"ja": "追加プロンプト(任意・末尾に付加)(英語、中国語がおすすめ)",
|
| 123 |
+
"zh": "附加提示词(可选,追加在末尾)(推荐英文和中文)",
|
| 124 |
},
|
| 125 |
"extra_ph": {
|
| 126 |
+
"en": "e.g., Subject is a girl",
|
| 127 |
+
"ja": "例: 被摄体是一名女孩子",
|
| 128 |
+
"zh": "例如:被摄体是一名女孩子",
|
| 129 |
},
|
| 130 |
"accordion": {"en": "Show advanced settings", "ja": "詳細設定を開く", "zh": "展开高级设置"},
|
| 131 |
"seed": {"en": "Seed", "ja": "Seed", "zh": "Seed"},
|
|
|
|
| 133 |
"tgs": {"en": "True guidance scale", "ja": "True guidance scale", "zh": "True guidance scale"},
|
| 134 |
"steps": {"en": "Steps", "ja": "生成ステップ数", "zh": "生成步数"},
|
| 135 |
"run": {"en": "Generate", "ja": "生成", "zh": "生成"},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 136 |
"output": {"en": "Output image", "ja": "出力画像", "zh": "输出图像"},
|
| 137 |
"status": {"en": "Status", "ja": "ステータス", "zh": "状态"},
|
|
|
|
| 138 |
"status_ok": {
|
| 139 |
+
"en": "Generated 1 image (PNG).",
|
| 140 |
+
"ja": "1枚生成しました(PNG)。",
|
| 141 |
+
"zh": "已生成 1 张图片(PNG)。",
|
| 142 |
},
|
| 143 |
"err_no_img": {
|
| 144 |
"en": "Error: Please upload an input image.",
|
|
|
|
| 146 |
"zh": "错误:请先上传输入图像。",
|
| 147 |
},
|
| 148 |
"err_no_custom": {
|
| 149 |
+
"en": "Error: Please enter a custom prompt.",
|
| 150 |
+
"ja": "エラー: 自由入力のプロンプトを入力してください",
|
| 151 |
+
"zh": "错误:请输入自定义提示词。",
|
| 152 |
},
|
| 153 |
"lang_label": {"en": "UI Language", "ja": "UI言語", "zh": "界面语言"},
|
| 154 |
}
|
|
|
|
| 157 |
return I18N[key][lang]
|
| 158 |
|
| 159 |
def build_dropdown_choices(lang):
|
| 160 |
+
# 表示は選択言語のみ(送信値は中国語)
|
| 161 |
if lang not in ("en", "ja", "zh"):
|
| 162 |
lang = "en"
|
| 163 |
ch = []
|
| 164 |
for item in CAMERA_OPTIONS:
|
| 165 |
+
label = item[lang] # 単言語表示
|
| 166 |
+
ch.append((label, item["cn"])) # 値は中国語を送る
|
| 167 |
ch.append((CUSTOM_LABELS[lang], CUSTOM_OPTION_VALUE))
|
| 168 |
return ch
|
| 169 |
|
|
|
|
| 201 |
seed = random.randint(0, MAX_SEED)
|
| 202 |
|
| 203 |
if image is None:
|
| 204 |
+
return None, t("err_no_img", lang)
|
| 205 |
|
| 206 |
if isinstance(image, Image.Image):
|
| 207 |
input_image = image.convert("RGB")
|
|
|
|
| 213 |
if dropdown_value_cn == CUSTOM_OPTION_VALUE:
|
| 214 |
base_cn = (custom_cn or "").strip()
|
| 215 |
if not base_cn:
|
| 216 |
+
return None, t("err_no_custom", lang)
|
| 217 |
else:
|
| 218 |
base_cn = dropdown_value_cn or CAMERA_OPTIONS[0]["cn"]
|
| 219 |
|
|
|
|
| 223 |
out = generate_single_view(pil_images, final_prompt, seed, num_inference_steps, true_guidance_scale)
|
| 224 |
progress(1.0, desc="Done" if lang=="en" else ("完了" if lang=="ja" else "完成"))
|
| 225 |
|
| 226 |
+
return out, t("status_ok", lang)
|
| 227 |
|
| 228 |
# --- UI ---
|
| 229 |
css = """
|
|
|
|
| 278 |
dropdown = gr.Dropdown(
|
| 279 |
label=I18N["dropdown_label"]["en"],
|
| 280 |
choices=build_dropdown_choices("en"),
|
| 281 |
+
value=CAMERA_OPTIONS[0]["cn"], # 値は中国語(見た目は単言語ラベル)
|
| 282 |
allow_custom_value=False,
|
| 283 |
interactive=True,
|
| 284 |
)
|
|
|
|
| 305 |
|
| 306 |
run_button = gr.Button(I18N["run"]["en"], variant="primary")
|
| 307 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 308 |
with gr.Row():
|
| 309 |
with gr.Column(scale=1, elem_classes=["card"]):
|
| 310 |
result_image = gr.Image(label=I18N["output"]["en"], type="pil", format="png", height=520, show_download_button=True)
|
| 311 |
status_text = gr.Textbox(label=I18N["status"]["en"], interactive=False)
|
|
|
|
|
|
|
| 312 |
|
| 313 |
+
# ドロップダウン選択に応じた「自由入力」欄の表示切替のみ残す
|
| 314 |
+
def _toggle_custom(v_cn, extra, custom_text):
|
| 315 |
+
is_custom = (v_cn == CUSTOM_OPTION_VALUE)
|
| 316 |
+
return gr.update(visible=is_custom)
|
| 317 |
+
|
| 318 |
+
dropdown.change(
|
| 319 |
+
fn=_toggle_custom,
|
| 320 |
+
inputs=[dropdown, extra_prompt, custom_cn],
|
| 321 |
+
outputs=[custom_cn]
|
| 322 |
+
)
|
| 323 |
+
extra_prompt.change(
|
| 324 |
+
fn=_toggle_custom,
|
| 325 |
+
inputs=[dropdown, extra_prompt, custom_cn],
|
| 326 |
+
outputs=[custom_cn]
|
| 327 |
+
)
|
| 328 |
+
custom_cn.change(
|
| 329 |
+
fn=_toggle_custom,
|
| 330 |
+
inputs=[dropdown, extra_prompt, custom_cn],
|
| 331 |
+
outputs=[custom_cn]
|
| 332 |
+
)
|
| 333 |
+
|
| 334 |
+
# 言語切替(単言語表示に統一)
|
| 335 |
def _switch_lang(lang, current_dropdown_value):
|
|
|
|
| 336 |
return (
|
| 337 |
gr.update(label=I18N["lang_label"][lang]), # lang_selector label
|
| 338 |
I18N["title"][lang], # title_md value
|
|
|
|
| 346 |
gr.update(label=I18N["seed"][lang]), # seed
|
| 347 |
gr.update(label=I18N["rand"][lang]), # randomize_seed
|
| 348 |
gr.update(label=I18N["tgs"][lang]), # true_guidance_scale
|
| 349 |
+
gr.update(label=I18N["steps"][lang]), # num_inference_steps
|
| 350 |
gr.update(value=I18N["run"][lang]), # run_button text
|
|
|
|
|
|
|
| 351 |
gr.update(label=I18N["output"][lang]), # result_image
|
| 352 |
gr.update(label=I18N["status"][lang]), # status_text
|
|
|
|
| 353 |
)
|
| 354 |
|
| 355 |
lang_selector.change(
|
|
|
|
| 368 |
true_guidance_scale, # tgs label
|
| 369 |
num_inference_steps, # steps label
|
| 370 |
run_button, # button text
|
|
|
|
|
|
|
| 371 |
result_image, # label
|
| 372 |
status_text, # label
|
|
|
|
| 373 |
],
|
| 374 |
)
|
| 375 |
|
| 376 |
+
# 実行(UIは単言語表示、送信は中国語値)
|
| 377 |
run_button.click(
|
| 378 |
fn=generate_from_dropdown,
|
| 379 |
inputs=[input_image, dropdown, custom_cn, extra_prompt, seed, randomize_seed, true_guidance_scale, num_inference_steps, lang_selector],
|
| 380 |
+
outputs=[result_image, status_text],
|
| 381 |
)
|
| 382 |
|
| 383 |
if __name__ == "__main__":
|