drawface-live / illust.html
ingon1's picture
sync from bd61e564bfa012b93c3fabe3190d66575174a898
102a1b6 verified
Raw
History Blame Contribute Delete
6.48 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Illustration Track — DrawFace Live</title>
<!-- 정적 쇼케이스. 이 페이지는 추론을 돌리지 않는다 — 로컬 GPU 에서 미리 렌더한 결과만 재생한다.
실시간 트랙(index.html)과 달리 LivePortrait 는 TensorRT + GPU 가 필요해 웹에 못 올린다.
핵심 메시지는 "되는 그림 / 안 되는 그림" 대조다. 성공 사례만 걸면 다음 사람이
손그림에 이 트랙을 붙였다가 같은 실패를 반복한다. -->
<style>
:root { color-scheme: dark; }
* { box-sizing: border-box; }
body {
margin: 0; min-height: 100vh; display: flex; flex-direction: column; align-items: center;
font-family: 'Pretendard', 'Noto Sans KR', sans-serif; background: #16161d; color: #e8e8ef;
}
main { width: min(900px, 96vw); padding: 24px 0 48px; }
h1 { font-size: 1.25rem; font-weight: 700; margin: 12px 0 4px; }
h2 { font-size: 1.02rem; font-weight: 700; margin: 34px 0 10px; }
p { line-height: 1.7; color: #c3c3d2; font-size: .93rem; margin: 8px 0; }
.lede { color: #9a9ab0; font-size: .9rem; margin-bottom: 6px; }
.tag { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: .74rem; font-weight: 700; letter-spacing: .02em; }
.tag.ok { background: #17402c; color: #7ee0a8; }
.tag.no { background: #431c22; color: #ff9aa5; }
.duo { display: flex; gap: 14px; flex-wrap: wrap; }
figure { flex: 1 1 300px; margin: 0; }
figure video, figure img {
width: 100%; display: block; border-radius: 14px; border: 1px solid #2a2a35; background: #0d0d12;
}
figcaption { color: #9a9ab0; font-size: .82rem; margin-top: 7px; line-height: 1.55; }
.card { border: 1px solid #2a2a35; border-radius: 14px; padding: 14px 16px; background: #1b1b23; }
table { border-collapse: collapse; width: 100%; font-size: .88rem; margin-top: 8px; }
th, td { text-align: left; padding: 8px 10px; border-bottom: 1px solid #2a2a35; }
th { color: #9a9ab0; font-weight: 600; }
td strong { color: #7ee0a8; }
a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.row { display: flex; gap: 8px; margin-top: 18px; align-items: center; flex-wrap: wrap; }
.btn { padding: 10px 16px; border-radius: 6px; border: 1px solid transparent; background: #e8e8ef; color: #16161d;
font-size: .93rem; font-weight: 600; text-decoration: none; }
.btn.alt { background: transparent; color: #c9c9d4; border-color: #3a3f47; }
footer { margin-top: 30px; font-size: .78rem; color: #66667a; line-height: 1.7; }
</style>
</head>
<body>
<main>
<h1>Illustration Track — the artwork follows my face</h1>
<p class="lede">FasterLivePortrait · local GPU only · everything below is pre-rendered</p>
<p>
This repo has <strong>two</strong> ways to animate a face, and which one works depends entirely on the
artwork. The same model gives opposite results on different kinds of drawings, so we measured it and
split the pipeline into two tracks.
</p>
<h2><span class="tag ok">Works</span> &nbsp;Standard-proportion illustration · fine art</h2>
<div class="duo">
<figure>
<video src="img/flp/vermeer.mp4" autoplay loop muted playsinline preload="metadata"></video>
<figcaption>
Vermeer, “Girl with a Pearl Earring” (1665, public domain).
The brushwork and canvas craquelure stay intact while only the head pose and expression move.
</figcaption>
</figure>
<figure>
<img src="img/flp_illust_ok.png" alt="Six frames of a driven vector illustration — the linework and coloring hold while only the expression changes">
<figcaption>
Six frames of a vector illustration. The linework and coloring are never regenerated, so the
original style survives.
</figcaption>
</figure>
</div>
<h2><span class="tag no">Doesn't work</span> &nbsp;Hand drawings · doodles · chibi</h2>
<figure style="max-width:660px">
<img src="img/flp/fail_handdrawn.png" alt="LivePortrait applied to a hand drawing — no face is detected, so all three frames stay unchanged">
<figcaption>
Same pipeline, same webcam input. On a hand drawing <strong>face detection fails outright</strong>,
so nothing happens at all — and if you force detection through, the entire head smears instead.
Line art on white paper is outside the model's training distribution.
</figcaption>
</figure>
<p>
That is why hand drawings are handled by <a href="./">ARAP warp mirroring</a> rather than this track.
It deforms the original strokes over a triangle mesh, so it never invents pixels that were not there,
and it runs in real time in the browser.
</p>
<h2>Why this can't run in the browser</h2>
<div class="card">
<table>
<tr><th>Backend</th><th>Per frame</th><th>In practice</th></tr>
<tr><td>TensorRT (RTX 4070 Ti)</td><td><strong>27–37 ms</strong></td><td>Real-time (~30 fps)</td></tr>
<tr><td>ONNX GPU (same card)</td><td>118–124 ms</td><td>~8 fps — not real-time</td></tr>
</table>
<p style="margin-top:12px">
Real-time is a <strong>TensorRT-only number</strong>. And a TensorRT engine is bound to the GPU and
versions it was built on — it will not load on any other machine. Free hosting is CPU-only, so it is
slower still, and round-tripping webcam frames through a server destroys the feeling that the drawing
is following you. That is why this page only shows <strong>pre-rendered results</strong>.
</p>
</div>
<div class="row">
<a class="btn" href="./">Try the real-time mirroring</a>
<a class="btn alt" href="https://github.com/ingon1026/drawface-live#일러스트-트랙--liveportrait-실시간-2026-07-23-재실측">How to run it yourself</a>
</div>
<footer>
The clips were pre-rendered on a local GPU (RTX 4070 Ti, TensorRT) — this page runs no inference.
There is no audio.<br>
Source artwork — Vermeer's “Girl with a Pearl Earring” is public domain and ships as an example image
with <a href="https://github.com/warmshao/FasterLivePortrait">FasterLivePortrait</a> (MIT).
The pig drawing is my own.<br>
Reproduction steps and local patches are in
<a href="https://github.com/ingon1026/drawface-live/blob/main/THIRD_PARTY.md">THIRD_PARTY.md</a>.
</footer>
</main>
</body>
</html>