优化为4b 模型

This commit is contained in:
xsl
2026-07-18 15:30:31 +08:00
parent 659c037270
commit b58cd4c441
289 changed files with 9367 additions and 558 deletions
+20 -26
View File
@@ -41,10 +41,10 @@
</head>
<body>
<div class="container">
<h1>接口12 final — 发际线带重绘 <span style="font-size:13px;color:#888">(精简版:final + 纯红遮罩 → 外部 ComfyUI 重绘)</span></h1>
<h1>接口12 final — 发际线带重绘 <span style="font-size:13px;color:#888">(精简版:final + 纯红遮罩 → ComfyUI 重绘)</span></h1>
<div class="subtitle">
只需上传图片 + 选择发型,其余参数全部用当前调优默认值(<code>/api/v1/hairline/grow_v2_final</code>)。<br>
后端产出 <b>④ final(接缝融合基底)</b> + <b>⑤-② 纯红遮罩 PNG</b>前端<b>外部重绘服务(local_test,默认 :8899</b>完成发际线带重绘。⚠️ 需 ComfyUI(:8188) 在跑。
后端产出 <b>④ final(接缝融合基底)</b> + <b>⑤-② 纯红遮罩 PNG</b><b>后端重绘接口(/api/v1/redraw</b>完成发际线带重绘。⚠️ 需 ComfyUI(:8188) 在跑。
局部加发版见 <a href="/static/test_interface12_final_v2.html">接口12 final v2</a>;完整参数调试见 <a href="/static/test_interface12.html">接口12 调试页</a>
</div>
@@ -52,11 +52,7 @@
<div class="upload-row">
<input type="file" id="imageFile" accept="image/*">
<button class="btn btn-primary" id="submitBtn" onclick="submitTest()">🎨 生成 final+遮罩</button>
<button class="btn btn-green" id="redrawBtn" onclick="runLocalRedraw()" disabled>🧪 调 local_test 重绘</button>
</div>
<div class="upload-row" style="margin-top:10px">
<label style="font-size:13px;font-weight:600;white-space:nowrap">重绘服务地址</label>
<input type="text" id="localTestUrl" value="http://10.60.74.221:8899" style="flex:1;min-width:200px;padding:8px;border:1px solid #ddd;border-radius:8px">
<button class="btn btn-green" id="redrawBtn" onclick="runLocalRedraw()" disabled>🧪 重绘</button>
</div>
<div class="upload-row" style="margin-top:10px">
<label style="font-size:13px;font-weight:600;white-space:nowrap">重绘提示词</label>
@@ -84,9 +80,9 @@
<div class="steps" style="grid-template-columns: repeat(auto-fill, minmax(300px, 1fr))">
<div class="step big"><div class="cap">接口11 final <small>④ 接缝融合(重绘输入基底,无美颜)</small></div><img id="finalBase"></div>
<div class="step big"><div class="cap">⑤-① 发际线重绘带遮罩 <small>纯红 alpha PNG(遮罩区=红+不透明,其余全透明)</small></div><img id="maskPng"></div>
<div class="step big"><div class="cap">🧪 local_test 重绘结果 <small>final + 遮罩 → 外部 ComfyUI(0716add-hair.json)</small></div><img id="localResult"></div>
<div class="step big"><div class="cap">🧪 重绘结果 <small>final + 遮罩 → ComfyUI(0716add-hair)</small></div><img id="localResult"></div>
</div>
<div style="font-size:12px;color:#888;margin-top:10px">流程:后端产出 final(接缝融合基底)+ 纯红遮罩 PNG,前端把两者 POST 到 local_test 重绘服务完成发际线补发。</div>
<div style="font-size:12px;color:#888;margin-top:10px">流程:后端产出 final(接缝融合基底)+ 纯红遮罩 PNG,再调后端 /api/v1/redraw 完成发际线补发。</div>
</div>
</div>
</div>
@@ -98,7 +94,7 @@ const API_BASE = window.location.origin;
const ENDPOINT = '/api/v1/hairline/grow_v2_final';
const TOKEN = 'dev-shared-secret-2026';
// 缓存最近一次后端返回的 final(data URI)和纯红遮罩(data URI),供 local_test 重绘使用
// 缓存最近一次后端返回的 final(data URI)和纯红遮罩(data URI),供重绘使用
let _finalDataUri = '';
let _maskDataUri = '';
@@ -121,7 +117,7 @@ function renderResult(d) {
$('redrawBtn').disabled = !canRedraw;
}
// data URI → Blob,用于把后端返回的 final/遮罩图作为文件 POST 给 local_test
// data URI → Blob,用于把后端返回的 final/遮罩图作为文件 POST 给后端重绘
function dataUriToBlob(dataUri) {
const [meta, b64] = dataUri.split(',');
const mime = (meta.match(/data:([^;]+)/) || [, 'application/octet-stream'])[1];
@@ -173,36 +169,34 @@ async function submitTest() {
async function runLocalRedraw() {
if (!_finalDataUri || !_maskDataUri) { setStatus('缺少 final 或遮罩,请先生成', 'error'); return; }
const base = $('localTestUrl').value.trim().replace(/\/+$/, '');
if (!base) { setStatus('请填写重绘服务地址', 'error'); return; }
const prompt = $('localTestPrompt').value.trim() || '填充遮罩区域的头发,皮肤加一点磨皮';
const btn = $('redrawBtn');
btn.disabled = true; btn.textContent = '⏳ 重绘中...';
const form = new FormData();
form.append('image', dataUriToBlob(_finalDataUri), 'final.jpg');
form.append('mask', dataUriToBlob(_maskDataUri), 'mask.png');
form.append('image_file', dataUriToBlob(_finalDataUri), 'final.jpg');
form.append('mask_file', dataUriToBlob(_maskDataUri), 'mask.png');
form.append('prompt', prompt);
const t0 = performance.now();
try {
const resp = await fetch(base + '/api/generate', { method: 'POST', body: form });
const resp = await fetch(API_BASE + '/api/v1/redraw', {
method: 'POST',
body: form,
});
const dt = ((performance.now() - t0) / 1000).toFixed(2);
if (resp.ok && resp.headers.get('content-type', '').includes('image/')) {
const blob = await resp.blob();
const url = URL.createObjectURL(blob);
$('localResult').src = url;
const json = await resp.json();
if (json.code === 0 && json.data && json.data.image_base64) {
$('localResult').src = json.data.image_base64;
$('localResult').onclick = function(){ zoom(this.src); };
setStatus('✅ local_test 重绘完成 (' + dt + 's)', 'success');
setStatus('✅ 重绘完成 (' + dt + 's)', 'success');
} else {
let msg = resp.status + '';
try { const j = await resp.json(); msg = j.error || JSON.stringify(j); } catch (_) {}
setStatus('❌ local_test 重绘失败:' + msg, 'error');
setStatus('❌ 重绘失败:' + (json.message || JSON.stringify(json)), 'error');
}
} catch (err) {
setStatus('❌ local_test 网络错误:' + err.message + '(确认服务在跑且已加 CORS', 'error');
setStatus('❌ 重绘网络错误:' + err.message, 'error');
} finally {
btn.disabled = false; btn.textContent = '🧪 调 local_test 重绘';
btn.disabled = false; btn.textContent = '🧪 重绘';
}
}
</script>