diff --git a/server.py b/server.py index 78fd90e..bf4e2cb 100644 --- a/server.py +++ b/server.py @@ -116,9 +116,11 @@ def doll_catalogue(): # keying cleanly (7/7 flood seeds) on both a dark solid and a busy multicolour knit, so # white is the default and green is the escape hatch, not the other way round. TEMPLATES = { + # 'no hanger, no coat hanger' is not padding: without it a wire hanger showed up in most + # SD product shots (and some flux ones), and a hanger keys into the cutout as garment. 'flat3d': ('product photo of a single {phrase} laid flat on a plain white background, front view, ' - 'no mannequin, no person, no text, soft even lighting, 1990s Australian op-shop garment, ' - 'slightly worn'), + 'no mannequin, no person, no hanger, no coat hanger, no text, soft even lighting, ' + '1990s Australian op-shop garment, slightly worn'), 'doll2d': ('paper doll clothing item for a dress-up game, {phrase}, {year} australia, {view}, ' 'floating centered on a plain pure white background, painterly stylized 3d game ' 'illustration, full item visible, no body, no person, no mannequin, no hanger, ' @@ -133,6 +135,15 @@ DOLL_PROMPT = TEMPLATES['doll2d_green'] # back-compat alias FLAT_PROMPT = TEMPLATES['flat3d'] +# The SD lane's default. Hyper_Realism was the only checkpoint the farm could reach and it is a +# person-photoreal merge — it framed every garment as worn-and-cropped no matter how hard you +# negative-prompted. juggernautXL is a product/material specialist; measured on the same +# prompt+seed it returns a clean isolated flat-lay. +SD_CKPT = os.environ.get('WG_SD_CKPT', 'juggernautXL_ragnarok.safetensors') +SD_NEG = ('person, human, body, model, mannequin, face, hands, legs, worn by someone, ' + 'hanger, coat hanger, (worst quality, low quality:1.4), blurry, watermark, text') + + def gen_seed(phrase, variant=0): """Reproducible seed from the phrase — reroll by bumping `variant`. @@ -596,6 +607,26 @@ class H(BaseHTTPRequestHandler): with open(tgt, 'wb') as f: f.write(base64.b64decode(out['result']['image'])) return tgt + if backend == 'sd': + # SDXL via ComfyUI. juggernautXL is a product/material specialist and beats + # the SD1.5 default outright: measured side by side on the same prompt+seed it + # gives a full isolated flat-lay, where Hyper_Realism frames the garment as + # worn and crops it at the edge. `lora` may be a list — the operator chains them. + JOBS[jid]['note'] = 'comfyui_sd ' + body.get('checkpoint', SD_CKPT) + params = {'prompt': style, 'negative': body.get('negative', SD_NEG), + 'checkpoint': body.get('checkpoint', SD_CKPT), + 'steps': int(body.get('steps') or 25), 'cfg': float(body.get('cfg', 7.0)), + 'width': wide, 'height': wide, 'seed': seed} + if body.get('lora'): + params['lora'] = body['lora'] + params['lora_weight'] = body.get('lora_weight', 0.8) + j = mb_req('/api/jobs', {'operator': 'comfyui_sd', 'params': params}) + gid = j.get('id') or j.get('job_id') + mb_wait(gid, jid, timeout=900) + outs = mb_outputs(gid) + if not outs: + raise RuntimeError('no image came back') + return mb_download(outs[0], tgt) JOBS[jid]['note'] = 'flux_local klein-4b' j = mb_req('/api/jobs', {'operator': 'flux_local', 'params': {'prompt': style, 'model': 'flux2-klein-4b', diff --git a/web/index.html b/web/index.html index f436b0e..6356dee 100644 --- a/web/index.html +++ b/web/index.html @@ -177,6 +177,7 @@