Spaces:
Paused
Paused
Upload app.py with huggingface_hub
Browse files
app.py
CHANGED
|
@@ -95,9 +95,10 @@ IDENTITY_NEG = os.getenv(
|
|
| 95 |
# -limb artifacts. Applied on person edits (whenever the identity lock is on).
|
| 96 |
ANATOMY_POS = os.getenv(
|
| 97 |
"ANATOMY_POS",
|
| 98 |
-
"
|
| 99 |
-
"
|
| 100 |
-
"fingers
|
|
|
|
| 101 |
# Extra anatomy negatives (active when Guidance > 1).
|
| 102 |
ANATOMY_NEG = os.getenv(
|
| 103 |
"ANATOMY_NEG",
|
|
@@ -380,6 +381,7 @@ def infer(
|
|
| 380 |
preserve_identity=True,
|
| 381 |
identity_strength=65,
|
| 382 |
output_size=1280,
|
|
|
|
| 383 |
progress=gr.Progress(track_tqdm=True),
|
| 384 |
):
|
| 385 |
gc.collect()
|
|
@@ -421,6 +423,14 @@ def infer(
|
|
| 421 |
|
| 422 |
pipe.set_adapters([adapter_name], adapter_weights=[1.0])
|
| 423 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 424 |
if randomize_seed:
|
| 425 |
seed = random.randint(0, MAX_SEED)
|
| 426 |
|
|
@@ -1219,6 +1229,16 @@ function init() {
|
|
| 1219 |
});
|
| 1220 |
}
|
| 1221 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1222 |
function showLoader() {
|
| 1223 |
const l = document.getElementById('output-loader');
|
| 1224 |
if (l) l.classList.add('active');
|
|
@@ -1394,6 +1414,7 @@ with gr.Blocks() as demo:
|
|
| 1394 |
preserve_identity = gr.Checkbox(value=True, elem_id="gradio-preserve", elem_classes="hidden-input", container=False)
|
| 1395 |
identity_strength = gr.Slider(minimum=0, maximum=100, step=5, value=65, elem_id="gradio-idstrength", elem_classes="hidden-input", container=False)
|
| 1396 |
output_size = gr.Slider(minimum=1024, maximum=2048, step=128, value=1280, elem_id="gradio-outsize", elem_classes="hidden-input", container=False)
|
|
|
|
| 1397 |
result = gr.Image(elem_id="gradio-result", elem_classes="hidden-input", container=False, format="png")
|
| 1398 |
|
| 1399 |
example_idx = gr.Textbox(value="", elem_id="example-idx-input", elem_classes="hidden-input", container=False)
|
|
@@ -1561,6 +1582,10 @@ with gr.Blocks() as demo:
|
|
| 1561 |
<input type="checkbox" id="custom-preserve" checked>
|
| 1562 |
<label for="custom-preserve">Keep her face / identity (pose & head can still change) — uncheck for anime/3D styles</label>
|
| 1563 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1564 |
<div class="slider-row">
|
| 1565 |
<label>Identity lock</label>
|
| 1566 |
<input type="range" id="custom-idstrength" min="0" max="100" step="5" value="65">
|
|
@@ -1616,9 +1641,9 @@ with gr.Blocks() as demo:
|
|
| 1616 |
|
| 1617 |
run_btn.click(
|
| 1618 |
fn=infer,
|
| 1619 |
-
inputs=[hidden_images_b64, prompt, lora_adapter, seed, randomize_seed, guidance_scale, steps, preserve_identity, identity_strength, output_size],
|
| 1620 |
outputs=[result, seed],
|
| 1621 |
-
js=r"""(imgs, p, la, s, rs, gs, st, pi, idst, osz) => {
|
| 1622 |
const images = window.__uploadedImages || [];
|
| 1623 |
const b64Array = images.map(img => img.b64);
|
| 1624 |
const imgsJson = JSON.stringify(b64Array);
|
|
@@ -1627,12 +1652,14 @@ with gr.Blocks() as demo:
|
|
| 1627 |
const presEl = document.getElementById('custom-preserve');
|
| 1628 |
const idstEl = document.getElementById('custom-idstrength');
|
| 1629 |
const oszEl = document.getElementById('custom-outsize');
|
|
|
|
| 1630 |
const promptVal = promptEl ? promptEl.value : p;
|
| 1631 |
const loraVal = loraEl ? loraEl.value : la;
|
| 1632 |
const presVal = presEl ? presEl.checked : pi;
|
| 1633 |
const idstVal = idstEl ? parseInt(idstEl.value) : idst;
|
| 1634 |
const oszVal = oszEl ? parseInt(oszEl.value) : osz;
|
| 1635 |
-
|
|
|
|
| 1636 |
}""",
|
| 1637 |
)
|
| 1638 |
|
|
|
|
| 95 |
# -limb artifacts. Applied on person edits (whenever the identity lock is on).
|
| 96 |
ANATOMY_POS = os.getenv(
|
| 97 |
"ANATOMY_POS",
|
| 98 |
+
" Render the hands perfectly: each hand has exactly five fingers — one thumb and "
|
| 99 |
+
"four fingers — in correct natural proportions, cleanly separated, no extra or "
|
| 100 |
+
"missing or fused fingers. Keep body anatomy correct: two hands, two arms, two "
|
| 101 |
+
"legs, no extra or duplicated limbs.")
|
| 102 |
# Extra anatomy negatives (active when Guidance > 1).
|
| 103 |
ANATOMY_NEG = os.getenv(
|
| 104 |
"ANATOMY_NEG",
|
|
|
|
| 381 |
preserve_identity=True,
|
| 382 |
identity_strength=65,
|
| 383 |
output_size=1280,
|
| 384 |
+
fix_hands=False,
|
| 385 |
progress=gr.Progress(track_tqdm=True),
|
| 386 |
):
|
| 387 |
gc.collect()
|
|
|
|
| 423 |
|
| 424 |
pipe.set_adapters([adapter_name], adapter_weights=[1.0])
|
| 425 |
|
| 426 |
+
# "Fix hands": the anti-extra-finger terms live in the NEGATIVE prompt, which is
|
| 427 |
+
# ignored at Guidance=1 (CFG off on this distilled model). Raising Guidance turns
|
| 428 |
+
# true-CFG on so those negatives actually suppress extra/fused fingers; a couple
|
| 429 |
+
# more steps give CFG room to work. Costs ~2x time — hence it's opt-in.
|
| 430 |
+
if bool(fix_hands):
|
| 431 |
+
guidance_scale = max(float(guidance_scale), float(os.getenv("FIXHANDS_CFG", "2.5")))
|
| 432 |
+
steps = max(int(steps), int(os.getenv("FIXHANDS_STEPS", "6")))
|
| 433 |
+
|
| 434 |
if randomize_seed:
|
| 435 |
seed = random.randint(0, MAX_SEED)
|
| 436 |
|
|
|
|
| 1229 |
});
|
| 1230 |
}
|
| 1231 |
|
| 1232 |
+
const fixHandsCheck = document.getElementById('custom-fixhands');
|
| 1233 |
+
if (fixHandsCheck) {
|
| 1234 |
+
fixHandsCheck.addEventListener('change', () => {
|
| 1235 |
+
const container = document.getElementById('gradio-fixhands');
|
| 1236 |
+
if (!container) return;
|
| 1237 |
+
const cb = container.querySelector('input[type="checkbox"]');
|
| 1238 |
+
if (cb && cb.checked !== fixHandsCheck.checked) cb.click();
|
| 1239 |
+
});
|
| 1240 |
+
}
|
| 1241 |
+
|
| 1242 |
function showLoader() {
|
| 1243 |
const l = document.getElementById('output-loader');
|
| 1244 |
if (l) l.classList.add('active');
|
|
|
|
| 1414 |
preserve_identity = gr.Checkbox(value=True, elem_id="gradio-preserve", elem_classes="hidden-input", container=False)
|
| 1415 |
identity_strength = gr.Slider(minimum=0, maximum=100, step=5, value=65, elem_id="gradio-idstrength", elem_classes="hidden-input", container=False)
|
| 1416 |
output_size = gr.Slider(minimum=1024, maximum=2048, step=128, value=1280, elem_id="gradio-outsize", elem_classes="hidden-input", container=False)
|
| 1417 |
+
fix_hands = gr.Checkbox(value=False, elem_id="gradio-fixhands", elem_classes="hidden-input", container=False)
|
| 1418 |
result = gr.Image(elem_id="gradio-result", elem_classes="hidden-input", container=False, format="png")
|
| 1419 |
|
| 1420 |
example_idx = gr.Textbox(value="", elem_id="example-idx-input", elem_classes="hidden-input", container=False)
|
|
|
|
| 1582 |
<input type="checkbox" id="custom-preserve" checked>
|
| 1583 |
<label for="custom-preserve">Keep her face / identity (pose & head can still change) — uncheck for anime/3D styles</label>
|
| 1584 |
</div>
|
| 1585 |
+
<div class="checkbox-row">
|
| 1586 |
+
<input type="checkbox" id="custom-fixhands">
|
| 1587 |
+
<label for="custom-fixhands">Fix hands (activates anti-extra-finger negatives — slower, ~2×)</label>
|
| 1588 |
+
</div>
|
| 1589 |
<div class="slider-row">
|
| 1590 |
<label>Identity lock</label>
|
| 1591 |
<input type="range" id="custom-idstrength" min="0" max="100" step="5" value="65">
|
|
|
|
| 1641 |
|
| 1642 |
run_btn.click(
|
| 1643 |
fn=infer,
|
| 1644 |
+
inputs=[hidden_images_b64, prompt, lora_adapter, seed, randomize_seed, guidance_scale, steps, preserve_identity, identity_strength, output_size, fix_hands],
|
| 1645 |
outputs=[result, seed],
|
| 1646 |
+
js=r"""(imgs, p, la, s, rs, gs, st, pi, idst, osz, fh) => {
|
| 1647 |
const images = window.__uploadedImages || [];
|
| 1648 |
const b64Array = images.map(img => img.b64);
|
| 1649 |
const imgsJson = JSON.stringify(b64Array);
|
|
|
|
| 1652 |
const presEl = document.getElementById('custom-preserve');
|
| 1653 |
const idstEl = document.getElementById('custom-idstrength');
|
| 1654 |
const oszEl = document.getElementById('custom-outsize');
|
| 1655 |
+
const fhEl = document.getElementById('custom-fixhands');
|
| 1656 |
const promptVal = promptEl ? promptEl.value : p;
|
| 1657 |
const loraVal = loraEl ? loraEl.value : la;
|
| 1658 |
const presVal = presEl ? presEl.checked : pi;
|
| 1659 |
const idstVal = idstEl ? parseInt(idstEl.value) : idst;
|
| 1660 |
const oszVal = oszEl ? parseInt(oszEl.value) : osz;
|
| 1661 |
+
const fhVal = fhEl ? fhEl.checked : fh;
|
| 1662 |
+
return [imgsJson, promptVal, loraVal, s, rs, gs, st, presVal, idstVal, oszVal, fhVal];
|
| 1663 |
}""",
|
| 1664 |
)
|
| 1665 |
|