feat: initial project setup

This commit is contained in:
2026-10-08 09:46:47 +08:00
commit 5833a303bc
65 changed files with 11628 additions and 0 deletions
+267
View File
@@ -0,0 +1,267 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BiRefNet WebUI · 智能抠图</title>
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='8' fill='%234f8cff'/%3E%3Cpath d='M9 21c4-1 5-10 14-10-4 1-5 10-14 10z' fill='white'/%3E%3C/svg%3E">
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
<header class="topbar">
<div class="brand">
<span class="logo" aria-hidden="true">
<svg viewBox="0 0 32 32" width="26" height="26"><rect width="32" height="32" rx="8" fill="var(--accent)"/><path d="M9 21c4-1 5-10 14-10-4 1-5 10-14 10z" fill="#fff"/></svg>
</span>
<h1>BiRefNet <em>WebUI</em></h1>
</div>
<dl class="meta" id="meta">
<div><dt>设备</dt><dd id="meta-device">检测中…</dd></div>
<div><dt>模型</dt><dd id="meta-models">—</dd></div>
<div><dt>模型代码</dt><dd id="meta-node" class="path" title="">—</dd></div>
</dl>
<div class="topbar-actions">
<button class="btn ghost sm" id="btn-reload-models" type="button">重新扫描模型</button>
<button class="btn ghost sm" id="btn-unload" type="button">卸载显存</button>
</div>
</header>
<main class="layout">
<!-- ============================= 参数面板 ============================= -->
<aside class="sidebar">
<section class="block">
<header class="block-head"><h2>1 · 图片</h2><span class="hint" id="file-count">未选择</span></header>
<div class="dropzone compact" id="dropzone" tabindex="0" role="button" aria-label="选择或拖入图片">
<p>拖入图片 / 点击选择 / <kbd>Ctrl</kbd>+<kbd>V</kbd> 粘贴</p>
<p class="sub">支持 PNG · JPG · WebP · BMP · TIFF · 一次一张,新图会替换上一张</p>
<input type="file" id="file-input" accept="image/*" hidden>
</div>
<ul class="thumbs" id="thumbs"></ul>
<p class="pending-note" id="pending-note"></p>
</section>
<section class="block">
<header class="block-head"><h2>2 · 模型</h2><span class="hint" id="model-hint"></span></header>
<label class="field">
<span>权重文件</span>
<select id="opt-model"></select>
</label>
<div class="field-row">
<label class="field">
<span>设备</span>
<select id="opt-device">
<option value="auto">自动 (GPU)</option>
<option value="cpu">CPU</option>
</select>
</label>
<label class="field">
<span>精度</span>
<select id="opt-dtype">
<option value="auto">自动 (fp16 加速)</option>
<option value="float32">float32 · 最稳</option>
<option value="float16">float16 · 最省显存</option>
<option value="bfloat16">bfloat16</option>
</select>
</label>
</div>
<label class="field">
<span>架构</span>
<select id="opt-arch">
<option value="auto">自动识别</option>
<option value="v1">v1(新版,safetensors)</option>
<option value="old">old(旧版 .pth)</option>
</select>
</label>
</section>
<section class="block">
<header class="block-head"><h2>3 · 参数</h2><span class="hint">按需调整</span></header>
<label class="field">
<span>预处理尺寸</span>
<select id="opt-resolution-mode">
<option value="square">固定 1024×1024(推荐)</option>
<option value="longest">长边自适应(保宽高比)</option>
<option value="custom">自定义宽高</option>
</select>
</label>
<div class="field-row" id="row-longest">
<label class="field">
<span>长边像素</span>
<input type="number" id="opt-longest-side" value="1024" min="32" max="4096" step="32">
</label>
</div>
<div class="field-row hidden" id="row-wh">
<label class="field">
<span>宽</span>
<input type="number" id="opt-width" value="1024" min="32" max="4096" step="32">
</label>
<label class="field">
<span>高</span>
<input type="number" id="opt-height" value="1024" min="32" max="4096" step="32">
</label>
</div>
<div class="field-row">
<label class="field">
<span>插值方式</span>
<select id="opt-upscale">
<option value="bilinear">bilinear</option>
<option value="bicubic">bicubic</option>
<option value="nearest">nearest</option>
<option value="nearest-exact">nearest-exact</option>
</select>
</label>
<label class="field">
<span>遮罩阈值</span>
<input type="number" id="opt-threshold" value="0" min="0" max="1" step="0.004">
</label>
</div>
<label class="field">
<span>背景</span>
<select id="opt-background">
<option value="transparent">透明(PNG Alpha)</option>
<option value="color">纯色背景</option>
</select>
</label>
<div class="field-row hidden" id="row-bgcolor">
<label class="field">
<span>背景色</span>
<input type="color" id="opt-bgcolor" value="#ffffff">
</label>
<div class="swatches" id="swatches">
<button type="button" data-color="#ffffff" style="--c:#ffffff" title="白"></button>
<button type="button" data-color="#000000" style="--c:#000000" title="黑"></button>
<button type="button" data-color="#00ff00" style="--c:#00ff00" title="绿幕"></button>
<button type="button" data-color="#4f8cff" style="--c:#4f8cff" title="蓝"></button>
</div>
</div>
<label class="check">
<input type="checkbox" id="opt-refine" checked>
<span>前景精修(去除边缘残留背景色)</span>
</label>
<div class="field-row" id="row-blur">
<label class="field">
<span>大核 r1</span>
<input type="number" id="opt-blur1" value="90" min="1" max="255">
</label>
<label class="field">
<span>小核 r2</span>
<input type="number" id="opt-blur2" value="6" min="1" max="255">
</label>
</div>
<label class="check">
<input type="checkbox" id="opt-mask">
<span>同时输出遮罩(灰度 PNG)</span>
</label>
<label class="field">
<span>最终尺寸 · 最长边(0 = 保持原图尺寸)</span>
<input type="number" id="opt-final-side" value="0" min="0" max="32768" step="16">
</label>
<p class="field-tip">非 0 时按原图比例等比缩放,使结果最长边等于该值。例:2000×3000 填 1440 → 960×1440</p>
</section>
<section class="block actions">
<button class="btn primary" id="btn-run" type="button" disabled>开始抠图</button>
<div class="progress" id="progress" hidden>
<div class="bar"><i id="progress-bar"></i></div>
<div class="progress-meta">
<span id="progress-stage">等待中</span>
<button class="btn link" id="btn-cancel" type="button">取消</button>
</div>
</div>
<p class="error-text" id="error-text" hidden></p>
</section>
<section class="block">
<header class="block-head"><h2>4 · 批量处理</h2><span class="hint">按目录批量抠图</span></header>
<label class="field">
<span>图片目录(模板路径)</span>
<input type="text" id="batch-input-dir" placeholder="例:F:\photos\待抠图" spellcheck="false" autocomplete="off">
</label>
<label class="field">
<span>输出目录</span>
<input type="text" id="batch-output-dir" placeholder="默认:项目 outputs 目录" spellcheck="false" autocomplete="off">
</label>
<label class="check">
<input type="checkbox" id="batch-recursive">
<span>包含子目录</span>
</label>
<button class="btn" id="btn-batch" type="button">开始批量抠图</button>
<div class="progress" id="batch-progress" hidden>
<div class="bar"><i id="batch-progress-bar"></i></div>
<div class="progress-meta">
<span id="batch-progress-stage">准备中…</span>
<button class="btn link" id="btn-batch-cancel" type="button">取消</button>
</div>
</div>
<p class="error-text" id="batch-error" hidden></p>
<p class="batch-note">
两个目录都必须<strong>已存在</strong>(本工具不会自动创建,路径不对会直接报错)。结果写入输出目录,命名
<code>RMBG_原名_时间戳.后缀</code>,原名超 20 字符截断;抠图参数沿用左侧当前设置。
</p>
</section>
</aside>
<!-- ============================= 结果区 ============================= -->
<section class="stage">
<header class="stage-head">
<h2>结果 <span class="count" id="result-count">0</span></h2>
<div class="stage-tools">
<div class="segmented" id="view-switch">
<button type="button" data-view="cutout" class="active">抠图</button>
<button type="button" data-view="mask">遮罩</button>
<button type="button" data-view="original">原图</button>
</div>
<button class="btn ghost sm" id="btn-zip" type="button" disabled>打包下载 ZIP</button>
<button class="btn ghost sm" id="btn-clear" type="button" title="清空整个结果列表" disabled>清空</button>
</div>
</header>
<p class="stage-tip">结果会一直保留在列表里(传新图、改参数都不会清空)· 点文件名或「重新处理」会套用它上次使用的参数 · 点卡片选中 · 点 × 移除单条</p>
<section class="batch-report" id="batch-report" hidden>
<header class="batch-report-head">
<h3>批量任务 <span class="badge" id="batch-badge">排队中</span></h3>
<span class="batch-report-path" id="batch-report-path" title=""></span>
<button class="btn ghost sm" id="btn-batch-hide" type="button">收起</button>
</header>
<p class="batch-report-sum" id="batch-report-sum"></p>
<ul class="batch-rows" id="batch-rows"></ul>
</section>
<div class="empty-state" id="empty">
<div class="empty-art" aria-hidden="true">
<svg viewBox="0 0 240 140" width="240" height="140">
<rect x="1" y="1" width="238" height="138" rx="14" fill="none" stroke="var(--border)" stroke-dasharray="6 6"/>
<circle cx="70" cy="62" r="22" fill="none" stroke="var(--accent)" stroke-width="2"/>
<path d="M104 92c14-4 18-40 52-40-14 4-18 40-52 40z" fill="var(--accent)" opacity=".85"/>
<path d="M46 108h148" stroke="var(--border)" stroke-width="2" stroke-linecap="round"/>
</svg>
</div>
<h3>还没有结果</h3>
<p>左侧拖入图片 → 选择模型 → 点击「开始抠图」。处理完成后可拖拽分割线对比原图与抠图效果,记录会累积在右侧供随时重新处理。</p>
</div>
<div class="grid" id="results"></div>
</section>
</main>
<script src="/static/zip.js"></script>
<script src="/static/app.js"></script>
</body>
</html>