# Aniface-Demo **Repository Path**: mrchip233/Aniface-Demo ## Basic Information - **Project Name**: Aniface-Demo - **Description**: 照片 → 摄像头可驱动的 3D 头像。Blender + ICT-FaceKit 建模 · aniface / MediaPipe 驱动 ARKit 52 表情 · 小熊猫头模 + 三视图 Web 演示(AR 贴脸/背景虚化/选区蒙版)· 自动部署 GitHub Pages - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: https://mrchipset.github.io/aniface-demo/ - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-13 - **Last Updated**: 2026-10-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 照片 → 可被摄像头驱动的 3D 头像(Blender + aniface) 把一张**参考图**变成能在浏览器里用**摄像头实时驱动**的 3D 头像:模型带完整的 ARKit 52 表情 (morph target),由 MediaPipe 识别人脸后驱动。 项目包含**两条建模流水线**(真人头像 / 卡通动物头像)、一个**开箱即用的网页演示**, 以及一份把两次实践中所有坑记录下来的工程笔记。

参考图   ➜   生成的小熊猫头像
参考图 ➜ 程序化生成的 redpanda_head.glb(52 个 ARKit 表情,0.84 MB)

--- ## 这是什么 一条完整链路: ``` 参考图 / 照片 │ ← Blender + MCP(由 Codex 等 agent 直接驱动) ▼ 带 ARKit 命名 morph target 的 GLB │ ← three.js + aniface 运行时 ▼ 摄像头 → MediaPipe FaceLandmarker → ARKit 52 blendshape → 模型表情 ``` 关键约束:**模型的 morph target 必须按 ARKit 命名**(大小写敏感、名字精确匹配), 否则 aniface 只会让头转动,脸是死的。 ## 站在谁的肩膀上 本项目不是一个从零开始的模型库,而是在两个成熟上游之上做**工程化补齐**。 下面说清楚「谁给了什么」和「我们补了什么」。 ### 上游项目 | 上游 | 提供 | 许可 | |---|---|---| | [ICT-FaceKit](https://github.com/USC-ICT/ICT-FaceKit)(USC ICT) | 真人头基座:26,719 顶点、UV 完整、53 个 ARKit 命名 shape key | MIT | | [aniface](https://github.com/alysachan830/aniface)(Alysa Chan) | 运行时:MediaPipe FaceLandmarker → ARKit 52 blendshape → three.js morph | MIT | | aniface 的 demo 素材 `raccoon_head_small.glb` | 卡通基座(自带 52 个 ARKit 表情,含 `tongueOut`) | MIT | | `mcp-for-blender` | 让 agent 直接驱动 Blender 建模 / 渲染 / 导出 | MIT | ### 我们在 ICT-FaceKit 基础上做的(流水线 A:真人照片 → 人头) ICT-FaceKit 只给你「模型 + 形状基」,**不会告诉你怎么从一张照片得到你的脸**。 下面这些是补上的部分: 1. **2D→3D 身份拟合**:MediaPipe 468 关键点 → 人工校验过的 29 个语义对应点 → 60 个 PCA 模式 + 相似变换,交替最小二乘 + 岭回归求解身份系数 (结果 `|c|=3.0`,重投影 RMSE 22.9 px ≈ 脸宽 5%) 2. **正确的 shape key 写入方式**:有 shape key 的网格改 `mesh.vertices` 无效, 必须把增量写进**每一个 shape key 块** 3. **姿态规整**:法线重算朝外(贴图覆盖面 1894 → 7882 面)、统一缩放居中(头高 0.26 m) 4. **命名对齐**:`_L`→`Left`、`_R`→`Right` 等重命名,合并到 51 个精确 ARKit 名(缺 `tongueOut`) 5. **瘦身导出**:剔除眼球 / 牙齿 / 牙龈 / 睫毛(26,719 → 14,062 顶点)+ 关 morph 法线 + meshopt 压缩 → **97.7 MB → 20.2 MB** 6. **一键复现**:以上步骤串成 `pipeline.py`,在 Blender 里一行 `exec()` 跑完 ### 我们在 aniface 基础上做的(接入层 + 缺陷绕过) aniface 的 head-only 模式有几处「不看源码必然踩」的行为,本项目都做了处理并写进文档: | 上游行为 | 后果 | 我们的处理 | |---|---|---| | head-only 分支把模型矩阵**放大 40 倍** | Scale 要调到 0.1 才看得见,且只剩一张大嘴 | 读内层实际缩放并抵消:`wrapper.scale = 用户Scale / innerScale` | | 内部已镜像 Y/Z,合成时又翻一次 → 双重镜像 | 模型动作与人脸左右相反 | `pasteMirror = !viewMirror` | | 把人脸矩阵的**平移分量写进模型根节点** | 模型在画布内跑偏、被裁成半张脸 | 每帧在 render **之前**清零 `matrix.elements[12..14]` | | 每帧覆盖 `gltf.scene.matrix` | 直接改模型位置 / 缩放无效 | 外套一层 `THREE.Group`,改 wrapper | ### 完全由本项目新增的部分 - **卡通动物头像流水线**(流水线 B):基于 raccoon 基座的配色重映射方案 - **`aniface-demo`**:三视图网页演示(见下),上游只有一个「把模型摆在你脸上」的最小 demo - **背景虚化 / 选区裁剪 / 圆角圆形蒙版**等合成与输出能力 - **GitHub Pages 子路径部署**(CI 构建 + 自动发布) - **工程笔记 `AGENTS.md`**:30+ 条实测踩坑,含失败方案的复盘 ## 在线演示 推送到 GitHub 后由 Actions 自动构建并发布到 `https://<用户名>.github.io/<仓库名>/`。 **GitHub Pages 自带 HTTPS,因此别人打开网页就能直接授权摄像头驱动头像**,不需要自签证书。 ```powershell cd C:\Users\Zouyu\tmp\blender git remote add origin https://github.com/<用户名>/<仓库名>.git git push -u origin main ``` Pages 开关不用手动点(`configure-pages` 带 `enablement: true` 会自动开启)。 细节见 [aniface-demo/README.md](aniface-demo/README.md#部署到-github-pages) 与 [.github/workflows/deploy-pages.yml](.github/workflows/deploy-pages.yml)。 ## 快速开始 ```powershell cd aniface-demo npm install npm run dev # 默认 HTTPS,打开 https://localhost:5199/ ``` 跨机器用摄像头(需要 https,且本机 IP 变了要重签证书): ```powershell npm run cert # 把当前所有网卡 IP 写进 SAN npm run dev # 在另一台机器打开 https://<本机IP>:5199/ ``` ## 演示程序能做什么 三栏布局,控件跟着各自的视图走: | 视图 | 能力 | |---|---| | **① 摄像头原始画面** | 关键点 / 网格叠加、镜像、实时信息;**背景虚化**(Selfie Segmenter,强度可调 + 反转遮罩) | | **② 合成视图** | 把小熊猫按人脸框 **AR 贴到真人脸上**,大小 / 偏移 X、Y 可调 | | **③ 输出视图** | **选区裁剪 × 倍率**得到任意分辨率输出;**蒙版**支持圆角矩形 / 圆形 + 边缘羽化 | 另有:3D 模型源切换、模型自身的位置 / 缩放 / 旋转、手动表情滑块(验证模型)、 文件测试模式(**不需要摄像头**,选本地视频或图片即可跑通整条链路)。 所有滑块都支持**鼠标滚轮调节**(`Shift` 粗调 10×、`Alt` 微调 1/10)。 ```powershell npm run check # 自检:main.js 里所有 $('id') 是否都能在 index.html 找到 npm run vendor:mediapipe # 把 MediaPipe 运行时本地化(约 36MB,避免依赖 CDN) ``` ## 产物 | 文件 | 说明 | |---|---| | `work/assets/redpanda_head.glb` | ★ 小熊猫头像,52 个 ARKit 表情,head-only,meshopt 压缩,**0.84 MB** | | `aniface-demo/public/redpanda_head.glb` | 同一模型(演示用副本) | | `work/assets/redpanda_only.blend` | ★ 小熊猫 Blender 源工程 · 干净版(1.88 MB,开箱可渲染) | | `work/assets/redpanda_source.blend` | 小熊猫源工程 · 实验全场景(8.8 MB,含 53 个 shape key) | | `work/assets/raccoon_head_small.glb` | 上游卡通基座(MIT),流水线 B 的输入 | | `work/assets/redpanda_base3.png` / `redpanda_ear3.png` | 重映射生成的主体 / 耳朵贴图 | | `work/assets/renders/` | 迭代渲染图(`final_f.png`、`redpanda_only_preview.png` 等) | | `work/scripts/` | 全部建模脚本(`pipeline.py`、`facekit/`、`redpanda/`、`tools/`) | 校验和与归档说明见 [archive/CHECKSUMS.md](archive/CHECKSUMS.md)。 ## 两条流水线怎么做 ### 流水线 A:真人照片 → 人头(ICT-FaceKit) ```python # 在 Blender(已装 mcp-for-blender)里执行 exec(open(r"work/scripts/pipeline.py", encoding="utf-8").read()) ``` 需要:`ICT-FaceKit/` 已 clone、`ict_fit.json`、 `ict_neutral.npy` / `ict_ids.npy`(由 `work/scripts/facekit/fit3.py` 生成)、一张正面照片。 ```bash git clone --depth 1 https://github.com/USC-ICT/ICT-FaceKit.git ``` ### 流水线 B:卡通动物头像(以小熊猫为例) 1. 取 `raccoon_head_small.glb` 作基座(自带 52 个 ARKit 表情) 2. **配色重映射**:按亮度分区把原贴图换成目标色板 —— 深 → 深红棕(眼罩 / 鼻)、中 → 锈橘(主体)、浅 → 奶白(吻 / 耳缘) 3. 耳朵单独一套贴图(白边 + 橘心) 4. 导出:meshopt + 关 morph 法线 → 0.84 MB > 为什么不做照片投影?**把带表情的照片平面投影到模型上,会把舌头、张口、光照烤进中性表情**, > 球面投影还会把眼周拉变形。做中性基座必须用**贴图配色重映射**这条稳的路子。 > 这个方案曾被采用又回退,复盘见 [docs/STATUS.md](docs/STATUS.md)。 ## 目录结构 ``` . ├── aniface-demo/ 可运行的演示(Vite + three.js + MediaPipe) │ ├── src/main.js 三种驱动模式 + 合成 + 虚化 + 选区输出 │ ├── public/redpanda_head.glb │ ├── scripts/ vendor:mediapipe / make-cert / check-ids │ └── README.md 界面说明 · 操作技巧 · 排错 │ ├── .github/workflows/ GitHub Pages 构建与发布 ├── AGENTS.md ★ 工程笔记:30+ 条实测踩坑与硬约束(动手前先读) ├── LICENSE MIT ├── docs/STATUS.md 当前问题清单 + 两条流水线的完整步骤 ├── archive/CHECKSUMS.md 产物 SHA256 与归档说明 │ └── work/ ★ 建模工作目录(详见 work/README.md) ├── assets/ 模型 / 贴图 / 中间数据(脚本的 CWD) │ ├── renders/ 迭代渲染图留档 │ └── textures/ Blender 源工程引用的环境贴图(CC0) └── scripts/ ├── pipeline.py ★ 真人头像一键重建 ├── facekit/ ICT 身份拟合、对齐、贴图、瘦身导出 ├── redpanda/ 小熊猫配色重映射、UV 绘制、导出 └── tools/ GLB 规格校验与分析 ``` ## 已知不足 | 问题 | 说明 | |---|---| | **精细斑纹做不出来** | 基座贴图脸岛仅约 100×140 px 且左右镜像共用 UV,按 3D 坐标绘制分辨率不够。正解是重展 UV 到 1K~2K 后手工绘制 | | 耳朵是侧向的 | 继承自 raccoon,真小熊猫是直立耳 | | 人类头像缺 `tongueOut` | 卡通版本有,人类版本缺 | | 人类头像脸型偏窄长 | 仅 29 个 2D 约束、无深度约束,线性模型拟合不到 100% | | 无身体、无耳朵 / 尾巴骨骼 | aniface 只管脸 + 头旋转 | | 实时链路未端到端验证 | 开发机无摄像头,需在另一台机器用 https 打开 | 具体路径与优先级见 [docs/STATUS.md](docs/STATUS.md)。 ## 许可与致谢 - 本项目采用 **MIT** 许可,见 [LICENSE](LICENSE) - 上游 [ICT-FaceKit](https://github.com/USC-ICT/ICT-FaceKit)、[aniface](https://github.com/alysachan830/aniface)、 `mcp-for-blender` 均为 **MIT**,本项目对其的使用与二次开发遵循各自许可 - `rpm_avatar.glb`(Ready Player Me 全身像)仅作参考对比,遵循 Ready Player Me 条款 - `work/assets/textures/studio_kontrast_03_1k.hdr`(环境贴图)来自 PolyHaven,**CC0**,可自由再分发 - 仓库不包含任何真人照片素材;演示请用「用视频 / 图片文件测试」自选本地文件