diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..e2a98c8 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,11 @@ +{ + "permissions": { + "allow": [ + "Bash(awk '/^vt / {print $2, $3}' D:/face_sdk/app/src/main/assets/face_picture_3dmax.obj)", + "Bash(awk 'BEGIN{minu=99;maxu=-99;minv=99;maxv=-99} {if\\($1maxu\\)maxu=$1; if\\($2maxv\\)maxv=$2} END{print \"u:\",minu,maxu,\" v:\",minv,maxv}')", + "Bash(python -c \"from PIL import Image; print\\(Image.open\\('D:/face_sdk/example/src/main/assets/pic/4ex.png'\\).size\\)\")", + "Bash(python -c ' *)", + "Bash(python -c \"import sys; print\\(sys.executable\\)\")" + ] + } +} diff --git a/python/README.md b/python/README.md new file mode 100644 index 0000000..8a97bfe --- /dev/null +++ b/python/README.md @@ -0,0 +1,146 @@ +# Face SDK Web 服务 + +把 Android Face SDK 的人脸贴图渲染逻辑迁移到 Python Web 服务:上传一张人物图 + 效果 ID, +返回叠加渲染后的 PNG。CPU 实现(OpenCV 仿射 warp + alpha 混合),不依赖 GPU。 + +--- + +## 渲染原理(与 Android SDK 一致) + +``` +input image ──► MediaPipe FaceLandmarker ──► 478 normalized landmarks + │ + ▼ + face_picture_3dmax.obj (468 顶点+UV / 852 三角形) + 每个 obj 顶点 i 的画面位置 = landmarks[INDEX_MAP[i]] + │ + ▼ + 每个三角形: + src = obj UV × effect 贴图尺寸 (在 512×512 effect 里) + dst = landmarks 像素位置 (在 input image 里) + cv2.getAffineTransform → cv2.warpAffine → alpha 混合 + │ + ▼ + output PNG(同原图尺寸) +``` + +`INDEX_MAP[468]` 同步自 `vulkan/hardcode_data.h::indexMap`,UV 的 V 翻转与 +`vulkan/FaceApp.cpp::LoadOBJ` 行为一致。 + +--- + +## 目录结构 + +``` +python/ +├── server/ +│ ├── main.py FastAPI 入口(/health /effects /render) +│ ├── face_renderer.py 渲染核心 +│ ├── mesh.py OBJ 解析 +│ ├── index_map.py OBJ vertex → MediaPipe landmark 映射 +│ ├── assets/ +│ │ ├── face_picture_3dmax.obj ← 来自 app/src/main/assets +│ │ └── face_landmarker.task ← 可选;不放则自动回退到 app/src/main/assets/ +│ └── effects/ +│ └── 1.png 512×512 RGBA 效果贴图,文件名是效果 ID(1-99) +└── requirements.txt +``` + +--- + +## 一次性安装 + +需要 Python 3.10–3.12(mediapipe 当前不支持 3.13)。 + +```powershell +# Windows PowerShell(或 cmd) +cd D:\face_sdk\python +python -m venv venv +.\venv\Scripts\Activate.ps1 # cmd 用 .\venv\Scripts\activate.bat +pip install --upgrade pip +pip install -r requirements.txt +``` + +```bash +# Linux / macOS +cd /path/to/face_sdk/python +python3 -m venv venv +source venv/bin/activate +pip install --upgrade pip +pip install -r requirements.txt +``` + +--- + +## 启动服务 + +```powershell +cd D:\face_sdk\python +.\venv\Scripts\Activate.ps1 +uvicorn server.main:app --host 0.0.0.0 --port 8000 +``` + +启动日志看到 `Application startup complete.` 即就绪。 + +--- + +## API + +### `GET /health` +```json +{"ok": true} +``` + +### `GET /effects` +返回当前 `server/effects/` 下存在的效果 ID(按 `.png` 文件名提取,1–99): +```json +{"effects": [1]} +``` + +### `POST /render` +- form-data: + - `image`: 文件(jpeg / png / webp,≤ 20MB) + - `effect_id`: 整数(1–99,必须在 `/effects` 列表内) +- 成功:`200`,`Content-Type: image/png`,body 是 PNG 字节 +- 没检测到人脸:`400 {"error":"no_face"}` +- effect_id 不存在:`404` +- 参数错误(图非法 / 太大 / id 越界):`400` + +#### curl 示例 + +```bash +curl -X POST http://localhost:8000/render \ + -F image=@/path/to/photo.jpg \ + -F effect_id=1 \ + --output result.png +``` + +#### Python 示例 + +```python +import requests +files = {"image": open("photo.jpg", "rb")} +data = {"effect_id": 1} +r = requests.post("http://localhost:8000/render", files=files, data=data) +r.raise_for_status() +open("result.png", "wb").write(r.content) +``` + +--- + +## 添加新效果 + +把一张 512×512 的 RGBA PNG 放到 `python/server/effects/.png`(`` 是 1–99 的整数)。 +服务下次响应 `/effects` 时会自动列出;首次被请求时按需载入并缓存内存。 + +PNG 必须有 alpha 通道——透明区域不会盖到原图上。 + +--- + +## 已知限制 + +- 纯 2D 仿射 warp,与 Android SDK 行为一致:人脸侧面角度大时贴图会拉伸。 +- MediaPipe FaceLandmarker 每次 `detect()` 不保证多线程并发安全,服务用锁串行化。 + 单进程同步部署够用;要更高并发请用多 worker 或前置队列。 +- 单张 4K 图渲染约 100–300ms(852 三角形 × `cv2.warpAffine`);如需更快可改成 + `cv2.remap` 一次性贴整脸,但需要更多代码。 diff --git a/python/requirements.txt b/python/requirements.txt new file mode 100644 index 0000000..dcd3160 --- /dev/null +++ b/python/requirements.txt @@ -0,0 +1,7 @@ +fastapi>=0.110 +uvicorn[standard]>=0.27 +python-multipart>=0.0.9 +mediapipe>=0.10.14 +opencv-python>=4.9 +pillow>=10.0 +numpy>=1.26,<2.0 diff --git a/python/server/__init__.py b/python/server/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/server/__pycache__/__init__.cpython-312.pyc b/python/server/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..75959b3 Binary files /dev/null and b/python/server/__pycache__/__init__.cpython-312.pyc differ diff --git a/python/server/__pycache__/index_map.cpython-312.pyc b/python/server/__pycache__/index_map.cpython-312.pyc new file mode 100644 index 0000000..79fbb72 Binary files /dev/null and b/python/server/__pycache__/index_map.cpython-312.pyc differ diff --git a/python/server/__pycache__/mesh.cpython-312.pyc b/python/server/__pycache__/mesh.cpython-312.pyc new file mode 100644 index 0000000..70c3f41 Binary files /dev/null and b/python/server/__pycache__/mesh.cpython-312.pyc differ diff --git a/python/server/assets/face_picture_3dmax.obj b/python/server/assets/face_picture_3dmax.obj new file mode 100644 index 0000000..a4c9eac --- /dev/null +++ b/python/server/assets/face_picture_3dmax.obj @@ -0,0 +1,2279 @@ +# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware +# ļ:02.12.2025 18:33:58 + +mtllib 1202.mtl + +# +# object default +# + +v 0.1676 0.5092 0.2591 +v 0.1771 0.5141 0.1685 +v 0.1865 0.4618 0.1361 +v 0.4670 0.7575 -0.0631 +v 0.4671 0.7458 -0.0670 +v 0.4379 0.7395 -0.0631 +v 0.3892 0.5426 -0.0007 +v 0.3631 0.5501 0.0018 +v 0.3648 0.5691 -0.0028 +v 0.4383 0.7547 -0.0594 +v 0.4080 0.7493 -0.0466 +v 0.4142 0.5453 -0.0172 +v 0.3929 0.5585 -0.0115 +v 0.3953 0.5777 -0.0249 +v 0.2693 0.3555 -0.0041 +v 0.3317 0.3441 -0.0417 +v 0.3176 0.2901 -0.0208 +v 0.4645 0.9425 0.0141 +v 0.4131 0.9359 0.0208 +v 0.4148 0.9524 0.0567 +v 0.2764 0.5811 0.0178 +v 0.2618 0.6372 0.0203 +v 0.3218 0.6083 -0.0036 +v 0.4130 0.7599 -0.0441 +v 0.3882 0.7597 -0.0267 +v 0.4716 0.4160 -0.0756 +v 0.4717 0.3448 -0.0701 +v 0.3976 0.3432 -0.0630 +v 0.3969 0.6604 -0.0717 +v 0.4082 0.6504 -0.0986 +v 0.4081 0.6340 -0.0898 +v 0.3866 0.8650 0.0146 +v 0.3576 0.8424 0.0268 +v 0.3437 0.8641 0.0496 +v 0.3940 0.7654 -0.0259 +v 0.3753 0.7689 -0.0041 +v 0.4042 0.7765 -0.0144 +v 0.3997 0.7722 -0.0205 +v 0.3858 0.7742 -0.0038 +v 0.3656 0.7335 -0.0192 +v 0.3465 0.7519 0.0005 +v 0.3297 0.5547 0.0078 +v 0.2951 0.5537 0.0195 +v 0.3330 0.8122 0.0361 +v 0.3121 0.7799 0.0363 +v 0.2817 0.7829 0.0643 +v 0.4327 0.8532 -0.0060 +v 0.4654 0.8552 -0.0070 +v 0.4656 0.8296 -0.0366 +v 0.3696 0.7768 0.0149 +v 0.3665 0.7770 0.0190 +v 0.3761 0.7887 0.0050 +v 0.3077 0.4839 0.0049 +v 0.2906 0.4595 -0.0031 +v 0.2739 0.4710 0.0089 +v 0.3790 0.4711 -0.0057 +v 0.3737 0.4919 0.0003 +v 0.3911 0.5057 0.0066 +v 0.3754 0.8206 0.0083 +v 0.2726 0.8255 0.1227 +v 0.2492 0.7539 0.0989 +v 0.3648 0.6781 -0.0133 +v 0.3913 0.7208 -0.0338 +v 0.4049 0.6867 -0.0353 +v 0.1839 0.3975 0.1474 +v 0.2000 0.4179 0.0893 +v 0.2271 0.3808 0.0385 +v 0.4461 0.6108 -0.1335 +v 0.4449 0.6420 -0.1470 +v 0.4683 0.6424 -0.1505 +v 0.3130 0.5174 0.0122 +v 0.3092 0.5328 0.0113 +v 0.3340 0.5345 0.0034 +v 0.3805 0.7832 0.0001 +v 0.3891 0.8008 -0.0126 +v 0.3002 0.6720 -0.0008 +v 0.2473 0.6924 0.0531 +v 0.4243 0.8807 0.0009 +v 0.4652 0.8852 -0.0044 +v 0.4008 0.8398 -0.0021 +v 0.3934 0.7913 -0.0180 +v 0.4090 0.8158 -0.0252 +v 0.4368 0.8081 -0.0399 +v 0.4355 0.8259 -0.0348 +v 0.3387 0.7021 -0.0061 +v 0.3413 0.6423 -0.0146 +v 0.3707 0.9171 0.0457 +v 0.4398 0.4946 -0.0439 +v 0.4163 0.4924 -0.0098 +v 0.4205 0.5208 -0.0087 +v 0.3286 0.4800 -0.0027 +v 0.3507 0.4822 -0.0044 +v 0.3507 0.4573 -0.0138 +v 0.2650 0.4848 0.0259 +v 0.2885 0.4959 0.0245 +v 0.2953 0.4902 0.0145 +v 0.4299 0.5952 -0.0907 +v 0.4478 0.5842 -0.1103 +v 0.4469 0.5590 -0.0919 +v 0.2100 0.3506 0.0899 +v 0.4704 0.4907 -0.0625 +v 0.4708 0.4538 -0.0666 +v 0.2438 0.5706 0.0425 +v 0.2694 0.5454 0.0357 +v 0.2547 0.5342 0.0489 +v 0.4147 0.4479 -0.0578 +v 0.4381 0.6925 -0.0621 +v 0.4358 0.6881 -0.0632 +v 0.3997 0.6049 -0.0340 +v 0.3666 0.5924 -0.0138 +v 0.4158 0.6704 -0.0715 +v 0.4240 0.6662 -0.0985 +v 0.4162 0.6618 -0.1040 +v 0.3915 0.5162 0.0115 +v 0.3762 0.5164 0.0068 +v 0.3827 0.5290 0.0029 +v 0.4015 0.6264 -0.0480 +v 0.3951 0.6468 -0.0647 +v 0.2745 0.8529 0.1747 +v 0.3121 0.8883 0.1365 +v 0.4156 0.5873 -0.0517 +v 0.3094 0.4427 -0.0210 +v 0.2958 0.4235 -0.0338 +v 0.2595 0.4320 -0.0112 +v 0.4257 0.6190 -0.1166 +v 0.3369 0.8887 0.0738 +v 0.3553 0.8012 0.0189 +v 0.3268 0.5785 0.0047 +v 0.2483 0.5082 0.0545 +v 0.2680 0.5023 0.0429 +v 0.2444 0.4142 0.0007 +v 0.4447 0.6760 -0.1132 +v 0.4468 0.6819 -0.0886 +v 0.4518 0.6855 -0.0880 +v 0.2345 0.4506 0.0166 +v 0.2186 0.4376 0.0384 +v 0.2080 0.4730 0.0733 +v 0.3758 0.7767 0.0109 +v 0.3724 0.7765 0.0115 +v 0.3860 0.7805 -0.0004 +v 0.2017 0.5181 0.1021 +v 0.1794 0.5700 0.1817 +v 0.2078 0.6235 0.0945 +v 0.2264 0.5516 0.0656 +v 0.4481 0.6677 -0.1374 +v 0.4565 0.6808 -0.1238 +v 0.4680 0.6820 -0.1255 +v 0.3186 0.7336 0.0088 +v 0.3551 0.5186 0.0035 +v 0.3600 0.5332 0.0009 +v 0.4362 0.7131 -0.0588 +v 0.4161 0.9117 0.0047 +v 0.3756 0.6237 -0.0222 +v 0.3370 0.7750 0.0229 +v 0.4334 0.6829 -0.0627 +v 0.2232 0.5152 0.0750 +v 0.2488 0.4835 0.0338 +v 0.3185 0.4537 -0.0130 +v 0.3124 0.8326 0.0644 +v 0.2574 0.4627 0.0097 +v 0.1892 0.6268 0.1920 +v 0.2004 0.5675 0.0971 +v 0.4176 0.7696 -0.0389 +v 0.4403 0.7685 -0.0495 +v 0.3885 0.6596 -0.0216 +v 0.3968 0.6721 -0.0561 +v 0.4127 0.6839 -0.0509 +v 0.3910 0.6586 -0.0486 +v 0.2811 0.7127 0.0235 +v 0.3801 0.7717 -0.0038 +v 0.3058 0.8611 0.0987 +v 0.3436 0.9132 0.1068 +v 0.3766 0.9355 0.0767 +v 0.2857 0.4006 -0.0310 +v 0.3413 0.4028 -0.0575 +v 0.4461 0.5307 -0.0678 +v 0.4702 0.5253 -0.0786 +v 0.2170 0.6766 0.1074 +v 0.3464 0.4269 -0.0501 +v 0.4055 0.4113 -0.0715 +v 0.3989 0.7829 -0.0152 +v 0.4124 0.7997 -0.0300 +v 0.1829 0.6285 0.2903 +v 0.4662 0.7941 -0.0388 +v 0.4395 0.7914 -0.0353 +v 0.4667 0.7799 -0.0380 +v 0.4429 0.7777 -0.0344 +v 0.3334 0.5197 0.0053 +v 0.4044 0.7768 -0.0132 +v 0.4168 0.7866 -0.0268 +v 0.3914 0.7770 0.0008 +v 0.2412 0.7896 0.1540 +v 0.2439 0.8140 0.2214 +v 0.2163 0.7403 0.1861 +v 0.2171 0.7611 0.2620 +v 0.4046 0.6684 -0.0743 +v 0.4218 0.7757 -0.0259 +v 0.4693 0.5807 -0.1203 +v 0.4645 0.9176 -0.0027 +v 0.4427 0.7770 -0.0354 +v 0.3002 0.5130 0.0210 +v 0.2904 0.5279 0.0232 +v 0.1733 0.5677 0.2835 +v 0.3888 0.2791 -0.0510 +v 0.4062 0.6759 -0.0606 +v 0.3911 0.7769 -0.0000 +v 0.3491 0.4463 -0.0240 +v 0.4591 0.6886 -0.0877 +v 0.3948 0.4651 -0.0194 +v 0.4693 0.5547 -0.0987 +v 0.2793 0.5182 0.0339 +v 0.2917 0.5082 0.0285 +v 0.2830 0.5012 0.0372 +v 0.4253 0.6445 -0.1239 +v 0.4322 0.6630 -0.1245 +v 0.4292 0.5259 -0.0266 +v 0.1712 0.4480 0.2091 +v 0.4299 0.5441 -0.0501 +v 0.4302 0.5711 -0.0722 +v 0.4679 0.6942 -0.0697 +v 0.4487 0.6788 -0.1199 +v 0.4677 0.7135 -0.0618 +v 0.4672 0.7696 -0.0536 +v 0.4666 0.7789 -0.0387 +v 0.4143 0.6117 -0.0684 +v 0.3989 0.5145 0.0114 +v 0.3979 0.5234 0.0058 +v 0.4074 0.5155 0.0073 +v 0.4330 0.6672 -0.1115 +v 0.4015 0.4957 0.0009 +v 0.3750 0.8914 0.0272 +v 0.4221 0.7771 -0.0248 +v 0.1977 0.6930 0.2835 +v 0.2017 0.6854 0.1930 +v 0.4680 0.6685 -0.1399 +v 0.2263 0.7213 0.1205 +v 0.4161 0.6751 -0.0607 +v 0.4679 0.6893 -0.0895 +v 0.4217 0.6803 -0.0551 +v 0.2780 0.4493 -0.0086 +v 0.4070 0.5352 -0.0034 +v 0.4134 0.5615 -0.0359 +v 0.2270 0.4800 0.0463 +v 0.7744 0.5149 0.2502 +v 0.7717 0.4527 0.2009 +v 0.7564 0.4666 0.1289 +v 0.4961 0.7564 -0.0603 +v 0.4968 0.7409 -0.0641 +v 0.5513 0.5446 -0.0028 +v 0.5470 0.5601 -0.0137 +v 0.5759 0.5717 -0.0057 +v 0.5217 0.7633 -0.0460 +v 0.5265 0.7526 -0.0487 +v 0.5263 0.5464 -0.0187 +v 0.5258 0.5628 -0.0376 +v 0.5440 0.5794 -0.0271 +v 0.5326 0.5370 -0.0051 +v 0.6749 0.3576 -0.0091 +v 0.6914 0.3169 0.0245 +v 0.6266 0.2923 -0.0250 +v 0.4644 0.9578 0.0484 +v 0.5151 0.9534 0.0552 +v 0.6655 0.5852 0.0127 +v 0.6148 0.5816 0.0010 +v 0.6177 0.6115 -0.0074 +v 0.5414 0.7702 -0.0285 +v 0.5470 0.7642 -0.0296 +v 0.5384 0.4118 -0.0725 +v 0.5462 0.3442 -0.0649 +v 0.5404 0.6625 -0.0737 +v 0.5420 0.6489 -0.0668 +v 0.5294 0.6356 -0.0915 +v 0.5463 0.8663 0.0123 +v 0.5572 0.8928 0.0248 +v 0.5904 0.8660 0.0460 +v 0.5546 0.7769 -0.0072 +v 0.5597 0.7746 -0.0078 +v 0.5303 0.7798 -0.0166 +v 0.5433 0.7812 -0.0029 +v 0.5494 0.7797 -0.0068 +v 0.5895 0.7566 -0.0036 +v 0.6114 0.5583 0.0040 +v 0.6029 0.8160 0.0321 +v 0.6222 0.8358 0.0597 +v 0.6549 0.7875 0.0586 +v 0.4990 0.8532 -0.0067 +v 0.4972 0.8271 -0.0358 +v 0.5660 0.7828 0.0113 +v 0.5545 0.7887 -0.0031 +v 0.5593 0.7932 0.0014 +v 0.6346 0.4869 0.0005 +v 0.6476 0.4942 0.0098 +v 0.6703 0.4744 0.0038 +v 0.5633 0.4724 -0.0083 +v 0.5397 0.4974 -0.0014 +v 0.5495 0.5072 0.0040 +v 0.5582 0.8234 0.0052 +v 0.5322 0.8411 -0.0042 +v 0.6630 0.8297 0.1167 +v 0.6946 0.7937 0.1473 +v 0.6879 0.7587 0.0926 +v 0.5719 0.6809 -0.0160 +v 0.5485 0.6618 -0.0238 +v 0.5309 0.6890 -0.0369 +v 0.7595 0.4019 0.1394 +v 0.7337 0.3543 0.0828 +v 0.7165 0.3837 0.0323 +v 0.4907 0.6108 -0.1342 +v 0.4686 0.6085 -0.1422 +v 0.6285 0.5216 0.0079 +v 0.6083 0.5236 0.0014 +v 0.6071 0.5388 -0.0005 +v 0.5410 0.7954 -0.0205 +v 0.5457 0.8047 -0.0151 +v 0.6384 0.6759 -0.0051 +v 0.6567 0.7166 0.0184 +v 0.6916 0.6970 0.0471 +v 0.5070 0.8820 -0.0003 +v 0.5247 0.8179 -0.0270 +v 0.5220 0.8031 -0.0318 +v 0.4960 0.8096 -0.0407 +v 0.4663 0.8117 -0.0427 +v 0.5989 0.7052 -0.0097 +v 0.5967 0.6454 -0.0179 +v 0.5548 0.9369 0.0738 +v 0.5614 0.9182 0.0429 +v 0.5700 0.7367 -0.0225 +v 0.5441 0.7234 -0.0362 +v 0.5007 0.4954 -0.0448 +v 0.5116 0.5273 -0.0278 +v 0.5196 0.5223 -0.0099 +v 0.6141 0.4824 -0.0067 +v 0.6251 0.4559 -0.0172 +v 0.5922 0.4593 -0.0170 +v 0.6544 0.5000 0.0197 +v 0.5084 0.5956 -0.0919 +v 0.5087 0.5722 -0.0734 +v 0.4922 0.5595 -0.0925 +v 0.5285 0.4483 -0.0589 +v 0.6986 0.5752 0.0364 +v 0.7160 0.5567 0.0593 +v 0.6877 0.5382 0.0432 +v 0.5248 0.4937 -0.0115 +v 0.5480 0.4664 -0.0217 +v 0.5237 0.6857 -0.0523 +v 0.4998 0.6891 -0.0639 +v 0.5391 0.6066 -0.0361 +v 0.5629 0.6260 -0.0248 +v 0.5726 0.5943 -0.0166 +v 0.5205 0.6722 -0.0730 +v 0.5317 0.6708 -0.0760 +v 0.5198 0.6630 -0.1055 +v 0.5495 0.5184 0.0091 +v 0.5428 0.5258 0.0035 +v 0.5577 0.5312 0.0005 +v 0.5364 0.6280 -0.0500 +v 0.5238 0.6125 -0.0700 +v 0.6281 0.8636 0.0938 +v 0.6213 0.8908 0.1315 +v 0.5232 0.5884 -0.0534 +v 0.6352 0.4452 -0.0248 +v 0.6668 0.4522 -0.0132 +v 0.6867 0.4338 -0.0162 +v 0.4918 0.6432 -0.1477 +v 0.5114 0.6456 -0.1254 +v 0.5115 0.6200 -0.1179 +v 0.5553 0.2800 -0.0530 +v 0.5789 0.8055 0.0152 +v 0.5774 0.5527 -0.0012 +v 0.6946 0.5128 0.0488 +v 0.6953 0.4875 0.0281 +v 0.6793 0.4888 0.0205 +v 0.7019 0.4160 -0.0048 +v 0.6604 0.4020 -0.0352 +v 0.6497 0.4245 -0.0376 +v 0.4912 0.6765 -0.1137 +v 0.4866 0.6789 -0.1205 +v 0.4840 0.6866 -0.0884 +v 0.7115 0.4529 0.0107 +v 0.7171 0.4838 0.0400 +v 0.7369 0.4771 0.0664 +v 0.5594 0.7825 0.0073 +v 0.5439 0.7814 -0.0022 +v 0.5485 0.7852 -0.0035 +v 0.7270 0.4401 0.0327 +v 0.7415 0.5225 0.0958 +v 0.7419 0.5721 0.0907 +v 0.7620 0.5753 0.1738 +v 0.7328 0.6288 0.0872 +v 0.4875 0.6683 -0.1379 +v 0.4904 0.5846 -0.1110 +v 0.6180 0.7377 0.0042 +v 0.5643 0.5195 0.0040 +v 0.5813 0.5365 -0.0023 +v 0.4993 0.7142 -0.0598 +v 0.5151 0.9128 0.0035 +v 0.5984 0.7794 0.0184 +v 0.4892 0.6825 -0.0891 +v 0.5669 0.4936 -0.0026 +v 0.7203 0.5196 0.0686 +v 0.6533 0.4625 -0.0078 +v 0.5766 0.8444 0.0235 +v 0.5623 0.7825 0.0079 +v 0.7520 0.6314 0.1844 +v 0.5167 0.7730 -0.0406 +v 0.5400 0.6741 -0.0581 +v 0.5303 0.6776 -0.0624 +v 0.5353 0.7759 -0.0228 +v 0.6239 0.7833 0.0314 +v 0.5960 0.8909 0.0700 +v 0.6122 0.3457 -0.0448 +v 0.4938 0.5309 -0.0685 +v 0.6776 0.6411 0.0149 +v 0.5357 0.7863 -0.0175 +v 0.5982 0.4280 -0.0528 +v 0.6040 0.4038 -0.0603 +v 0.5174 0.7896 -0.0284 +v 0.7582 0.6342 0.2818 +v 0.7690 0.5736 0.2749 +v 0.4943 0.7922 -0.0363 +v 0.5854 0.5220 0.0003 +v 0.5304 0.7802 -0.0155 +v 0.5130 0.7792 -0.0265 +v 0.6597 0.8562 0.1685 +v 0.7211 0.7447 0.1787 +v 0.6912 0.8179 0.2141 +v 0.5286 0.6525 -0.1003 +v 0.5129 0.7787 -0.0275 +v 0.5682 0.7832 0.0151 +v 0.5171 0.9373 0.0194 +v 0.4939 0.7699 -0.0503 +v 0.6871 0.4657 0.0044 +v 0.6327 0.5371 0.0068 +v 0.6520 0.5319 0.0182 +v 0.6466 0.5575 0.0148 +v 0.7649 0.5192 0.1610 +v 0.4720 0.2776 -0.0588 +v 0.5948 0.4476 -0.0270 +v 0.4767 0.6883 -0.0879 +v 0.6595 0.5052 0.0319 +v 0.6627 0.5227 0.0286 +v 0.6748 0.5067 0.0376 +v 0.5094 0.5448 -0.0511 +v 0.7436 0.4215 0.0823 +v 0.5889 0.9153 0.1029 +v 0.4976 0.6930 -0.0628 +v 0.5039 0.6639 -0.1257 +v 0.5413 0.5168 0.0092 +v 0.5031 0.6686 -0.1125 +v 0.5327 0.5174 0.0054 +v 0.4791 0.6807 -0.1241 +v 0.7373 0.6903 0.1852 +v 0.7417 0.6977 0.2756 +v 0.5128 0.6674 -0.0998 +v 0.7229 0.6814 0.1002 +v 0.7119 0.7257 0.1136 +v 0.5199 0.6768 -0.0623 +v 0.5147 0.6813 -0.0562 +v 0.6730 0.5500 0.0303 +v 0.5024 0.6834 -0.0634 +v 0.7196 0.7647 0.2546 +v 0.6510 0.5129 0.0235 +v 0.2529 0.3140 0.0303 +v 0.5906 0.4839 -0.0078 +v 0.5462 0.6605 -0.0508 +v 0.4910 0.7798 -0.0353 +v 0.4916 0.7787 -0.0363 +v 0.6419 0.5178 0.0164 +# 468 vertices + + +vt 0.0147 0.4668 0.0000 +vt 0.1049 0.4716 0.0000 +vt 0.1292 0.5313 0.0000 +vt 0.5005 0.2458 0.0000 +vt 0.5005 0.2570 0.0000 +vt 0.4745 0.2628 0.0000 +vt 0.3859 0.4818 0.0000 +vt 0.3646 0.4669 0.0000 +vt 0.3693 0.4471 0.0000 +vt 0.4759 0.2479 0.0000 +vt 0.4423 0.2555 0.0000 +vt 0.4120 0.4846 0.0000 +vt 0.3932 0.4639 0.0000 +vt 0.4003 0.4442 0.0000 +vt 0.2789 0.6680 0.0000 +vt 0.3509 0.6923 0.0000 +vt 0.3233 0.7432 0.0000 +vt 0.5005 0.0338 0.0000 +vt 0.4441 0.0397 0.0000 +vt 0.4312 0.0048 0.0000 +vt 0.2866 0.4184 0.0000 +vt 0.2814 0.3609 0.0000 +vt 0.3366 0.3971 0.0000 +vt 0.4479 0.2441 0.0000 +vt 0.4187 0.2424 0.0000 +vt 0.5013 0.6285 0.0000 +vt 0.5009 0.7040 0.0000 +vt 0.4227 0.7019 0.0000 +vt 0.4367 0.3599 0.0000 +vt 0.4546 0.3734 0.0000 +vt 0.4474 0.3880 0.0000 +vt 0.4127 0.1154 0.0000 +vt 0.3776 0.1397 0.0000 +vt 0.3570 0.1118 0.0000 +vt 0.4245 0.2358 0.0000 +vt 0.3990 0.2257 0.0000 +vt 0.4291 0.2176 0.0000 +vt 0.4278 0.2257 0.0000 +vt 0.4085 0.2183 0.0000 +vt 0.3920 0.2671 0.0000 +vt 0.3702 0.2432 0.0000 +vt 0.3340 0.4539 0.0000 +vt 0.2997 0.4488 0.0000 +vt 0.3483 0.1726 0.0000 +vt 0.3277 0.2091 0.0000 +vt 0.2881 0.2020 0.0000 +vt 0.4647 0.1244 0.0000 +vt 0.5005 0.1223 0.0000 +vt 0.5005 0.1584 0.0000 +vt 0.3882 0.2060 0.0000 +vt 0.3842 0.2055 0.0000 +vt 0.4009 0.1949 0.0000 +vt 0.3240 0.5332 0.0000 +vt 0.3086 0.5596 0.0000 +vt 0.2893 0.5442 0.0000 +vt 0.3901 0.5544 0.0000 +vt 0.3855 0.5335 0.0000 +vt 0.3961 0.5202 0.0000 +vt 0.4023 0.1612 0.0000 +vt 0.2419 0.1475 0.0000 +vt 0.2356 0.2274 0.0000 +vt 0.3833 0.3293 0.0000 +vt 0.4165 0.2829 0.0000 +vt 0.4238 0.3222 0.0000 +vt 0.1094 0.6010 0.0000 +vt 0.1699 0.5849 0.0000 +vt 0.2225 0.6315 0.0000 +vt 0.4860 0.4115 0.0000 +vt 0.4924 0.3854 0.0000 +vt 0.5012 0.3858 0.0000 +vt 0.3136 0.4853 0.0000 +vt 0.3135 0.4704 0.0000 +vt 0.3372 0.4740 0.0000 +vt 0.4066 0.2006 0.0000 +vt 0.4228 0.1832 0.0000 +vt 0.3239 0.3285 0.0000 +vt 0.2580 0.2993 0.0000 +vt 0.4569 0.0982 0.0000 +vt 0.5005 0.0934 0.0000 +vt 0.4319 0.1411 0.0000 +vt 0.4280 0.1927 0.0000 +vt 0.4470 0.1698 0.0000 +vt 0.4744 0.1790 0.0000 +vt 0.4737 0.1615 0.0000 +vt 0.3593 0.2991 0.0000 +vt 0.3583 0.3638 0.0000 +vt 0.3901 0.0568 0.0000 +vt 0.4604 0.5378 0.0000 +vt 0.4215 0.5338 0.0000 +vt 0.4193 0.5091 0.0000 +vt 0.3461 0.5423 0.0000 +vt 0.3661 0.5430 0.0000 +vt 0.3662 0.5686 0.0000 +vt 0.2731 0.5238 0.0000 +vt 0.2948 0.5106 0.0000 +vt 0.3067 0.5212 0.0000 +vt 0.4582 0.4314 0.0000 +vt 0.4820 0.4394 0.0000 +vt 0.4781 0.4654 0.0000 +vt 0.1687 0.6591 0.0000 +vt 0.5006 0.5393 0.0000 +vt 0.5005 0.5826 0.0000 +vt 0.2482 0.4258 0.0000 +vt 0.2699 0.4542 0.0000 +vt 0.2515 0.4650 0.0000 +vt 0.4436 0.5938 0.0000 +vt 0.4655 0.3097 0.0000 +vt 0.4596 0.3179 0.0000 +vt 0.4055 0.4116 0.0000 +vt 0.3746 0.4209 0.0000 +vt 0.4472 0.3421 0.0000 +vt 0.4638 0.3541 0.0000 +vt 0.4621 0.3644 0.0000 +vt 0.3851 0.5111 0.0000 +vt 0.3696 0.5043 0.0000 +vt 0.3786 0.4937 0.0000 +vt 0.4170 0.3941 0.0000 +vt 0.4310 0.3714 0.0000 +vt 0.1987 0.1072 0.0000 +vt 0.2659 0.0727 0.0000 +vt 0.4255 0.4356 0.0000 +vt 0.3309 0.5828 0.0000 +vt 0.3224 0.6075 0.0000 +vt 0.2824 0.5897 0.0000 +vt 0.4691 0.4044 0.0000 +vt 0.3374 0.0828 0.0000 +vt 0.3767 0.1817 0.0000 +vt 0.3352 0.4294 0.0000 +vt 0.2436 0.4922 0.0000 +vt 0.2667 0.4989 0.0000 +vt 0.2640 0.6037 0.0000 +vt 0.4861 0.3510 0.0000 +vt 0.4776 0.3328 0.0000 +vt 0.4828 0.3273 0.0000 +vt 0.2509 0.5633 0.0000 +vt 0.2244 0.5712 0.0000 +vt 0.1957 0.5278 0.0000 +vt 0.3952 0.2075 0.0000 +vt 0.3920 0.2069 0.0000 +vt 0.4106 0.2053 0.0000 +vt 0.1759 0.4752 0.0000 +vt 0.1009 0.4117 0.0000 +vt 0.1954 0.3660 0.0000 +vt 0.2214 0.4448 0.0000 +vt 0.4894 0.3650 0.0000 +vt 0.4963 0.3512 0.0000 +vt 0.5013 0.3506 0.0000 +vt 0.3407 0.2632 0.0000 +vt 0.3509 0.4949 0.0000 +vt 0.3596 0.4824 0.0000 +vt 0.4679 0.2897 0.0000 +vt 0.4512 0.0662 0.0000 +vt 0.3857 0.3856 0.0000 +vt 0.3562 0.2113 0.0000 +vt 0.4558 0.3242 0.0000 +vt 0.2113 0.4830 0.0000 +vt 0.2544 0.5237 0.0000 +vt 0.3366 0.5693 0.0000 +vt 0.3182 0.1465 0.0000 +vt 0.2735 0.5527 0.0000 +vt 0.1012 0.3494 0.0000 +vt 0.1847 0.4235 0.0000 +vt 0.4508 0.2318 0.0000 +vt 0.4757 0.2315 0.0000 +vt 0.4010 0.3544 0.0000 +vt 0.4301 0.3460 0.0000 +vt 0.4367 0.3271 0.0000 +vt 0.4212 0.3580 0.0000 +vt 0.3021 0.2818 0.0000 +vt 0.4032 0.2219 0.0000 +vt 0.2912 0.1118 0.0000 +vt 0.3179 0.0469 0.0000 +vt 0.3723 0.0264 0.0000 +vt 0.3117 0.6281 0.0000 +vt 0.3711 0.6357 0.0000 +vt 0.4738 0.4975 0.0000 +vt 0.5008 0.5007 0.0000 +vt 0.1975 0.3082 0.0000 +vt 0.3746 0.6135 0.0000 +vt 0.4366 0.6327 0.0000 +vt 0.4299 0.2024 0.0000 +vt 0.4496 0.1861 0.0000 +vt 0.0053 0.3348 0.0000 +vt 0.5005 0.1954 0.0000 +vt 0.4749 0.1968 0.0000 +vt 0.5005 0.2115 0.0000 +vt 0.4768 0.2107 0.0000 +vt 0.3319 0.4878 0.0000 +vt 0.4328 0.2102 0.0000 +vt 0.4508 0.2000 0.0000 +vt 0.4135 0.2110 0.0000 +vt 0.1895 0.1824 0.0000 +vt 0.1298 0.1429 0.0000 +vt 0.1384 0.2290 0.0000 +vt 0.0685 0.1945 0.0000 +vt 0.4418 0.3514 0.0000 +vt 0.4494 0.2171 0.0000 +vt 0.5009 0.4400 0.0000 +vt 0.5005 0.0619 0.0000 +vt 0.4742 0.2157 0.0000 +vt 0.3008 0.4876 0.0000 +vt 0.2923 0.4722 0.0000 +vt 0.0005 0.4015 0.0000 +vt 0.4068 0.7707 0.0000 +vt 0.4363 0.3405 0.0000 +vt 0.4123 0.2121 0.0000 +vt 0.3686 0.5816 0.0000 +vt 0.4912 0.3214 0.0000 +vt 0.4097 0.5625 0.0000 +vt 0.5005 0.4679 0.0000 +vt 0.2791 0.4819 0.0000 +vt 0.2919 0.4918 0.0000 +vt 0.2827 0.4994 0.0000 +vt 0.4738 0.3832 0.0000 +vt 0.4791 0.3668 0.0000 +vt 0.4334 0.5056 0.0000 +vt 0.0543 0.5378 0.0000 +vt 0.4456 0.4851 0.0000 +vt 0.4515 0.4542 0.0000 +vt 0.5005 0.3015 0.0000 +vt 0.4916 0.3521 0.0000 +vt 0.5008 0.2886 0.0000 +vt 0.5005 0.2309 0.0000 +vt 0.5005 0.2127 0.0000 +vt 0.4341 0.4127 0.0000 +vt 0.3949 0.5126 0.0000 +vt 0.3922 0.5039 0.0000 +vt 0.4020 0.5117 0.0000 +vt 0.4750 0.3572 0.0000 +vt 0.4057 0.5296 0.0000 +vt 0.4019 0.0857 0.0000 +vt 0.4541 0.2102 0.0000 +vt 0.0273 0.2648 0.0000 +vt 0.1148 0.2863 0.0000 +vt 0.5011 0.3651 0.0000 +vt 0.1987 0.2586 0.0000 +vt 0.4424 0.3354 0.0000 +vt 0.5008 0.3208 0.0000 +vt 0.4437 0.3275 0.0000 +vt 0.2981 0.5717 0.0000 +vt 0.4023 0.4956 0.0000 +vt 0.4203 0.4658 0.0000 +vt 0.2287 0.5259 0.0000 +vt 0.9848 0.4692 0.0000 +vt 0.9459 0.5412 0.0000 +vt 0.8720 0.5338 0.0000 +vt 0.5265 0.2472 0.0000 +vt 0.5278 0.2623 0.0000 +vt 0.6153 0.4824 0.0000 +vt 0.6078 0.4648 0.0000 +vt 0.6324 0.4475 0.0000 +vt 0.5545 0.2426 0.0000 +vt 0.5596 0.2542 0.0000 +vt 0.5894 0.4851 0.0000 +vt 0.5805 0.4662 0.0000 +vt 0.6005 0.4447 0.0000 +vt 0.5981 0.4959 0.0000 +vt 0.7226 0.6706 0.0000 +vt 0.7602 0.7091 0.0000 +vt 0.6771 0.7445 0.0000 +vt 0.5005 0.0005 0.0000 +vt 0.5712 0.0054 0.0000 +vt 0.7164 0.4194 0.0000 +vt 0.6676 0.4301 0.0000 +vt 0.6652 0.3982 0.0000 +vt 0.5782 0.2337 0.0000 +vt 0.5835 0.2407 0.0000 +vt 0.5670 0.6338 0.0000 +vt 0.5793 0.7023 0.0000 +vt 0.5645 0.3606 0.0000 +vt 0.5700 0.3722 0.0000 +vt 0.5539 0.3888 0.0000 +vt 0.5906 0.1168 0.0000 +vt 0.6014 0.0873 0.0000 +vt 0.6464 0.1140 0.0000 +vt 0.5984 0.2198 0.0000 +vt 0.6026 0.2235 0.0000 +vt 0.5728 0.2157 0.0000 +vt 0.5891 0.2097 0.0000 +vt 0.5936 0.2159 0.0000 +vt 0.6318 0.2428 0.0000 +vt 0.6677 0.4541 0.0000 +vt 0.6550 0.1736 0.0000 +vt 0.6842 0.1482 0.0000 +vt 0.7142 0.2035 0.0000 +vt 0.5379 0.1252 0.0000 +vt 0.5294 0.1616 0.0000 +vt 0.6140 0.2039 0.0000 +vt 0.5958 0.1986 0.0000 +vt 0.6018 0.1939 0.0000 +vt 0.6771 0.5351 0.0000 +vt 0.6938 0.5232 0.0000 +vt 0.7137 0.5456 0.0000 +vt 0.6110 0.5558 0.0000 +vt 0.5943 0.5303 0.0000 +vt 0.6034 0.5215 0.0000 +vt 0.6001 0.1616 0.0000 +vt 0.5710 0.1421 0.0000 +vt 0.7597 0.1494 0.0000 +vt 0.8115 0.1846 0.0000 +vt 0.7662 0.2292 0.0000 +vt 0.6177 0.3301 0.0000 +vt 0.5999 0.3550 0.0000 +vt 0.5771 0.3224 0.0000 +vt 0.8905 0.6045 0.0000 +vt 0.8310 0.6625 0.0000 +vt 0.7787 0.6346 0.0000 +vt 0.5151 0.4121 0.0000 +vt 0.5009 0.4119 0.0000 +vt 0.6876 0.4855 0.0000 +vt 0.6697 0.4878 0.0000 +vt 0.6640 0.4736 0.0000 +vt 0.5748 0.1915 0.0000 +vt 0.5804 0.1824 0.0000 +vt 0.6785 0.3296 0.0000 +vt 0.7003 0.2837 0.0000 +vt 0.7442 0.3013 0.0000 +vt 0.5459 0.0983 0.0000 +vt 0.5564 0.1701 0.0000 +vt 0.5539 0.1850 0.0000 +vt 0.5284 0.1787 0.0000 +vt 0.5005 0.1772 0.0000 +vt 0.6430 0.3002 0.0000 +vt 0.6430 0.3646 0.0000 +vt 0.6303 0.0280 0.0000 +vt 0.6132 0.0590 0.0000 +vt 0.6097 0.2674 0.0000 +vt 0.5849 0.2832 0.0000 +vt 0.5402 0.5378 0.0000 +vt 0.5678 0.5055 0.0000 +vt 0.5815 0.5092 0.0000 +vt 0.6558 0.5438 0.0000 +vt 0.6657 0.5712 0.0000 +vt 0.6354 0.5697 0.0000 +vt 0.7059 0.5124 0.0000 +vt 0.5430 0.4322 0.0000 +vt 0.5497 0.4544 0.0000 +vt 0.5233 0.4656 0.0000 +vt 0.5587 0.5950 0.0000 +vt 0.7543 0.4271 0.0000 +vt 0.7807 0.4461 0.0000 +vt 0.7504 0.4667 0.0000 +vt 0.5788 0.5343 0.0000 +vt 0.5917 0.5639 0.0000 +vt 0.5647 0.3278 0.0000 +vt 0.5418 0.3174 0.0000 +vt 0.5956 0.4123 0.0000 +vt 0.6156 0.3864 0.0000 +vt 0.6264 0.4223 0.0000 +vt 0.5542 0.3419 0.0000 +vt 0.5591 0.3514 0.0000 +vt 0.5393 0.3648 0.0000 +vt 0.6157 0.5115 0.0000 +vt 0.6086 0.5039 0.0000 +vt 0.6221 0.4943 0.0000 +vt 0.5841 0.3948 0.0000 +vt 0.5672 0.4138 0.0000 +vt 0.7110 0.1141 0.0000 +vt 0.7358 0.0748 0.0000 +vt 0.5756 0.4364 0.0000 +vt 0.6724 0.5841 0.0000 +vt 0.7053 0.5733 0.0000 +vt 0.7220 0.5927 0.0000 +vt 0.5098 0.3851 0.0000 +vt 0.5277 0.3835 0.0000 +vt 0.5323 0.4048 0.0000 +vt 0.5945 0.7713 0.0000 +vt 0.6251 0.1815 0.0000 +vt 0.6365 0.4674 0.0000 +vt 0.7583 0.4933 0.0000 +vt 0.7484 0.5253 0.0000 +vt 0.7302 0.5250 0.0000 +vt 0.7398 0.6069 0.0000 +vt 0.6925 0.6304 0.0000 +vt 0.6819 0.6101 0.0000 +vt 0.5160 0.3506 0.0000 +vt 0.5102 0.3521 0.0000 +vt 0.5188 0.3269 0.0000 +vt 0.7529 0.5667 0.0000 +vt 0.7737 0.5282 0.0000 +vt 0.8066 0.5304 0.0000 +vt 0.6068 0.2054 0.0000 +vt 0.5889 0.2094 0.0000 +vt 0.5914 0.2039 0.0000 +vt 0.7790 0.5747 0.0000 +vt 0.8264 0.4776 0.0000 +vt 0.8176 0.4259 0.0000 +vt 0.8998 0.4138 0.0000 +vt 0.8059 0.3678 0.0000 +vt 0.5123 0.3651 0.0000 +vt 0.5195 0.4396 0.0000 +vt 0.6613 0.2639 0.0000 +vt 0.6307 0.5044 0.0000 +vt 0.6418 0.4822 0.0000 +vt 0.5337 0.2895 0.0000 +vt 0.5524 0.0668 0.0000 +vt 0.6458 0.2115 0.0000 +vt 0.5245 0.3325 0.0000 +vt 0.6141 0.5347 0.0000 +vt 0.7909 0.4849 0.0000 +vt 0.6941 0.5613 0.0000 +vt 0.6256 0.1415 0.0000 +vt 0.6096 0.2049 0.0000 +vt 0.9000 0.3524 0.0000 +vt 0.5515 0.2303 0.0000 +vt 0.5709 0.3469 0.0000 +vt 0.5645 0.3412 0.0000 +vt 0.5747 0.2240 0.0000 +vt 0.6746 0.2107 0.0000 +vt 0.6652 0.0847 0.0000 +vt 0.6511 0.6939 0.0000 +vt 0.5274 0.4979 0.0000 +vt 0.7207 0.3628 0.0000 +vt 0.5729 0.2018 0.0000 +vt 0.6289 0.6150 0.0000 +vt 0.6339 0.6380 0.0000 +vt 0.5520 0.1991 0.0000 +vt 0.9949 0.3369 0.0000 +vt 0.9995 0.4038 0.0000 +vt 0.5281 0.1971 0.0000 +vt 0.6494 0.4952 0.0000 +vt 0.5698 0.2093 0.0000 +vt 0.5491 0.2099 0.0000 +vt 0.8023 0.1093 0.0000 +vt 0.8624 0.2316 0.0000 +vt 0.8703 0.1449 0.0000 +vt 0.5467 0.3737 0.0000 +vt 0.5529 0.2158 0.0000 +vt 0.6173 0.2034 0.0000 +vt 0.5588 0.0402 0.0000 +vt 0.5267 0.2312 0.0000 +vt 0.7295 0.5547 0.0000 +vt 0.6883 0.4705 0.0000 +vt 0.7097 0.4730 0.0000 +vt 0.7023 0.4497 0.0000 +vt 0.8959 0.4739 0.0000 +vt 0.5005 0.7724 0.0000 +vt 0.6340 0.5832 0.0000 +vt 0.5103 0.3214 0.0000 +vt 0.7183 0.5004 0.0000 +vt 0.7223 0.4825 0.0000 +vt 0.7349 0.4997 0.0000 +vt 0.5555 0.4858 0.0000 +vt 0.8313 0.5881 0.0000 +vt 0.6843 0.0486 0.0000 +vt 0.5357 0.3096 0.0000 +vt 0.5225 0.3673 0.0000 +vt 0.6052 0.5128 0.0000 +vt 0.5262 0.3575 0.0000 +vt 0.5981 0.5120 0.0000 +vt 0.5059 0.3513 0.0000 +vt 0.8860 0.2886 0.0000 +vt 0.9734 0.2673 0.0000 +vt 0.5380 0.3550 0.0000 +vt 0.8040 0.3108 0.0000 +vt 0.8029 0.2613 0.0000 +vt 0.5581 0.3352 0.0000 +vt 0.5573 0.3283 0.0000 +vt 0.7323 0.4549 0.0000 +vt 0.5458 0.3240 0.0000 +vt 0.9322 0.1972 0.0000 +vt 0.7099 0.4918 0.0000 +vt 0.2399 0.7066 0.0000 +vt 0.6343 0.5445 0.0000 +vt 0.5798 0.3590 0.0000 +vt 0.5256 0.2097 0.0000 +vt 0.5282 0.2152 0.0000 +vt 0.7007 0.4875 0.0000 +# 468 texture coords + + +vn -0.9892 0.0918 -0.1146 +vn -0.9788 0.0236 -0.2033 +vn -0.9677 -0.0121 -0.2518 +vn -0.0286 0.4641 -0.8853 +vn -0.0210 0.1059 -0.9942 +vn -0.2963 0.0263 -0.9547 +vn -0.2656 -0.3737 -0.8887 +vn -0.1333 -0.1062 -0.9854 +vn -0.2982 -0.3067 -0.9039 +vn -0.2701 0.4062 -0.8730 +vn -0.5118 0.1804 -0.8400 +vn -0.6858 -0.4508 -0.5714 +vn -0.4596 -0.4367 -0.7734 +vn -0.6024 -0.3459 -0.7194 +vn -0.6700 -0.2574 -0.6963 +vn -0.3874 -0.2160 -0.8962 +vn -0.4873 -0.2184 -0.8455 +vn -0.0187 0.7636 -0.6454 +vn -0.3895 0.6894 -0.6107 +vn -0.3730 0.8476 -0.3773 +vn -0.4425 -0.2135 -0.8710 +vn -0.6390 0.0497 -0.7676 +vn -0.3241 -0.1838 -0.9280 +vn -0.4361 0.4943 -0.7520 +vn -0.5509 0.4800 -0.6827 +vn -0.0096 0.1041 -0.9945 +vn -0.0117 -0.1221 -0.9924 +vn -0.2092 -0.1327 -0.9688 +vn -0.9011 0.2674 -0.3415 +vn -0.8776 0.0591 -0.4757 +vn -0.8804 -0.3287 -0.3418 +vn -0.5055 0.2486 -0.8262 +vn -0.5902 0.2855 -0.7551 +vn -0.6930 0.3322 -0.6398 +vn -0.4684 0.6694 -0.5766 +vn -0.4272 0.7368 -0.5240 +vn -0.2852 0.8727 -0.3964 +vn -0.3535 0.8216 -0.4473 +vn -0.3118 0.8767 -0.3662 +vn -0.5250 0.1467 -0.8384 +vn -0.4721 0.4437 -0.7617 +vn -0.2451 -0.0267 -0.9691 +vn -0.4187 -0.1407 -0.8972 +vn -0.5714 0.2908 -0.7675 +vn -0.5276 0.3879 -0.7558 +vn -0.7228 0.4014 -0.5625 +vn -0.1836 0.4449 -0.8765 +vn -0.0125 0.4693 -0.8829 +vn -0.0217 0.5490 -0.8355 +vn -0.7483 0.2841 -0.5994 +vn -0.4508 0.3894 -0.8032 +vn -0.7218 -0.1978 -0.6632 +vn -0.2589 0.4773 -0.8397 +vn -0.1985 0.5505 -0.8109 +vn -0.3127 0.5807 -0.7516 +vn -0.1325 0.5499 -0.8246 +vn 0.0988 0.3107 -0.9454 +vn -0.0383 0.4255 -0.9042 +vn -0.5889 0.2725 -0.7609 +vn -0.8103 0.4772 -0.3402 +vn -0.8348 0.3692 -0.4084 +vn -0.3030 -0.0161 -0.9529 +vn -0.4987 -0.0940 -0.8617 +vn -0.6857 0.2014 -0.6994 +vn -0.9601 -0.0063 -0.2796 +vn -0.9401 -0.0814 -0.3311 +vn -0.8443 -0.2348 -0.4818 +vn -0.5192 -0.4575 -0.7219 +vn -0.4560 -0.0053 -0.8899 +vn -0.0145 0.0191 -0.9997 +vn -0.4007 -0.1577 -0.9025 +vn -0.3961 -0.0224 -0.9179 +vn -0.1931 0.0337 -0.9806 +vn -0.6352 -0.3880 -0.6678 +vn -0.6957 0.1472 -0.7031 +vn -0.4450 0.1127 -0.8884 +vn -0.7920 0.2538 -0.5553 +vn -0.2588 0.1393 -0.9558 +vn -0.0160 0.0757 -0.9970 +vn -0.4640 0.3737 -0.8031 +vn -0.5965 -0.2402 -0.7659 +vn -0.5234 0.3510 -0.7764 +vn -0.2373 0.0020 -0.9714 +vn -0.2813 0.4791 -0.8315 +vn -0.3584 0.0892 -0.9293 +vn -0.2542 0.0002 -0.9671 +vn -0.6701 0.5630 -0.4837 +vn -0.7034 0.1121 -0.7019 +vn -0.6507 0.4083 -0.6402 +vn -0.7793 -0.1925 -0.5964 +vn -0.1515 0.3979 -0.9048 +vn -0.0209 0.3518 -0.9359 +vn -0.1058 0.5639 -0.8190 +vn -0.3450 0.6540 -0.6732 +vn -0.3752 0.7249 -0.5777 +vn -0.3356 0.6076 -0.7198 +vn -0.8198 -0.4081 -0.4018 +vn -0.6040 -0.5115 -0.6112 +vn -0.6003 -0.4769 -0.6420 +vn -0.8971 -0.1474 -0.4166 +vn -0.0088 -0.1756 -0.9844 +vn -0.0130 0.2566 -0.9664 +vn -0.6727 -0.1461 -0.7253 +vn -0.5253 -0.1978 -0.8276 +vn -0.5550 -0.1543 -0.8174 +vn -0.2962 0.5043 -0.8111 +vn -0.5151 0.3789 -0.7689 +vn -0.6769 0.4352 -0.5936 +vn -0.7119 -0.1376 -0.6887 +vn -0.3869 -0.2729 -0.8808 +vn -0.2593 0.9100 -0.3235 +vn -0.4232 0.8725 -0.2441 +vn -0.6388 0.6348 -0.4346 +vn 0.0075 -0.5272 -0.8497 +vn 0.1431 -0.3278 -0.9338 +vn 0.0417 -0.2968 -0.9540 +vn -0.9190 -0.2914 -0.2656 +vn -0.9525 -0.1975 -0.2320 +vn -0.8218 0.5259 -0.2193 +vn -0.7717 0.5717 -0.2788 +vn -0.8407 -0.2471 -0.4819 +vn -0.1589 0.6204 -0.7680 +vn -0.3844 0.3934 -0.8351 +vn -0.5135 0.2291 -0.8270 +vn -0.7775 -0.3931 -0.4910 +vn -0.7590 0.4870 -0.4321 +vn -0.5333 0.0772 -0.8424 +vn -0.2512 -0.2327 -0.9396 +vn -0.5037 0.2809 -0.8169 +vn -0.3684 0.3409 -0.8649 +vn -0.7436 -0.0832 -0.6634 +vn -0.6117 0.7847 -0.1002 +vn -0.5291 0.8080 -0.2592 +vn -0.4508 0.8443 -0.2898 +vn -0.6923 0.3110 -0.6511 +vn -0.8890 -0.0214 -0.4573 +vn -0.8997 0.1327 -0.4158 +vn -0.2615 0.0617 -0.9632 +vn -0.7042 -0.3851 -0.5965 +vn -0.4049 -0.7183 -0.5658 +vn -0.8981 0.0608 -0.4355 +vn -0.9788 0.1245 -0.1626 +vn -0.9079 0.1364 -0.3963 +vn -0.7298 -0.0858 -0.6783 +vn -0.4109 0.5683 -0.7129 +vn -0.2760 0.8715 -0.4054 +vn -0.0052 0.8916 -0.4528 +vn -0.4766 0.3068 -0.8238 +vn 0.0050 -0.1775 -0.9841 +vn -0.0091 -0.0562 -0.9984 +vn -0.3366 0.0198 -0.9414 +vn -0.3670 0.2717 -0.8897 +vn -0.3339 0.0046 -0.9426 +vn -0.3391 0.4495 -0.8264 +vn -0.6108 0.5190 -0.5979 +vn -0.7075 0.1706 -0.6858 +vn -0.4370 0.5756 -0.6911 +vn -0.1373 0.5563 -0.8196 +vn -0.6839 0.4104 -0.6032 +vn -0.4112 0.5547 -0.7234 +vn -0.9719 0.1950 -0.1316 +vn -0.8965 0.0314 -0.4419 +vn -0.3061 0.7640 -0.5679 +vn -0.2095 0.7295 -0.6511 +vn -0.6765 0.0404 -0.7353 +vn -0.7748 0.5551 -0.3026 +vn -0.3352 0.8062 -0.4875 +vn -0.9828 0.0737 -0.1690 +vn -0.6294 0.2746 -0.7270 +vn -0.4010 0.7990 -0.4481 +vn -0.7680 0.5065 -0.3919 +vn -0.7313 0.6102 -0.3048 +vn -0.6386 0.7024 -0.3143 +vn -0.5403 -0.0661 -0.8389 +vn -0.2972 0.0398 -0.9540 +vn -0.6776 -0.4136 -0.6081 +vn -0.0027 -0.5203 -0.8540 +vn -0.9184 0.2515 -0.3056 +vn -0.2748 0.5707 -0.7738 +vn -0.1584 0.1286 -0.9790 +vn -0.4616 -0.5618 -0.6866 +vn -0.4293 -0.0927 -0.8984 +vn -0.9793 0.1926 -0.0624 +vn -0.0161 -0.1523 -0.9882 +vn -0.2259 -0.2227 -0.9484 +vn -0.0197 -0.0720 -0.9972 +vn -0.2632 -0.1251 -0.9566 +vn -0.2093 -0.1177 -0.9707 +vn -0.4462 -0.5951 -0.6684 +vn -0.3734 -0.3688 -0.8512 +vn -0.4127 -0.7924 -0.4493 +vn -0.8775 0.4155 -0.2396 +vn -0.8941 0.4319 -0.1185 +vn -0.9429 0.3025 -0.1392 +vn -0.9468 0.3122 -0.0776 +vn -0.4967 0.7780 -0.3847 +vn -0.2129 0.8951 -0.3917 +vn -0.0010 -0.6457 -0.7636 +vn -0.0191 0.3220 -0.9466 +vn -0.2007 0.8540 -0.4801 +vn -0.5261 -0.2296 -0.8189 +vn -0.5469 -0.1438 -0.8248 +vn -0.9882 0.1379 -0.0665 +vn -0.2607 -0.1418 -0.9549 +vn -0.3010 0.8206 -0.4858 +vn -0.2486 0.9237 -0.2915 +vn -0.1986 0.7334 -0.6502 +vn -0.2171 0.9455 -0.2426 +vn -0.3870 0.6895 -0.6122 +vn -0.0087 -0.5839 -0.8117 +vn -0.5436 -0.1897 -0.8176 +vn -0.5570 -0.2589 -0.7891 +vn -0.4501 0.2685 -0.8516 +vn -0.7925 0.0362 -0.6087 +vn -0.6696 0.5211 -0.5292 +vn -0.8579 -0.2632 -0.4412 +vn -0.9774 0.0665 -0.2005 +vn -0.8059 -0.4189 -0.4185 +vn -0.8334 -0.3312 -0.4425 +vn -0.0113 0.7507 -0.6605 +vn -0.5000 0.8023 -0.3261 +vn -0.0179 0.1168 -0.9930 +vn -0.0280 0.7348 -0.6777 +vn -0.0341 0.8515 -0.5232 +vn -0.8728 -0.3807 -0.3053 +vn -0.2925 -0.1250 -0.9481 +vn -0.2521 -0.4913 -0.8337 +vn -0.5752 -0.1476 -0.8046 +vn -0.5558 0.7877 -0.2655 +vn -0.3244 0.4596 -0.8268 +vn -0.6118 0.2479 -0.7511 +vn -0.3883 -0.3420 -0.8557 +vn -0.9704 0.2327 -0.0645 +vn -0.9662 0.2260 -0.1243 +vn -0.0165 0.5612 -0.8275 +vn -0.8997 0.3056 -0.3117 +vn -0.1538 0.8423 -0.5165 +vn 0.0106 0.9761 -0.2172 +vn -0.4197 0.4256 -0.8017 +vn -0.2580 0.5206 -0.8139 +vn -0.5099 -0.4374 -0.7407 +vn -0.7786 -0.4123 -0.4731 +vn -0.6680 0.4185 -0.6154 +vn 0.9885 0.0946 -0.1177 +vn 0.9766 0.0763 -0.2009 +vn 0.9707 -0.0059 -0.2403 +vn 0.2175 0.4167 -0.8827 +vn 0.2655 0.0332 -0.9635 +vn 0.2465 -0.3758 -0.8933 +vn 0.4508 -0.4321 -0.7811 +vn 0.2787 -0.3017 -0.9118 +vn 0.3870 0.4936 -0.7788 +vn 0.4777 0.1827 -0.8593 +vn 0.6807 -0.4529 -0.5758 +vn 0.7749 -0.3960 -0.4927 +vn 0.5928 -0.3359 -0.7320 +vn 0.5041 -0.4457 -0.7397 +vn 0.6609 -0.2685 -0.7009 +vn 0.7711 -0.1906 -0.6075 +vn 0.4693 -0.2150 -0.8565 +vn -0.0176 0.9138 -0.4057 +vn 0.3385 0.8619 -0.3777 +vn 0.4241 -0.2022 -0.8827 +vn 0.2284 -0.2246 -0.9473 +vn 0.3009 -0.1708 -0.9382 +vn 0.4152 0.6914 -0.5913 +vn 0.5263 0.4569 -0.7171 +vn 0.1372 0.1315 -0.9818 +vn 0.1889 -0.1299 -0.9734 +vn 0.8941 0.2902 -0.3410 +vn 0.9565 -0.1796 -0.2300 +vn 0.8827 -0.3064 -0.3563 +vn 0.4749 0.2725 -0.8368 +vn 0.5803 0.2684 -0.7689 +vn 0.6698 0.3602 -0.6493 +vn 0.3502 0.8087 -0.4726 +vn 0.3789 0.7560 -0.5337 +vn 0.1939 0.9029 -0.3835 +vn 0.0992 0.9694 -0.2244 +vn 0.2482 0.8870 -0.3894 +vn 0.4589 0.4349 -0.7748 +vn 0.2199 -0.0208 -0.9753 +vn 0.5447 0.3217 -0.7745 +vn 0.6608 0.4456 -0.6039 +vn 0.7042 0.4225 -0.5706 +vn 0.1420 0.4548 -0.8792 +vn 0.2331 0.5063 -0.8303 +vn 0.8500 -0.0556 -0.5238 +vn 0.6186 -0.3893 -0.6824 +vn 0.7050 -0.2003 -0.6803 +vn 0.2278 0.4733 -0.8510 +vn 0.3290 0.5971 -0.7316 +vn 0.2896 0.5777 -0.7632 +vn 0.1057 0.5527 -0.8267 +vn 0.2923 0.4695 -0.8331 +vn 0.0250 0.4179 -0.9081 +vn 0.5611 0.3112 -0.7670 +vn 0.4233 0.4058 -0.8100 +vn 0.7948 0.5049 -0.3366 +vn 0.8680 0.4384 -0.2332 +vn 0.8266 0.3904 -0.4053 +vn 0.2732 -0.0165 -0.9618 +vn 0.6635 0.0658 -0.7453 +vn 0.6643 0.2138 -0.7162 +vn 0.9600 -0.0003 -0.2800 +vn 0.8960 -0.1414 -0.4210 +vn 0.8452 -0.2504 -0.4722 +vn 0.5089 -0.4481 -0.7350 +vn -0.0089 -0.4314 -0.9021 +vn 0.3708 -0.1626 -0.9144 +vn 0.1925 -0.1126 -0.9748 +vn 0.1658 0.0472 -0.9850 +vn 0.5831 -0.2210 -0.7818 +vn 0.6667 0.1757 -0.7243 +vn 0.4231 0.1187 -0.8983 +vn 0.6085 0.2868 -0.7400 +vn 0.7769 0.2723 -0.5677 +vn 0.2238 0.1445 -0.9639 +vn 0.4823 0.3914 -0.7837 +vn 0.4059 -0.0703 -0.9112 +vn 0.1984 0.0143 -0.9800 +vn -0.0156 0.0695 -0.9975 +vn 0.3273 0.0921 -0.9404 +vn 0.2286 0.0054 -0.9735 +vn 0.6102 0.7222 -0.3257 +vn 0.6443 0.5803 -0.4981 +vn 0.4969 0.1416 -0.8562 +vn 0.4749 -0.0910 -0.8753 +vn 0.6870 0.1214 -0.7165 +vn 0.8579 -0.2672 -0.4390 +vn 0.7796 -0.1825 -0.5992 +vn 0.1208 0.3971 -0.9098 +vn 0.1075 0.5451 -0.8314 +vn 0.0761 0.5486 -0.8326 +vn 0.3651 0.7087 -0.6037 +vn 0.8210 -0.3904 -0.4167 +vn 0.8331 -0.3228 -0.4492 +vn 0.5980 -0.4679 -0.6507 +vn 0.2695 0.5104 -0.8166 +vn 0.6652 -0.1336 -0.7347 +vn 0.7261 -0.0753 -0.6835 +vn 0.5408 -0.1514 -0.8274 +vn 0.6207 0.4346 -0.6526 +vn 0.3602 0.6969 -0.6202 +vn 0.2923 0.8174 -0.4963 +vn 0.6549 0.4616 -0.5984 +vn 0.7013 -0.1214 -0.7024 +vn 0.3127 0.0149 -0.9498 +vn 0.3730 -0.2646 -0.8893 +vn 0.2068 0.9225 -0.3261 +vn 0.4428 0.8057 -0.3933 +vn 0.6128 0.6523 -0.4461 +vn -0.0282 -0.5216 -0.8527 +vn 0.2269 -0.4823 -0.8461 +vn -0.0625 -0.2963 -0.9530 +vn 0.9255 -0.2612 -0.2742 +vn 0.8782 -0.3583 -0.3167 +vn 0.7431 0.5356 -0.4013 +vn 0.7497 0.5979 -0.2835 +vn 0.8369 -0.2377 -0.4930 +vn 0.1306 0.5947 -0.7933 +vn 0.2395 0.5098 -0.8263 +vn 0.4942 0.2256 -0.8396 +vn 0.4387 0.0211 -0.8984 +vn 0.7810 0.0588 -0.6218 +vn 0.7757 -0.3764 -0.5066 +vn 0.2367 -0.1436 -0.9609 +vn 0.5078 0.1003 -0.8556 +vn 0.1036 -0.1009 -0.9895 +vn 0.4829 0.2882 -0.8269 +vn 0.4273 0.5748 -0.6979 +vn 0.3231 0.6484 -0.6894 +vn 0.7422 -0.0986 -0.6628 +vn 0.5223 -0.0708 -0.8498 +vn 0.3597 0.3844 -0.8502 +vn 0.5795 0.8063 -0.1185 +vn 0.4603 0.8254 -0.3268 +vn 0.3691 0.8831 -0.2895 +vn 0.6861 0.3121 -0.6571 +vn 0.6473 0.4401 -0.6223 +vn 0.8993 0.1483 -0.4114 +vn 0.2468 0.0393 -0.9683 +vn 0.4702 -0.7357 -0.4875 +vn 0.4528 -0.6808 -0.5758 +vn 0.8966 -0.0343 -0.4415 +vn 0.8987 0.0843 -0.4303 +vn 0.8959 0.0466 -0.4419 +vn 0.9774 0.1340 -0.1635 +vn 0.9007 0.1575 -0.4050 +vn 0.3724 0.5882 -0.7179 +vn 0.6001 -0.5021 -0.6227 +vn 0.4579 0.3117 -0.8325 +vn -0.1567 -0.3306 -0.9307 +vn -0.0155 -0.0506 -0.9986 +vn 0.3119 0.0191 -0.9499 +vn 0.3392 0.2827 -0.8972 +vn 0.3362 0.4579 -0.8230 +vn 0.5374 0.7997 -0.2676 +vn -0.1332 0.2907 -0.9475 +vn 0.7012 0.1840 -0.6888 +vn 0.1714 0.5455 -0.8204 +vn 0.5580 0.3128 -0.7686 +vn 0.5971 0.3016 -0.7433 +vn 0.9675 0.2147 -0.1340 +vn 0.2314 0.7831 -0.5773 +vn 0.7580 0.5782 -0.3018 +vn 0.2670 0.8375 -0.4768 +vn 0.2693 0.8599 -0.4336 +vn 0.5067 0.3950 -0.7663 +vn 0.7394 0.5132 -0.4357 +vn 0.3673 -0.2156 -0.9047 +vn 0.6777 -0.3981 -0.6182 +vn 0.6185 0.0661 -0.7830 +vn 0.4711 -0.5517 -0.6882 +vn 0.2506 0.5734 -0.7800 +vn 0.2726 0.0404 -0.9613 +vn 0.3665 -0.3395 -0.8662 +vn 0.9744 0.2145 -0.0671 +vn 0.9857 0.1509 -0.0744 +vn 0.2074 -0.2071 -0.9561 +vn -0.0326 -0.1888 -0.9815 +vn 0.4509 -0.5767 -0.6812 +vn 0.3959 -0.2961 -0.8693 +vn 0.8077 0.5514 -0.2088 +vn 0.9332 0.3326 -0.1365 +vn 0.8820 0.4566 -0.1162 +vn 0.8617 0.1065 -0.4962 +vn 0.1504 0.9084 -0.3900 +vn 0.4885 0.3529 -0.7980 +vn 0.3556 0.7052 -0.6134 +vn 0.1387 0.7361 -0.6625 +vn 0.3951 0.5494 -0.7363 +vn 0.3690 -0.0160 -0.9293 +vn 0.5278 -0.1434 -0.8372 +vn 0.3953 -0.1320 -0.9090 +vn 0.9794 0.0344 -0.1991 +vn -0.0106 -0.1659 -0.9861 +vn 0.1745 0.7218 -0.6697 +vn 0.1633 0.9568 -0.2405 +vn 0.4306 0.2942 -0.8532 +vn 0.5371 -0.1872 -0.8225 +vn 0.3508 0.3438 -0.8710 +vn 0.8106 -0.3958 -0.4315 +vn 0.9431 -0.0884 -0.3207 +vn 0.7107 0.6303 -0.3125 +vn 0.4906 0.3956 -0.7764 +vn 0.6379 0.5420 -0.5471 +vn 0.2648 -0.1351 -0.9548 +vn 0.5070 0.8298 -0.2331 +vn 0.5564 -0.1294 -0.8208 +vn 0.2610 0.8806 -0.3955 +vn 0.9583 0.2570 -0.1252 +vn 0.9614 0.2663 -0.0692 +vn 0.3949 0.8811 -0.2603 +vn 0.9102 0.2754 -0.3092 +vn 0.8881 0.3375 -0.3120 +vn 0.1150 0.8695 -0.4803 +vn 0.3658 0.4631 -0.8073 +vn 0.5063 -0.1983 -0.8392 +vn 0.5772 0.5500 -0.6036 +vn 0.9361 0.3433 -0.0766 +vn 0.5392 -0.2542 -0.8029 +vn -0.7761 -0.1922 -0.6006 +vn -0.0115 0.3481 -0.9374 +vn 0.9827 0.0780 -0.1680 +vn 0.2198 -0.1358 -0.9660 +vn 0.1342 0.8481 -0.5125 +vn 0.4880 -0.2447 -0.8379 +# 468 vertex normals + +#o default +g default +#usemtl 07___Default +#s 1 +f 1/1/1 2/2/2 3/3/3 +f 4/4/4 5/5/5 6/6/6 +f 7/7/7 8/8/8 9/9/9 +f 10/10/10 6/6/6 11/11/11 +f 12/12/12 13/13/13 14/14/14 +f 7/7/7 13/13/13 12/12/12 +f 15/15/15 16/16/16 17/17/17 +f 18/18/18 19/19/19 20/20/20 +f 21/21/21 22/22/22 23/23/23 +f 24/24/24 11/11/11 25/25/25 +f 26/26/26 27/27/27 28/28/28 +f 29/29/29 30/30/30 31/31/31 +f 32/32/32 33/33/33 34/34/34 +f 35/35/35 25/25/25 36/36/36 +f 37/37/37 38/38/38 39/39/39 +f 25/25/25 40/40/40 41/41/41 +f 42/42/42 43/43/43 21/21/21 +f 44/44/44 45/45/45 46/46/46 +f 47/47/47 48/48/48 49/49/49 +f 50/50/50 51/51/51 52/52/52 +f 53/53/53 54/54/54 55/55/55 +f 56/56/56 57/57/57 58/58/58 +f 59/59/59 33/33/33 32/32/32 +f 60/60/60 46/46/46 61/61/61 +f 62/62/62 63/63/63 64/64/64 +f 65/65/65 66/66/66 67/67/67 +f 68/68/68 69/69/69 70/70/70 +f 71/71/71 72/72/72 73/73/73 +f 74/74/74 52/52/52 75/75/75 +f 76/76/76 22/22/22 77/77/77 +f 78/78/78 79/79/79 48/48/48 +f 75/75/75 59/59/59 80/80/80 +f 81/81/81 75/75/75 82/82/82 +f 83/83/83 84/84/84 49/49/49 +f 85/85/85 62/62/62 86/86/86 +f 20/20/20 19/19/19 87/87/87 +f 40/40/40 25/25/25 11/11/11 +f 88/88/88 89/89/89 90/90/90 +f 91/91/91 92/92/92 93/93/93 +f 94/94/94 95/95/95 96/96/96 +f 97/97/97 98/98/98 99/99/99 +f 100/100/100 67/67/67 15/15/15 +f 88/88/88 101/101/101 102/102/102 +f 103/103/103 104/104/104 105/105/105 +f 89/89/89 88/88/88 106/106/106 +f 64/64/64 107/107/107 108/108/108 +f 109/109/109 14/14/14 110/110/110 +f 111/111/111 112/112/112 113/113/113 +f 114/114/114 115/115/115 116/116/116 +f 117/117/117 118/118/118 31/31/31 +f 60/60/60 119/119/119 120/120/120 +f 14/14/14 109/109/109 121/121/121 +f 122/122/122 123/123/123 124/124/124 +f 69/69/69 68/68/68 125/125/125 +f 34/34/34 126/126/126 87/87/87 +f 17/17/17 16/16/16 28/28/28 +f 127/127/127 59/59/59 75/75/75 +f 42/42/42 128/128/128 9/9/9 +f 129/129/129 130/130/130 94/94/94 +f 131/131/131 124/124/124 123/123/123 +f 132/132/132 133/133/133 134/134/134 +f 135/135/135 136/136/136 137/137/137 +f 138/138/138 139/139/139 140/140/140 +f 135/135/135 124/124/124 131/131/131 +f 141/141/141 2/2/2 142/142/142 +f 143/143/143 103/103/103 144/144/144 +f 145/145/145 146/146/146 147/147/147 +f 97/97/97 125/125/125 68/68/68 +f 148/148/148 85/85/85 76/76/76 +f 115/115/115 149/149/149 150/150/150 +f 11/11/11 6/6/6 151/151/151 +f 79/79/79 78/78/78 152/152/152 +f 86/86/86 153/153/153 110/110/110 +f 154/154/154 45/45/45 44/44/44 +f 133/133/133 155/155/155 108/108/108 +f 93/93/93 92/92/92 57/57/57 +f 156/156/156 129/129/129 157/157/157 +f 53/53/53 91/91/91 158/158/158 +f 33/33/33 44/44/44 159/159/159 +f 157/157/157 160/160/160 135/135/135 +f 127/127/127 44/44/44 33/33/33 +f 139/139/139 50/50/50 74/74/74 +f 161/161/161 143/143/143 162/162/162 +f 163/163/163 164/164/164 10/10/10 +f 62/62/62 165/165/165 153/153/153 +f 166/166/166 64/64/64 167/167/167 +f 118/118/118 168/168/168 166/166/166 +f 163/163/163 24/24/24 35/35/35 +f 45/45/45 148/148/148 169/169/169 +f 38/38/38 35/35/35 170/170/170 +f 171/171/171 126/126/126 34/34/34 +f 126/126/126 172/172/172 173/173/173 +f 174/174/174 175/175/175 16/16/16 +f 176/176/176 177/177/177 101/101/101 +f 143/143/143 178/178/178 77/77/77 +f 140/140/140 74/74/74 81/81/81 +f 179/179/179 106/106/106 180/180/180 +f 181/181/181 81/81/81 182/182/182 +f 23/23/23 110/110/110 9/9/9 +f 131/131/131 174/174/174 15/15/15 +f 183/183/183 161/161/161 142/142/142 +f 184/184/184 185/185/185 83/83/83 +f 165/165/165 168/168/168 118/118/118 +f 186/186/186 187/187/187 185/185/185 +f 106/106/106 102/102/102 26/26/26 +f 110/110/110 14/14/14 13/13/13 +f 188/188/188 73/73/73 150/150/150 +f 189/189/189 181/181/181 190/190/190 +f 177/177/177 176/176/176 99/99/99 +f 189/189/189 191/191/191 140/140/140 +f 192/192/192 193/193/193 119/119/119 +f 194/194/194 195/195/195 193/193/193 +f 30/30/30 29/29/29 196/196/196 +f 38/38/38 37/37/37 197/197/197 +f 198/198/198 98/98/98 68/68/68 +f 127/127/127 52/52/52 51/51/51 +f 19/19/19 18/18/18 199/199/199 +f 197/197/197 200/200/200 164/164/164 +f 124/124/124 135/135/135 160/160/160 +f 71/71/71 201/201/201 202/202/202 +f 123/123/123 179/179/179 175/175/175 +f 43/43/43 104/104/104 103/103/103 +f 2/2/2 1/1/1 203/203/203 +f 180/180/180 28/28/28 16/16/16 +f 204/204/204 28/28/28 27/27/27 +f 29/29/29 166/166/166 205/205/205 +f 139/139/139 138/138/138 206/206/206 +f 165/165/165 117/117/117 109/109/109 +f 144/144/144 156/156/156 141/141/141 +f 103/103/103 143/143/143 22/22/22 +f 207/207/207 179/179/179 123/123/123 +f 147/147/147 146/146/146 208/208/208 +f 209/209/209 106/106/106 179/179/179 +f 98/98/98 198/198/198 210/210/210 +f 211/211/211 212/212/212 213/213/213 +f 214/214/214 215/215/215 145/145/145 +f 136/136/136 66/66/66 3/3/3 +f 176/176/176 88/88/88 216/216/216 +f 94/94/94 130/130/130 213/213/213 +f 66/66/66 65/65/65 217/217/217 +f 126/126/126 171/171/171 120/120/120 +f 218/218/218 219/219/219 99/99/99 +f 148/148/148 41/41/41 40/40/40 +f 220/220/220 107/107/107 151/151/151 +f 208/208/208 146/146/146 221/221/221 +f 222/222/222 151/151/151 6/6/6 +f 10/10/10 164/164/164 223/223/223 +f 164/164/164 200/200/200 224/224/224 +f 131/131/131 67/67/67 66/66/66 +f 129/129/129 156/156/156 144/144/144 +f 23/23/23 22/22/22 76/76/76 +f 85/85/85 40/40/40 63/63/63 +f 117/117/117 225/225/225 121/121/121 +f 63/63/63 151/151/151 107/107/107 +f 214/214/214 30/30/30 113/113/113 +f 226/226/226 227/227/227 228/228/228 +f 229/229/229 132/132/132 221/221/221 +f 46/46/46 60/60/60 171/171/171 +f 230/230/230 58/58/58 226/226/226 +f 19/19/19 152/152/152 231/231/231 +f 146/146/146 145/145/145 215/215/215 +f 185/185/185 187/187/187 232/232/232 +f 83/83/83 185/185/185 190/190/190 +f 84/84/84 83/83/83 182/182/182 +f 47/47/47 84/84/84 82/82/82 +f 78/78/78 47/47/47 80/80/80 +f 161/161/161 183/183/183 233/233/233 +f 50/50/50 139/139/139 39/39/39 +f 51/51/51 50/50/50 170/170/170 +f 154/154/154 51/51/51 36/36/36 +f 45/45/45 154/154/154 41/41/41 +f 46/46/46 169/169/169 77/77/77 +f 2/2/2 141/141/141 137/137/137 +f 112/112/112 229/229/229 215/215/215 +f 143/143/143 161/161/161 234/234/234 +f 145/145/145 235/235/235 70/70/70 +f 78/78/78 32/32/32 231/231/231 +f 166/166/166 168/168/168 165/165/165 +f 236/236/236 194/194/194 192/192/192 +f 237/237/237 111/111/111 196/196/196 +f 134/134/134 108/108/108 107/107/107 +f 220/220/220 238/238/238 208/208/208 +f 239/239/239 237/237/237 205/205/205 +f 72/72/72 202/202/202 104/104/104 +f 211/211/211 130/130/130 129/129/129 +f 73/73/73 72/72/72 43/43/43 +f 150/150/150 73/73/73 42/42/42 +f 116/116/116 150/150/150 8/8/8 +f 227/227/227 116/116/116 7/7/7 +f 89/89/89 230/230/230 228/228/228 +f 209/209/209 56/56/56 230/230/230 +f 93/93/93 56/56/56 209/209/209 +f 158/158/158 93/93/93 207/207/207 +f 54/54/54 158/158/158 122/122/122 +f 55/55/55 54/54/54 240/240/240 +f 94/94/94 55/55/55 160/160/160 +f 132/132/132 112/112/112 133/133/133 +f 111/111/111 237/237/237 239/239/239 +f 155/155/155 239/239/239 167/167/167 +f 178/178/178 234/234/234 194/194/194 +f 133/133/133 112/112/112 111/111/111 +f 77/77/77 178/178/178 236/236/236 +f 227/227/227 241/241/241 90/90/90 +f 241/241/241 12/12/12 216/216/216 +f 12/12/12 242/242/242 218/218/218 +f 242/242/242 121/121/121 219/219/219 +f 31/31/31 30/30/30 214/214/214 +f 121/121/121 225/225/225 97/97/97 +f 225/225/225 31/31/31 125/125/125 +f 234/234/234 233/233/233 195/195/195 +f 141/141/141 156/156/156 243/243/243 +f 202/202/202 201/201/201 212/212/212 +f 104/104/104 202/202/202 211/211/211 +f 244/244/244 245/245/245 246/246/246 +f 4/4/4 247/247/247 248/248/248 +f 249/249/249 250/250/250 251/251/251 +f 247/247/247 252/252/252 253/253/253 +f 254/254/254 255/255/255 256/256/256 +f 249/249/249 257/257/257 254/254/254 +f 258/258/258 259/259/259 260/260/260 +f 18/18/18 261/261/261 262/262/262 +f 263/263/263 264/264/264 265/265/265 +f 252/252/252 266/266/266 267/267/267 +f 26/26/26 268/268/268 269/269/269 +f 270/270/270 271/271/271 272/272/272 +f 273/273/273 274/274/274 275/275/275 +f 266/266/266 276/276/276 277/277/277 +f 278/278/278 279/279/279 280/280/280 +f 267/267/267 277/277/277 281/281/281 +f 282/282/282 264/264/264 263/263/263 +f 283/283/283 284/284/284 285/285/285 +f 286/286/286 287/287/287 49/49/49 +f 288/288/288 289/289/289 290/290/290 +f 291/291/291 292/292/292 293/293/293 +f 294/294/294 295/295/295 296/296/296 +f 297/297/297 298/298/298 273/273/273 +f 299/299/299 300/300/300 301/301/301 +f 302/302/302 303/303/303 304/304/304 +f 305/305/305 306/306/306 307/307/307 +f 308/308/308 309/309/309 70/70/70 +f 310/310/310 311/311/311 312/312/312 +f 289/289/289 313/313/313 314/314/314 +f 315/315/315 316/316/316 317/317/317 +f 318/318/318 286/286/286 48/48/48 +f 314/314/314 319/319/319 298/298/298 +f 313/313/313 320/320/320 319/319/319 +f 321/321/321 322/322/322 49/49/49 +f 323/323/323 315/315/315 324/324/324 +f 262/262/262 325/325/325 326/326/326 +f 327/327/327 328/328/328 253/253/253 +f 329/329/329 330/330/330 331/331/331 +f 332/332/332 333/333/333 334/334/334 +f 335/335/335 293/293/293 292/292/292 +f 336/336/336 337/337/337 338/338/338 +f 306/306/306 259/259/259 258/258/258 +f 329/329/329 339/339/339 102/102/102 +f 340/340/340 341/341/341 342/342/342 +f 343/343/343 344/344/344 339/339/339 +f 304/304/304 345/345/345 346/346/346 +f 347/347/347 348/348/348 349/349/349 +f 350/350/350 351/351/351 352/352/352 +f 353/353/353 354/354/354 355/355/355 +f 356/356/356 357/357/357 272/272/272 +f 299/299/299 358/358/358 359/359/359 +f 256/256/256 255/255/255 360/360/360 +f 361/361/361 362/362/362 363/363/363 +f 364/364/364 365/365/365 366/366/366 +f 275/275/275 274/274/274 326/326/326 +f 260/260/260 367/367/367 269/269/269 +f 368/368/368 290/290/290 314/314/314 +f 282/282/282 369/369/369 251/251/251 +f 370/370/370 371/371/371 372/372/372 +f 373/373/373 374/374/374 375/375/375 +f 376/376/376 377/377/377 378/378/378 +f 379/379/379 380/380/380 381/381/381 +f 382/382/382 383/383/383 384/384/384 +f 379/379/379 385/385/385 373/373/373 +f 386/386/386 387/387/387 388/388/388 +f 389/389/389 387/387/387 341/341/341 +f 390/390/390 235/235/235 147/147/147 +f 336/336/336 391/391/391 308/308/308 +f 392/392/392 316/316/316 315/315/315 +f 393/393/393 355/355/355 394/394/394 +f 253/253/253 328/328/328 395/395/395 +f 79/79/79 199/199/199 396/396/396 +f 324/324/324 265/265/265 349/349/349 +f 397/397/397 368/368/368 283/283/283 +f 398/398/398 378/378/378 346/346/346 +f 334/334/334 294/294/294 399/399/399 +f 400/400/400 380/380/380 371/371/371 +f 291/291/291 401/401/401 333/333/333 +f 402/402/402 275/275/275 284/284/284 +f 371/371/371 380/380/380 379/379/379 +f 368/368/368 297/297/297 402/402/402 +f 403/403/403 384/384/384 289/289/289 +f 404/404/404 388/388/388 387/387/387 +f 405/405/405 252/252/252 247/247/247 +f 302/302/302 324/324/324 348/348/348 +f 406/406/406 407/407/407 345/345/345 +f 271/271/271 270/270/270 406/406/406 +f 405/405/405 408/408/408 266/266/266 +f 409/409/409 285/285/285 316/316/316 +f 408/408/408 280/280/280 276/276/276 +f 358/358/358 284/284/284 275/275/275 +f 410/410/410 326/326/326 325/325/325 +f 374/374/374 258/258/258 411/411/411 +f 412/412/412 329/329/329 101/101/101 +f 389/389/389 413/413/413 317/317/317 +f 384/384/384 414/414/414 313/313/313 +f 415/415/415 416/416/416 268/268/268 +f 414/414/414 417/417/417 320/320/320 +f 265/265/265 264/264/264 251/251/251 +f 373/373/373 307/307/307 258/258/258 +f 418/418/418 419/419/419 388/388/388 +f 184/184/184 322/322/322 321/321/321 +f 303/303/303 356/356/356 271/271/271 +f 186/186/186 184/184/184 420/420/420 +f 339/339/339 268/268/268 26/26/26 +f 349/349/349 251/251/251 250/250/250 +f 311/311/311 421/421/421 394/394/394 +f 422/422/422 423/423/423 417/417/417 +f 177/177/177 210/210/210 338/338/338 +f 422/422/422 414/414/414 384/384/384 +f 300/300/300 299/299/299 424/424/424 +f 425/425/425 300/300/300 426/426/426 +f 427/427/427 352/352/352 351/351/351 +f 408/408/408 405/405/405 428/428/428 +f 198/198/198 309/309/309 308/308/308 +f 368/368/368 397/397/397 429/429/429 +f 430/430/430 396/396/396 199/199/199 +f 428/428/428 405/405/405 431/431/431 +f 363/363/363 362/362/362 432/432/432 +f 310/310/310 433/433/433 434/434/434 +f 375/375/375 374/374/374 416/416/416 +f 435/435/435 263/263/263 340/340/340 +f 436/436/436 388/388/388 419/419/419 +f 268/268/268 416/416/416 411/411/411 +f 367/367/367 437/437/437 27/27/27 +f 270/270/270 351/351/351 407/407/407 +f 403/403/403 280/280/280 279/279/279 +f 303/303/303 348/348/348 347/347/347 +f 341/341/341 387/387/387 386/386/386 +f 340/340/340 263/263/263 413/413/413 +f 438/438/438 361/361/361 375/375/375 +f 147/147/147 238/238/238 439/439/439 +f 344/344/344 438/438/438 415/415/415 +f 391/391/391 338/338/338 210/210/210 +f 440/440/440 441/441/441 442/442/442 +f 365/365/365 364/364/364 390/390/390 +f 385/385/385 381/381/381 246/246/246 +f 412/412/412 443/443/443 330/330/330 +f 440/440/440 372/372/372 335/335/335 +f 444/444/444 246/246/246 245/245/245 +f 410/410/410 445/445/445 359/359/359 +f 443/443/443 412/412/412 338/338/338 +f 392/392/392 323/323/323 327/327/327 +f 220/220/220 222/222/222 395/395/395 +f 439/439/439 378/378/378 377/377/377 +f 222/222/222 5/5/5 248/248/248 +f 247/247/247 4/4/4 223/223/223 +f 431/431/431 223/223/223 224/224/224 +f 373/373/373 385/385/385 444/444/444 +f 370/370/370 342/342/342 341/341/341 +f 265/265/265 324/324/324 315/315/315 +f 323/323/323 302/302/302 328/328/328 +f 356/356/356 347/347/347 360/360/360 +f 328/328/328 304/304/304 446/446/446 +f 365/365/365 447/447/447 352/352/352 +f 354/354/354 353/353/353 448/448/448 +f 449/449/449 447/447/447 377/377/377 +f 285/285/285 284/284/284 358/358/358 +f 295/295/295 450/450/450 448/448/448 +f 430/430/430 326/326/326 274/274/274 +f 451/451/451 377/377/377 447/447/447 +f 420/420/420 417/417/417 423/423/423 +f 321/321/321 320/320/320 417/417/417 +f 287/287/287 319/319/319 320/320/320 +f 286/286/286 298/298/298 319/319/319 +f 318/318/318 273/273/273 298/298/298 +f 404/404/404 452/452/452 453/453/453 +f 288/288/288 276/276/276 280/280/280 +f 429/429/429 277/277/277 276/276/276 +f 397/397/397 281/281/281 277/277/277 +f 409/409/409 392/392/392 281/281/281 +f 285/285/285 301/301/301 317/317/317 +f 436/436/436 246/246/246 381/381/381 +f 454/454/454 352/352/352 447/447/447 +f 389/389/389 455/455/455 452/452/452 +f 390/390/390 364/364/364 70/70/70 +f 318/318/318 396/396/396 274/274/274 +f 406/406/406 304/304/304 303/303/303 +f 456/456/456 301/301/301 300/300/300 +f 457/457/457 407/407/407 351/351/351 +f 378/378/378 439/439/439 446/446/446 +f 220/220/220 446/446/446 439/439/439 +f 458/458/458 345/345/345 407/407/407 +f 433/433/433 435/435/435 459/459/459 +f 441/441/441 342/342/342 370/370/370 +f 312/312/312 282/282/282 435/435/435 +f 394/394/394 369/369/369 282/282/282 +f 355/355/355 249/249/249 369/369/369 +f 354/354/354 257/257/257 249/249/249 +f 343/343/343 331/331/331 450/450/450 +f 344/344/344 343/343/343 295/295/295 +f 334/334/334 438/438/438 344/344/344 +f 333/333/333 361/361/361 438/438/438 +f 401/401/401 362/362/362 361/361/361 +f 293/293/293 432/432/432 362/362/362 +f 372/372/372 371/371/371 432/432/432 +f 449/449/449 376/376/376 398/398/398 +f 457/457/457 350/350/350 460/460/460 +f 460/460/460 346/346/346 345/345/345 +f 455/455/455 456/456/456 425/425/425 +f 398/398/398 460/460/460 350/350/350 +f 317/317/317 301/301/301 456/456/456 +f 354/354/354 450/450/450 331/331/331 +f 257/257/257 331/331/331 330/330/330 +f 254/254/254 330/330/330 443/443/443 +f 255/255/255 443/443/443 337/337/337 +f 272/272/272 366/366/366 365/365/365 +f 360/360/360 337/337/337 336/336/336 +f 357/357/357 336/336/336 366/366/366 +f 452/452/452 425/425/425 461/461/461 +f 386/386/386 381/381/381 380/380/380 +f 434/434/434 441/441/441 462/462/462 +f 459/459/459 342/342/342 441/441/441 +f 226/226/226 228/228/228 230/230/230 +f 226/226/226 114/114/114 227/227/227 +f 213/213/213 95/95/95 94/94/94 +f 213/213/213 130/130/130 211/211/211 +f 296/296/296 399/399/399 294/294/294 +f 448/448/448 296/296/296 295/295/295 +f 448/448/448 450/450/450 354/354/354 +f 440/440/440 442/442/442 372/372/372 +f 440/440/440 462/462/462 441/441/441 +f 335/335/335 372/372/372 293/293/293 +f 239/239/239 155/155/155 111/111/111 +f 132/132/132 229/229/229 112/112/112 +f 217/217/217 1/1/1 3/3/3 +f 10/10/10 4/4/4 6/6/6 +f 13/13/13 7/7/7 9/9/9 +f 24/24/24 10/10/10 11/11/11 +f 242/242/242 12/12/12 14/14/14 +f 241/241/241 7/7/7 12/12/12 +f 463/463/463 15/15/15 17/17/17 +f 261/261/261 18/18/18 20/20/20 +f 128/128/128 21/21/21 23/23/23 +f 35/35/35 24/24/24 25/25/25 +f 180/180/180 26/26/26 28/28/28 +f 118/118/118 29/29/29 31/31/31 +f 231/231/231 32/32/32 34/34/34 +f 170/170/170 35/35/35 36/36/36 +f 206/206/206 37/37/37 39/39/39 +f 36/36/36 25/25/25 41/41/41 +f 128/128/128 42/42/42 21/21/21 +f 159/159/159 44/44/44 46/46/46 +f 84/84/84 47/47/47 49/49/49 +f 74/74/74 50/50/50 52/52/52 +f 96/96/96 53/53/53 55/55/55 +f 230/230/230 56/56/56 58/58/58 +f 80/80/80 59/59/59 32/32/32 +f 192/192/192 60/60/60 61/61/61 +f 165/165/165 62/62/62 64/64/64 +f 100/100/100 65/65/65 67/67/67 +f 309/309/309 68/68/68 70/70/70 +f 188/188/188 71/71/71 73/73/73 +f 81/81/81 74/74/74 75/75/75 +f 169/169/169 76/76/76 77/77/77 +f 47/47/47 78/78/78 48/48/48 +f 82/82/82 75/75/75 80/80/80 +f 182/182/182 81/81/81 82/82/82 +f 322/322/322 83/83/83 49/49/49 +f 76/76/76 85/85/85 86/86/86 +f 173/173/173 20/20/20 87/87/87 +f 63/63/63 40/40/40 11/11/11 +f 216/216/216 88/88/88 90/90/90 +f 158/158/158 91/91/91 93/93/93 +f 55/55/55 94/94/94 96/96/96 +f 219/219/219 97/97/97 99/99/99 +f 463/463/463 100/100/100 15/15/15 +f 106/106/106 88/88/88 102/102/102 +f 144/144/144 103/103/103 105/105/105 +f 209/209/209 89/89/89 106/106/106 +f 167/167/167 64/64/64 108/108/108 +f 153/153/153 109/109/109 110/110/110 +f 196/196/196 111/111/111 113/113/113 +f 227/227/227 114/114/114 116/116/116 +f 225/225/225 117/117/117 31/31/31 +f 171/171/171 60/60/60 120/120/120 +f 242/242/242 14/14/14 121/121/121 +f 240/240/240 122/122/122 124/124/124 +f 214/214/214 69/69/69 125/125/125 +f 231/231/231 34/34/34 87/87/87 +f 204/204/204 17/17/17 28/28/28 +f 52/52/52 127/127/127 75/75/75 +f 8/8/8 42/42/42 9/9/9 +f 157/157/157 129/129/129 94/94/94 +f 174/174/174 131/131/131 123/123/123 +f 221/221/221 132/132/132 134/134/134 +f 243/243/243 135/135/135 137/137/137 +f 191/191/191 138/138/138 140/140/140 +f 136/136/136 135/135/135 131/131/131 +f 162/162/162 141/141/141 142/142/142 +f 162/162/162 143/143/143 144/144/144 +f 235/235/235 145/145/145 147/147/147 +f 98/98/98 97/97/97 68/68/68 +f 169/169/169 148/148/148 76/76/76 +f 116/116/116 115/115/115 150/150/150 +f 63/63/63 11/11/11 151/151/151 +f 199/199/199 79/79/79 152/152/152 +f 23/23/23 86/86/86 110/110/110 +f 127/127/127 154/154/154 44/44/44 +f 134/134/134 133/133/133 108/108/108 +f 56/56/56 93/93/93 57/57/57 +f 243/243/243 156/156/156 157/157/157 +f 54/54/54 53/53/53 158/158/158 +f 34/34/34 33/33/33 159/159/159 +f 243/243/243 157/157/157 135/135/135 +f 59/59/59 127/127/127 33/33/33 +f 140/140/140 139/139/139 74/74/74 +f 142/142/142 161/161/161 162/162/162 +f 24/24/24 163/163/163 10/10/10 +f 86/86/86 62/62/62 153/153/153 +f 205/205/205 166/166/166 167/167/167 +f 29/29/29 118/118/118 166/166/166 +f 38/38/38 163/163/163 35/35/35 +f 46/46/46 45/45/45 169/169/169 +f 39/39/39 38/38/38 170/170/170 +f 159/159/159 171/171/171 34/34/34 +f 87/87/87 126/126/126 173/173/173 +f 15/15/15 174/174/174 16/16/16 +f 88/88/88 176/176/176 101/101/101 +f 22/22/22 143/143/143 77/77/77 +f 181/181/181 140/140/140 81/81/81 +f 175/175/175 179/179/179 180/180/180 +f 190/190/190 181/181/181 182/182/182 +f 128/128/128 23/23/23 9/9/9 +f 67/67/67 131/131/131 15/15/15 +f 203/203/203 183/183/183 142/142/142 +f 322/322/322 184/184/184 83/83/83 +f 117/117/117 165/165/165 118/118/118 +f 184/184/184 186/186/186 185/185/185 +f 180/180/180 106/106/106 26/26/26 +f 9/9/9 110/110/110 13/13/13 +f 149/149/149 188/188/188 150/150/150 +f 232/232/232 189/189/189 190/190/190 +f 210/210/210 177/177/177 99/99/99 +f 181/181/181 189/189/189 140/140/140 +f 60/60/60 192/192/192 119/119/119 +f 192/192/192 194/194/194 193/193/193 +f 113/113/113 30/30/30 196/196/196 +f 163/163/163 38/38/38 197/197/197 +f 309/309/309 198/198/198 68/68/68 +f 154/154/154 127/127/127 51/51/51 +f 152/152/152 19/19/19 199/199/199 +f 163/163/163 197/197/197 164/164/164 +f 240/240/240 124/124/124 160/160/160 +f 72/72/72 71/71/71 202/202/202 +f 174/174/174 123/123/123 175/175/175 +f 21/21/21 43/43/43 103/103/103 +f 142/142/142 2/2/2 203/203/203 +f 175/175/175 180/180/180 16/16/16 +f 437/437/437 204/204/204 27/27/27 +f 196/196/196 29/29/29 205/205/205 +f 39/39/39 139/139/139 206/206/206 +f 153/153/153 165/165/165 109/109/109 +f 162/162/162 144/144/144 141/141/141 +f 21/21/21 103/103/103 22/22/22 +f 122/122/122 207/207/207 123/123/123 +f 238/238/238 147/147/147 208/208/208 +f 207/207/207 209/209/209 179/179/179 +f 99/99/99 98/98/98 210/210/210 +f 69/69/69 214/214/214 145/145/145 +f 137/137/137 136/136/136 3/3/3 +f 218/218/218 176/176/176 216/216/216 +f 3/3/3 66/66/66 217/217/217 +f 172/172/172 126/126/126 120/120/120 +f 176/176/176 218/218/218 99/99/99 +f 85/85/85 148/148/148 40/40/40 +f 222/222/222 220/220/220 151/151/151 +f 134/134/134 208/208/208 221/221/221 +f 5/5/5 222/222/222 6/6/6 +f 4/4/4 10/10/10 223/223/223 +f 223/223/223 164/164/164 224/224/224 +f 136/136/136 131/131/131 66/66/66 +f 105/105/105 129/129/129 144/144/144 +f 86/86/86 23/23/23 76/76/76 +f 62/62/62 85/85/85 63/63/63 +f 109/109/109 117/117/117 121/121/121 +f 64/64/64 63/63/63 107/107/107 +f 215/215/215 214/214/214 113/113/113 +f 215/215/215 229/229/229 221/221/221 +f 159/159/159 46/46/46 171/171/171 +f 87/87/87 19/19/19 231/231/231 +f 221/221/221 146/146/146 215/215/215 +f 190/190/190 185/185/185 232/232/232 +f 182/182/182 83/83/83 190/190/190 +f 82/82/82 84/84/84 182/182/182 +f 80/80/80 47/47/47 82/82/82 +f 32/32/32 78/78/78 80/80/80 +f 234/234/234 161/161/161 233/233/233 +f 170/170/170 50/50/50 39/39/39 +f 36/36/36 51/51/51 170/170/170 +f 41/41/41 154/154/154 36/36/36 +f 148/148/148 45/45/45 41/41/41 +f 61/61/61 46/46/46 77/77/77 +f 3/3/3 2/2/2 137/137/137 +f 113/113/113 112/112/112 215/215/215 +f 178/178/178 143/143/143 234/234/234 +f 69/69/69 145/145/145 70/70/70 +f 152/152/152 78/78/78 231/231/231 +f 64/64/64 166/166/166 165/165/165 +f 61/61/61 236/236/236 192/192/192 +f 205/205/205 237/237/237 196/196/196 +f 208/208/208 134/134/134 107/107/107 +f 107/107/107 220/220/220 208/208/208 +f 167/167/167 239/239/239 205/205/205 +f 43/43/43 72/72/72 104/104/104 +f 105/105/105 211/211/211 129/129/129 +f 42/42/42 73/73/73 43/43/43 +f 8/8/8 150/150/150 42/42/42 +f 7/7/7 116/116/116 8/8/8 +f 241/241/241 227/227/227 7/7/7 +f 90/90/90 89/89/89 228/228/228 +f 89/89/89 209/209/209 230/230/230 +f 207/207/207 93/93/93 209/209/209 +f 122/122/122 158/158/158 207/207/207 +f 240/240/240 54/54/54 122/122/122 +f 160/160/160 55/55/55 240/240/240 +f 157/157/157 94/94/94 160/160/160 +f 108/108/108 155/155/155 167/167/167 +f 236/236/236 178/178/178 194/194/194 +f 155/155/155 133/133/133 111/111/111 +f 61/61/61 77/77/77 236/236/236 +f 228/228/228 227/227/227 90/90/90 +f 90/90/90 241/241/241 216/216/216 +f 216/216/216 12/12/12 218/218/218 +f 218/218/218 242/242/242 219/219/219 +f 125/125/125 31/31/31 214/214/214 +f 219/219/219 121/121/121 97/97/97 +f 97/97/97 225/225/225 125/125/125 +f 194/194/194 234/234/234 195/195/195 +f 137/137/137 141/141/141 243/243/243 +f 211/211/211 202/202/202 212/212/212 +f 105/105/105 104/104/104 211/211/211 +f 436/436/436 244/244/244 246/246/246 +f 5/5/5 4/4/4 248/248/248 +f 369/369/369 249/249/249 251/251/251 +f 248/248/248 247/247/247 253/253/253 +f 250/250/250 254/254/254 256/256/256 +f 250/250/250 249/249/249 254/254/254 +f 411/411/411 258/258/258 260/260/260 +f 430/430/430 18/18/18 262/262/262 +f 413/413/413 263/263/263 265/265/265 +f 253/253/253 252/252/252 267/267/267 +f 27/27/27 26/26/26 269/269/269 +f 427/427/427 270/270/270 272/272/272 +f 402/402/402 273/273/273 275/275/275 +f 267/267/267 266/266/266 277/277/277 +f 408/408/408 278/278/278 280/280/280 +f 327/327/327 267/267/267 281/281/281 +f 435/435/435 282/282/282 263/263/263 +f 409/409/409 283/283/283 285/285/285 +f 48/48/48 286/286/286 49/49/49 +f 429/429/429 288/288/288 290/290/290 +f 401/401/401 291/291/291 293/293/293 +f 402/402/402 297/297/297 273/273/273 +f 285/285/285 299/299/299 301/301/301 +f 328/328/328 302/302/302 304/304/304 +f 444/444/444 305/305/305 307/307/307 +f 364/364/364 308/308/308 70/70/70 +f 433/433/433 310/310/310 312/312/312 +f 290/290/290 289/289/289 314/314/314 +f 413/413/413 315/315/315 317/317/317 +f 79/79/79 318/318/318 48/48/48 +f 297/297/297 314/314/314 298/298/298 +f 314/314/314 313/313/313 319/319/319 +f 287/287/287 321/321/321 49/49/49 +f 302/302/302 323/323/323 324/324/324 +f 430/430/430 262/262/262 326/326/326 +f 267/267/267 327/327/327 253/253/253 +f 343/343/343 329/329/329 331/331/331 +f 464/464/464 332/332/332 334/334/334 +f 391/391/391 336/336/336 338/338/338 +f 307/307/307 306/306/306 258/258/258 +f 101/101/101 329/329/329 102/102/102 +f 459/459/459 340/340/340 342/342/342 +f 329/329/329 343/343/343 339/339/339 +f 446/446/446 304/304/304 346/346/346 +f 256/256/256 347/347/347 349/349/349 +f 454/454/454 350/350/350 352/352/352 +f 393/393/393 353/353/353 355/355/355 +f 271/271/271 356/356/356 272/272/272 +f 424/424/424 299/299/299 359/359/359 +f 347/347/347 256/256/256 360/360/360 +f 375/375/375 361/361/361 363/363/363 +f 308/308/308 364/364/364 366/366/366 +f 410/410/410 275/275/275 326/326/326 +f 411/411/411 260/260/260 269/269/269 +f 297/297/297 368/368/368 314/314/314 +f 264/264/264 282/282/282 251/251/251 +f 442/442/442 370/370/370 372/372/372 +f 363/363/363 373/373/373 375/375/375 +f 398/398/398 376/376/376 378/378/378 +f 385/385/385 379/379/379 381/381/381 +f 403/403/403 382/382/382 384/384/384 +f 363/363/363 379/379/379 373/373/373 +f 436/436/436 386/386/386 388/388/388 +f 340/340/340 389/389/389 341/341/341 +f 451/451/451 390/390/390 147/147/147 +f 366/366/366 336/336/336 308/308/308 +f 323/323/323 392/392/392 315/315/315 +f 421/421/421 393/393/393 394/394/394 +f 248/248/248 253/253/253 395/395/395 +f 318/318/318 79/79/79 396/396/396 +f 348/348/348 324/324/324 349/349/349 +f 409/409/409 397/397/397 283/283/283 +f 460/460/460 398/398/398 346/346/346 +f 464/464/464 334/334/334 399/399/399 +f 370/370/370 400/400/400 371/371/371 +f 332/332/332 291/291/291 333/333/333 +f 283/283/283 402/402/402 284/284/284 +f 432/432/432 371/371/371 379/379/379 +f 283/283/283 368/368/368 402/402/402 +f 288/288/288 403/403/403 289/289/289 +f 389/389/389 404/404/404 387/387/387 +f 431/431/431 405/405/405 247/247/247 +f 303/303/303 302/302/302 348/348/348 +f 304/304/304 406/406/406 345/345/345 +f 465/465/465 271/271/271 406/406/406 +f 252/252/252 405/405/405 266/266/266 +f 392/392/392 409/409/409 316/316/316 +f 266/266/266 408/408/408 276/276/276 +f 410/410/410 358/358/358 275/275/275 +f 445/445/445 410/410/410 325/325/325 +f 416/416/416 374/374/374 411/411/411 +f 177/177/177 412/412/412 101/101/101 +f 455/455/455 389/389/389 317/317/317 +f 289/289/289 384/384/384 313/313/313 +f 339/339/339 415/415/415 268/268/268 +f 313/313/313 414/414/414 320/320/320 +f 349/349/349 265/265/265 251/251/251 +f 374/374/374 373/373/373 258/258/258 +f 404/404/404 418/418/418 388/388/388 +f 420/420/420 184/184/184 321/321/321 +f 465/465/465 303/303/303 271/271/271 +f 466/466/466 186/186/186 420/420/420 +f 102/102/102 339/339/339 26/26/26 +f 256/256/256 349/349/349 250/250/250 +f 312/312/312 311/311/311 394/394/394 +f 414/414/414 422/422/422 417/417/417 +f 412/412/412 177/177/177 338/338/338 +f 383/383/383 422/422/422 384/384/384 +f 426/426/426 300/300/300 424/424/424 +f 461/461/461 425/425/425 426/426/426 +f 270/270/270 427/427/427 351/351/351 +f 278/278/278 408/408/408 428/428/428 +f 391/391/391 198/198/198 308/308/308 +f 290/290/290 368/368/368 429/429/429 +f 18/18/18 430/430/430 199/199/199 +f 467/467/467 428/428/428 431/431/431 +f 379/379/379 363/363/363 432/432/432 +f 468/468/468 310/310/310 434/434/434 +f 415/415/415 375/375/375 416/416/416 +f 459/459/459 435/435/435 340/340/340 +f 244/244/244 436/436/436 419/419/419 +f 269/269/269 268/268/268 411/411/411 +f 269/269/269 367/367/367 27/27/27 +f 406/406/406 270/270/270 407/407/407 +f 382/382/382 403/403/403 279/279/279 +f 356/356/356 303/303/303 347/347/347 +f 400/400/400 341/341/341 386/386/386 +f 389/389/389 340/340/340 413/413/413 +f 415/415/415 438/438/438 375/375/375 +f 451/451/451 147/147/147 439/439/439 +f 339/339/339 344/344/344 415/415/415 +f 198/198/198 391/391/391 210/210/210 +f 447/447/447 365/365/365 390/390/390 +f 444/444/444 385/385/385 246/246/246 +f 329/329/329 412/412/412 330/330/330 +f 305/305/305 444/444/444 245/245/245 +f 358/358/358 410/410/410 359/359/359 +f 337/337/337 443/443/443 338/338/338 +f 281/281/281 392/392/392 327/327/327 +f 446/446/446 220/220/220 395/395/395 +f 451/451/451 439/439/439 377/377/377 +f 395/395/395 222/222/222 248/248/248 +f 431/431/431 247/247/247 223/223/223 +f 467/467/467 431/431/431 224/224/224 +f 307/307/307 373/373/373 444/444/444 +f 400/400/400 370/370/370 341/341/341 +f 413/413/413 265/265/265 315/315/315 +f 327/327/327 323/323/323 328/328/328 +f 357/357/357 356/356/356 360/360/360 +f 395/395/395 328/328/328 446/446/446 +f 427/427/427 365/365/365 352/352/352 +f 376/376/376 449/449/449 377/377/377 +f 299/299/299 285/285/285 358/358/358 +f 396/396/396 430/430/430 274/274/274 +f 390/390/390 451/451/451 447/447/447 +f 466/466/466 420/420/420 423/423/423 +f 420/420/420 321/321/321 417/417/417 +f 321/321/321 287/287/287 320/320/320 +f 287/287/287 286/286/286 319/319/319 +f 286/286/286 318/318/318 298/298/298 +f 418/418/418 404/404/404 453/453/453 +f 403/403/403 288/288/288 280/280/280 +f 288/288/288 429/429/429 276/276/276 +f 429/429/429 397/397/397 277/277/277 +f 397/397/397 409/409/409 281/281/281 +f 316/316/316 285/285/285 317/317/317 +f 386/386/386 436/436/436 381/381/381 +f 449/449/449 454/454/454 447/447/447 +f 404/404/404 389/389/389 452/452/452 +f 235/235/235 390/390/390 70/70/70 +f 273/273/273 318/318/318 274/274/274 +f 465/465/465 406/406/406 303/303/303 +f 425/425/425 456/456/456 300/300/300 +f 350/350/350 457/457/457 351/351/351 +f 346/346/346 378/378/378 446/446/446 +f 238/238/238 220/220/220 439/439/439 +f 457/457/457 458/458/458 407/407/407 +f 434/434/434 433/433/433 459/459/459 +f 442/442/442 441/441/441 370/370/370 +f 433/433/433 312/312/312 435/435/435 +f 312/312/312 394/394/394 282/282/282 +f 394/394/394 355/355/355 369/369/369 +f 355/355/355 354/354/354 249/249/249 +f 295/295/295 343/343/343 450/450/450 +f 294/294/294 344/344/344 295/295/295 +f 294/294/294 334/334/334 344/344/344 +f 334/334/334 333/333/333 438/438/438 +f 333/333/333 401/401/401 361/361/361 +f 401/401/401 293/293/293 362/362/362 +f 293/293/293 372/372/372 432/432/432 +f 454/454/454 449/449/449 398/398/398 +f 458/458/458 457/457/457 460/460/460 +f 458/458/458 460/460/460 345/345/345 +f 452/452/452 455/455/455 425/425/425 +f 454/454/454 398/398/398 350/350/350 +f 455/455/455 317/317/317 456/456/456 +f 257/257/257 354/354/354 331/331/331 +f 254/254/254 257/257/257 330/330/330 +f 255/255/255 254/254/254 443/443/443 +f 360/360/360 255/255/255 337/337/337 +f 427/427/427 272/272/272 365/365/365 +f 357/357/357 360/360/360 336/336/336 +f 272/272/272 357/357/357 366/366/366 +f 453/453/453 452/452/452 461/461/461 +f 400/400/400 386/386/386 380/380/380 +f 468/468/468 434/434/434 462/462/462 +f 434/434/434 459/459/459 441/441/441 +# 852 faces + diff --git a/python/server/effects/1.png b/python/server/effects/1.png new file mode 100644 index 0000000..1634b44 Binary files /dev/null and b/python/server/effects/1.png differ diff --git a/python/server/effects/11.png b/python/server/effects/11.png new file mode 100644 index 0000000..0515230 Binary files /dev/null and b/python/server/effects/11.png differ diff --git a/python/server/effects/12.png b/python/server/effects/12.png new file mode 100644 index 0000000..2e24e29 Binary files /dev/null and b/python/server/effects/12.png differ diff --git a/python/server/effects/13.png b/python/server/effects/13.png new file mode 100644 index 0000000..d301f3d Binary files /dev/null and b/python/server/effects/13.png differ diff --git a/python/server/effects/14.png b/python/server/effects/14.png new file mode 100644 index 0000000..cf0e9e9 Binary files /dev/null and b/python/server/effects/14.png differ diff --git a/python/server/effects/21.png b/python/server/effects/21.png new file mode 100644 index 0000000..24d1a00 Binary files /dev/null and b/python/server/effects/21.png differ diff --git a/python/server/effects/23.png b/python/server/effects/23.png new file mode 100644 index 0000000..6255086 Binary files /dev/null and b/python/server/effects/23.png differ diff --git a/python/server/effects/24.png b/python/server/effects/24.png new file mode 100644 index 0000000..8343f29 Binary files /dev/null and b/python/server/effects/24.png differ diff --git a/python/server/effects/26.png b/python/server/effects/26.png new file mode 100644 index 0000000..bac8aa6 Binary files /dev/null and b/python/server/effects/26.png differ diff --git a/python/server/effects/27.png b/python/server/effects/27.png new file mode 100644 index 0000000..2ba9650 Binary files /dev/null and b/python/server/effects/27.png differ diff --git a/python/server/effects/32.png b/python/server/effects/32.png new file mode 100644 index 0000000..1ad5dc8 Binary files /dev/null and b/python/server/effects/32.png differ diff --git a/python/server/effects/37.png b/python/server/effects/37.png new file mode 100644 index 0000000..d77ffbb Binary files /dev/null and b/python/server/effects/37.png differ diff --git a/python/server/effects/4.png b/python/server/effects/4.png new file mode 100644 index 0000000..0cb9a8a Binary files /dev/null and b/python/server/effects/4.png differ diff --git a/python/server/effects/40.png b/python/server/effects/40.png new file mode 100644 index 0000000..914ec08 Binary files /dev/null and b/python/server/effects/40.png differ diff --git a/python/server/effects/45.png b/python/server/effects/45.png new file mode 100644 index 0000000..701c227 Binary files /dev/null and b/python/server/effects/45.png differ diff --git a/python/server/effects/48.png b/python/server/effects/48.png new file mode 100644 index 0000000..1b7ee8b Binary files /dev/null and b/python/server/effects/48.png differ diff --git a/python/server/effects/49.png b/python/server/effects/49.png new file mode 100644 index 0000000..f56d4b5 Binary files /dev/null and b/python/server/effects/49.png differ diff --git a/python/server/effects/5.png b/python/server/effects/5.png new file mode 100644 index 0000000..7a6da02 Binary files /dev/null and b/python/server/effects/5.png differ diff --git a/python/server/effects/53.png b/python/server/effects/53.png new file mode 100644 index 0000000..29ead54 Binary files /dev/null and b/python/server/effects/53.png differ diff --git a/python/server/effects/56.png b/python/server/effects/56.png new file mode 100644 index 0000000..5c397a7 Binary files /dev/null and b/python/server/effects/56.png differ diff --git a/python/server/effects/59.png b/python/server/effects/59.png new file mode 100644 index 0000000..9747bb1 Binary files /dev/null and b/python/server/effects/59.png differ diff --git a/python/server/effects/6.png b/python/server/effects/6.png new file mode 100644 index 0000000..414cf0e Binary files /dev/null and b/python/server/effects/6.png differ diff --git a/python/server/effects/62.png b/python/server/effects/62.png new file mode 100644 index 0000000..15f858c Binary files /dev/null and b/python/server/effects/62.png differ diff --git a/python/server/effects/65.png b/python/server/effects/65.png new file mode 100644 index 0000000..a7c11c3 Binary files /dev/null and b/python/server/effects/65.png differ diff --git a/python/server/effects/68.png b/python/server/effects/68.png new file mode 100644 index 0000000..fe86f2f Binary files /dev/null and b/python/server/effects/68.png differ diff --git a/python/server/effects/7.png b/python/server/effects/7.png new file mode 100644 index 0000000..884f1e6 Binary files /dev/null and b/python/server/effects/7.png differ diff --git a/python/server/effects/71.png b/python/server/effects/71.png new file mode 100644 index 0000000..73feea9 Binary files /dev/null and b/python/server/effects/71.png differ diff --git a/python/server/effects/76.png b/python/server/effects/76.png new file mode 100644 index 0000000..2e0ed3c Binary files /dev/null and b/python/server/effects/76.png differ diff --git a/python/server/effects/77.png b/python/server/effects/77.png new file mode 100644 index 0000000..643281d Binary files /dev/null and b/python/server/effects/77.png differ diff --git a/python/server/effects/78.png b/python/server/effects/78.png new file mode 100644 index 0000000..ceb0313 Binary files /dev/null and b/python/server/effects/78.png differ diff --git a/python/server/effects/80.png b/python/server/effects/80.png new file mode 100644 index 0000000..e6a60da Binary files /dev/null and b/python/server/effects/80.png differ diff --git a/python/server/effects/81.png b/python/server/effects/81.png new file mode 100644 index 0000000..7895d2a Binary files /dev/null and b/python/server/effects/81.png differ diff --git a/python/server/effects/82.png b/python/server/effects/82.png new file mode 100644 index 0000000..2425e5c Binary files /dev/null and b/python/server/effects/82.png differ diff --git a/python/server/face_renderer.py b/python/server/face_renderer.py new file mode 100644 index 0000000..e033211 --- /dev/null +++ b/python/server/face_renderer.py @@ -0,0 +1,312 @@ +""" +人脸贴图渲染核心:接受一张图 + 一个效果 ID,输出 PNG 字节。 + +流程(与 Android 端 vulkan/FaceApp.cpp 一致,CPU 实现): + 1. MediaPipe FaceLandmarker → 478 normalized landmarks per face + 2. 取最大人脸(按 landmark bbox 面积) + 3. 把 obj 的 468 顶点位置改写为 landmarks[INDEX_MAP[i]],得到 dst 顶点 + 4. 对 mesh 的每个三角形:从 512×512 effect 贴图取 src 三角形,仿射 warp + 到 dst 三角形位置,按贴图 alpha 通道 alpha-blend 到原图副本上 + 5. 输出 PNG(保持原图尺寸) +""" + +from __future__ import annotations + +import io +import threading +from dataclasses import dataclass +from pathlib import Path + +import cv2 +import numpy as np +from PIL import Image, ImageOps + +from .index_map import INDEX_MAP +from .mesh import FaceMesh, load_face_mesh + + +class NoFaceError(Exception): + """图里检测不到人脸。""" + + +class EffectNotFoundError(Exception): + """指定 effect_id 没有对应贴图。""" + + +@dataclass +class RendererPaths: + obj_path: Path + effects_dir: Path + + +class FaceRenderer: + """ + 单例式渲染器:mesh / mediapipe 模型加载一次复用。 + + 线程安全:MediaPipe FaceLandmarker 的 detect() 不保证多线程并发, + 用 _lock 串行化。FastAPI 单进程同步部署下,请求本身就串行,开销可忽略。 + """ + + def __init__(self, paths: RendererPaths, max_image_bytes: int = 20 * 1024 * 1024): + self.paths = paths + self.max_image_bytes = max_image_bytes + self._mesh: FaceMesh = load_face_mesh(paths.obj_path) + if len(self._mesh.uvs) != len(INDEX_MAP): + raise RuntimeError( + f"mesh has {len(self._mesh.uvs)} vertices but INDEX_MAP has " + f"{len(INDEX_MAP)}; obj/index_map.py 不匹配" + ) + # 预转 numpy 加速 + self._index_map = np.asarray(INDEX_MAP, dtype=np.int32) + + self._effect_cache: dict[int, np.ndarray] = {} + self._cache_lock = threading.Lock() + + # MediaPipe 延迟加载(首次请求时加载,缩短启动时间,便于本地调试) + self._landmarker = None + self._landmarker_lock = threading.Lock() + + # ---------- public ---------- + + def list_effect_ids(self) -> list[int]: + """枚举 effects/.png 中的 n。""" + ids: list[int] = [] + if not self.paths.effects_dir.is_dir(): + return ids + for p in self.paths.effects_dir.iterdir(): + if p.suffix.lower() != ".png": + continue + try: + n = int(p.stem) + except ValueError: + continue + if 1 <= n <= 99: + ids.append(n) + return sorted(ids) + + def render(self, image_bytes: bytes, effect_id: int) -> bytes: + if len(image_bytes) > self.max_image_bytes: + raise ValueError("image too large") + + effect_rgba = self._load_effect(effect_id) # (H,W,4) uint8 + + # 1. 解码 + 处理 EXIF orientation → RGB ndarray + img_rgb = self._decode_input(image_bytes) + h, w = img_rgb.shape[:2] + + # 2. MediaPipe 检测,挑最大人脸 + landmarks_norm = self._detect_largest_face(img_rgb) # (N,2) ∈ [0,1]² (N>=468) + + # 3. obj 顶点 → 像素坐标 + dst_xy = self._compute_dst_vertices(landmarks_norm, w, h) + + # 4. warp + 混合 + out = img_rgb.copy() + self._composite(out, effect_rgba, dst_xy) + + # 5. 编码 PNG + return self._encode_png(out) + + # ---------- internals ---------- + + def _load_effect(self, effect_id: int) -> np.ndarray: + if not (1 <= effect_id <= 99): + raise EffectNotFoundError(f"effect_id out of range: {effect_id}") + with self._cache_lock: + cached = self._effect_cache.get(effect_id) + if cached is not None: + return cached + png_path = self.paths.effects_dir / f"{effect_id}.png" + if not png_path.is_file(): + raise EffectNotFoundError(f"effect {effect_id} not found") + # 用 PIL 解码以保证 RGBA 一致;OpenCV imread 对部分 PNG 会丢 alpha + img = Image.open(png_path).convert("RGBA") + arr = np.array(img, dtype=np.uint8) # (H,W,4) RGBA + with self._cache_lock: + self._effect_cache[effect_id] = arr + return arr + + def _decode_input(self, image_bytes: bytes) -> np.ndarray: + try: + pil = Image.open(io.BytesIO(image_bytes)) + pil = ImageOps.exif_transpose(pil) # 处理手机 EXIF 旋转 + pil = pil.convert("RGB") + except Exception as e: + raise ValueError(f"invalid image: {e}") from e + return np.array(pil, dtype=np.uint8) + + def _ensure_landmarker(self): + if self._landmarker is not None: + return + with self._landmarker_lock: + if self._landmarker is not None: + return + # 延迟 import,避免单元测试时强依赖 mediapipe + from mediapipe.tasks import python as mp_python + from mediapipe.tasks.python import vision as mp_vision + + model_path = self._find_model_file() + base_options = mp_python.BaseOptions(model_asset_path=str(model_path)) + options = mp_vision.FaceLandmarkerOptions( + base_options=base_options, + running_mode=mp_vision.RunningMode.IMAGE, + num_faces=5, # 检测最多 5 张,挑最大那张 + min_face_detection_confidence=0.5, + min_face_presence_confidence=0.5, + min_tracking_confidence=0.5, + output_face_blendshapes=False, + output_facial_transformation_matrixes=False, + ) + self._landmarker = mp_vision.FaceLandmarker.create_from_options(options) + + def _find_model_file(self) -> Path: + """优先用本服务 assets 下的,找不到再回退到仓库 app/src/main/assets。""" + local = self.paths.obj_path.parent / "face_landmarker.task" + if local.is_file(): + return local + # 回退到仓库 app/src/main/assets/face_landmarker.task(Android SDK 用同一份) + repo_root = self.paths.obj_path.resolve().parents[3] + fallback = repo_root / "app" / "src" / "main" / "assets" / "face_landmarker.task" + if fallback.is_file(): + return fallback + raise FileNotFoundError( + "face_landmarker.task not found; place it under " + f"{local} or {fallback}" + ) + + def _detect_largest_face(self, img_rgb: np.ndarray) -> np.ndarray: + self._ensure_landmarker() + import mediapipe as mp + + mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=img_rgb) + with self._landmarker_lock: + result = self._landmarker.detect(mp_image) + + faces = result.face_landmarks or [] + if not faces: + raise NoFaceError("no face detected") + + # 选 bbox 面积最大的那张 + def bbox_area(landmarks) -> float: + xs = [lm.x for lm in landmarks] + ys = [lm.y for lm in landmarks] + return (max(xs) - min(xs)) * (max(ys) - min(ys)) + + biggest = max(faces, key=bbox_area) + # 转 ndarray,只取 xy + n = len(biggest) + arr = np.empty((n, 2), dtype=np.float32) + for i, lm in enumerate(biggest): + arr[i, 0] = lm.x + arr[i, 1] = lm.y + return arr + + def _compute_dst_vertices( + self, landmarks_norm: np.ndarray, w: int, h: int + ) -> np.ndarray: + """ + landmarks_norm: (N, 2) ∈ [0,1]² + 返回 (468, 2) float32 像素坐标,对应 mesh 的 468 个顶点。 + """ + n_landmarks = landmarks_norm.shape[0] + if self._index_map.max() >= n_landmarks: + raise RuntimeError( + f"INDEX_MAP references landmark index {int(self._index_map.max())} " + f"but mediapipe returned only {n_landmarks} landmarks" + ) + picked = landmarks_norm[self._index_map] # (468, 2) + out = np.empty_like(picked) + out[:, 0] = picked[:, 0] * w + out[:, 1] = picked[:, 1] * h + return out.astype(np.float32) + + def _composite( + self, + canvas_rgb: np.ndarray, + effect_rgba: np.ndarray, + dst_xy: np.ndarray, + ) -> None: + """ + 在 canvas_rgb(uint8 H×W×3,原地修改)上对 mesh 每个三角形: + 从 effect_rgba 取对应 src 三角形 → warpAffine 到 dst → alpha 混合。 + """ + eh, ew = effect_rgba.shape[:2] + canvas_h, canvas_w = canvas_rgb.shape[:2] + uvs = self._mesh.uvs # (468, 2) + tris = self._mesh.triangles # (852, 3) + + # 把 UV 一次性转成 effect 像素坐标 + src_pts_all = np.empty_like(uvs) + src_pts_all[:, 0] = uvs[:, 0] * ew + src_pts_all[:, 1] = uvs[:, 1] * eh + + effect_rgb = effect_rgba[..., :3] + effect_a = effect_rgba[..., 3] + + for tri in tris: + i0, i1, i2 = int(tri[0]), int(tri[1]), int(tri[2]) + src_tri = np.float32([src_pts_all[i0], src_pts_all[i1], src_pts_all[i2]]) + dst_tri = np.float32([dst_xy[i0], dst_xy[i1], dst_xy[i2]]) + + # 用 dst bbox 限定计算区域,避免对全画布 warp + x_min = int(np.floor(dst_tri[:, 0].min())) + y_min = int(np.floor(dst_tri[:, 1].min())) + x_max = int(np.ceil(dst_tri[:, 0].max())) + y_max = int(np.ceil(dst_tri[:, 1].max())) + + # clip 到画布 + x_min_c = max(0, x_min) + y_min_c = max(0, y_min) + x_max_c = min(canvas_w, x_max) + y_max_c = min(canvas_h, y_max) + if x_max_c <= x_min_c or y_max_c <= y_min_c: + continue + + box_w = x_max_c - x_min_c + box_h = y_max_c - y_min_c + + # 构造从 src → 局部 bbox 坐标系(左上为原点)的仿射 + dst_tri_local = dst_tri - np.array([x_min_c, y_min_c], dtype=np.float32) + M = cv2.getAffineTransform(src_tri, dst_tri_local) + + # 给 RGB 和 alpha 分别 warp 到 bbox 大小 + warped_rgb = cv2.warpAffine( + effect_rgb, + M, + (box_w, box_h), + flags=cv2.INTER_LINEAR, + borderMode=cv2.BORDER_REPLICATE, + ) + warped_a = cv2.warpAffine( + effect_a, + M, + (box_w, box_h), + flags=cv2.INTER_LINEAR, + borderMode=cv2.BORDER_CONSTANT, + borderValue=0, + ) + + # 限制只在三角形内部混合(防止 bbox 多余像素污染) + tri_mask = np.zeros((box_h, box_w), dtype=np.uint8) + cv2.fillConvexPoly( + tri_mask, + dst_tri_local.astype(np.int32), + 255, + lineType=cv2.LINE_AA, + ) + alpha = ( + warped_a.astype(np.float32) * (tri_mask.astype(np.float32) / 255.0) + ) / 255.0 + alpha = alpha[..., None] # (h,w,1) + + roi = canvas_rgb[y_min_c:y_max_c, x_min_c:x_max_c].astype(np.float32) + blended = roi * (1.0 - alpha) + warped_rgb.astype(np.float32) * alpha + canvas_rgb[y_min_c:y_max_c, x_min_c:x_max_c] = np.clip( + blended, 0, 255 + ).astype(np.uint8) + + def _encode_png(self, img_rgb: np.ndarray) -> bytes: + pil = Image.fromarray(img_rgb) + buf = io.BytesIO() + pil.save(buf, format="PNG") + return buf.getvalue() diff --git a/python/server/index_map.py b/python/server/index_map.py new file mode 100644 index 0000000..bcf7ae4 --- /dev/null +++ b/python/server/index_map.py @@ -0,0 +1,61 @@ +""" +OBJ 顶点索引 → MediaPipe FaceLandmarker landmark 索引的映射表。 + +直接从 vulkan/hardcode_data.h::indexMap[468] 同步而来。意义: + obj 顶点 i 在画面中的位置 = mediapipe_landmarks[INDEX_MAP[i]] + +注意:face_picture_3dmax.obj 的顶点数量必须正好 468,与本表长度一致。 +若以后换 obj,需要重新生成本表。 +""" + +INDEX_MAP = [ + 127, 34, 139, 11, 0, 37, 232, 231, 120, 72, + 39, 128, 121, 47, 104, 69, 67, 175, 171, 148, + 118, 50, 101, 73, 40, 9, 151, 108, 48, 115, + 131, 194, 204, 211, 74, 185, 80, 42, 183, 92, + 186, 230, 229, 202, 212, 214, 83, 18, 17, 76, + 61, 146, 160, 29, 30, 56, 157, 173, 106, 135, + 192, 203, 165, 98, 21, 71, 68, 51, 45, 4, + 144, 24, 23, 77, 91, 205, 187, 201, 200, 182, + 90, 181, 85, 84, 206, 36, 140, 193, 189, 244, + 159, 158, 28, 247, 246, 161, 236, 3, 196, 54, + 168, 8, 117, 228, 31, 55, 97, 99, 126, 100, + 166, 79, 218, 155, 154, 26, 209, 49, 136, 150, + 217, 223, 52, 53, 134, 170, 43, 119, 226, 130, + 63, 238, 20, 242, 46, 70, 156, 78, 62, 96, + 143, 227, 123, 111, 44, 125, 19, 216, 153, 22, + 167, 208, 142, 57, 60, 35, 113, 27, 210, 225, + 137, 116, 41, 38, 129, 64, 240, 102, 207, 184, + 169, 149, 176, 105, 66, 122, 6, 147, 65, 107, + 89, 180, 93, 15, 86, 14, 87, 145, 88, 179, + 95, 138, 172, 215, 58, 219, 81, 195, 199, 82, + 163, 110, 234, 109, 235, 191, 222, 141, 221, 197, + 25, 7, 33, 220, 237, 245, 162, 188, 174, 2, + 241, 164, 12, 13, 198, 133, 112, 243, 239, 190, + 32, 178, 132, 177, 1, 213, 59, 94, 75, 224, + 233, 114, 124, 356, 389, 368, 302, 267, 452, 350, + 349, 303, 269, 357, 343, 277, 453, 333, 332, 297, + 152, 377, 347, 348, 330, 304, 270, 336, 337, 278, + 279, 360, 418, 262, 431, 408, 409, 310, 415, 407, + 410, 450, 422, 430, 434, 313, 314, 306, 307, 375, + 387, 388, 260, 286, 414, 398, 335, 406, 364, 367, + 416, 423, 358, 327, 251, 284, 298, 281, 5, 373, + 374, 253, 320, 321, 425, 427, 411, 421, 405, 404, + 315, 16, 426, 266, 400, 369, 322, 391, 417, 465, + 464, 386, 257, 258, 466, 456, 399, 419, 285, 346, + 340, 261, 413, 441, 460, 328, 355, 371, 329, 392, + 439, 438, 382, 341, 256, 429, 420, 394, 379, 437, + 443, 444, 283, 275, 440, 363, 338, 273, 451, 446, + 342, 467, 293, 334, 282, 458, 461, 462, 276, 353, + 383, 308, 324, 325, 300, 372, 345, 447, 352, 274, + 248, 436, 381, 252, 393, 428, 287, 250, 384, 265, + 259, 424, 292, 366, 271, 294, 455, 272, 432, 395, + 299, 351, 280, 319, 295, 296, 403, 323, 454, 316, + 380, 318, 402, 365, 435, 397, 344, 311, 291, 396, + 268, 445, 254, 339, 449, 264, 10, 442, 370, 263, + 255, 359, 412, 301, 378, 326, 457, 362, 459, 463, + 354, 401, 361, 309, 376, 433, 289, 305, 448, 290, + 288, 249, 103, 385, 331, 317, 312, 390, +] + +assert len(INDEX_MAP) == 468, f"INDEX_MAP must have 468 entries, got {len(INDEX_MAP)}" diff --git a/python/server/main.py b/python/server/main.py new file mode 100644 index 0000000..8b3ee79 --- /dev/null +++ b/python/server/main.py @@ -0,0 +1,62 @@ +""" +FastAPI 入口。启动: + + python -m uvicorn server.main:app --host 0.0.0.0 --port 8000 + +或在 python/ 目录下: + + uvicorn server.main:app --host 0.0.0.0 --port 8000 +""" + +from __future__ import annotations + +from pathlib import Path + +from fastapi import FastAPI, File, Form, HTTPException, UploadFile +from fastapi.responses import JSONResponse, Response + +from .face_renderer import ( + EffectNotFoundError, + FaceRenderer, + NoFaceError, + RendererPaths, +) + +# 路径相对本文件,避免 cwd 不同时找不到资源 +_SERVER_DIR = Path(__file__).resolve().parent +_PATHS = RendererPaths( + obj_path=_SERVER_DIR / "assets" / "face_picture_3dmax.obj", + effects_dir=_SERVER_DIR / "effects", +) + +app = FastAPI(title="Face SDK Web", version="0.1.0") +renderer = FaceRenderer(_PATHS) + + +@app.get("/health") +def health() -> dict: + return {"ok": True} + + +@app.get("/effects") +def list_effects() -> dict: + return {"effects": renderer.list_effect_ids()} + + +@app.post("/render") +async def render( + image: UploadFile = File(...), + effect_id: int = Form(...), +) -> Response: + image_bytes = await image.read() + if not image_bytes: + raise HTTPException(status_code=400, detail="empty image") + try: + png_bytes = renderer.render(image_bytes, effect_id) + except NoFaceError: + return JSONResponse(status_code=400, content={"error": "no_face"}) + except EffectNotFoundError as e: + raise HTTPException(status_code=404, detail=str(e)) + except ValueError as e: + raise HTTPException(status_code=400, detail=str(e)) + return Response(content=png_bytes, media_type="image/png") diff --git a/python/server/mesh.py b/python/server/mesh.py new file mode 100644 index 0000000..5452b58 --- /dev/null +++ b/python/server/mesh.py @@ -0,0 +1,75 @@ +""" +解析 face_picture_3dmax.obj,得到顶点 UV 和三角形索引。 + +OBJ 约定:v 顶点 / vt UV / vn 法线,f 三元组 v/vt/vn 索引(1-based)。 +本服务只需要每个顶点的 UV 和三角形顶点索引——3D 顶点位置在 SDK 里也只是 +占位(运行时被 MediaPipe landmark 覆盖),这里同样无需读 v。 + +★ 与 vulkan/FaceApp.cpp::LoadOBJ 一致,UV 的 V 分量取 (1 - v),把 OBJ 的 + bottom-up 约定翻成 top-down,与图像(OpenCV/Pillow)一致。 +""" + +from dataclasses import dataclass +from pathlib import Path + +import numpy as np + + +@dataclass +class FaceMesh: + # (468, 2) float32, 每个顶点的 UV,V 已翻转,∈ [0,1]² + uvs: np.ndarray + # (852, 3) int32, 每个三角形的 3 个顶点索引(0-based,指向 uvs 第一维) + triangles: np.ndarray + + +def load_face_mesh(obj_path: str | Path) -> FaceMesh: + obj_path = Path(obj_path) + text = obj_path.read_text(encoding="utf-8", errors="ignore") + + pos_count = 0 + uv_list: list[tuple[float, float]] = [] + # OBJ 的 face 用 v/vt/vn,三个索引可能不同;但本工程的 obj 三者一一对齐 + # (pos_index == uv_index == normal_index),所以我们只看 v 索引来索引 UV + # 列表也成立。这里仍然显式校验以防换 obj 时出错。 + triangles: list[tuple[int, int, int]] = [] + + for raw in text.splitlines(): + line = raw.strip() + if not line or line.startswith("#"): + continue + parts = line.split() + tag = parts[0] + + if tag == "v": + pos_count += 1 + elif tag == "vt": + u = float(parts[1]) + v = float(parts[2]) + uv_list.append((u, 1.0 - v)) # V 翻转 + elif tag == "f": + if len(parts) != 4: + raise ValueError(f"only triangle faces supported, got: {line}") + tri: list[int] = [] + for token in parts[1:]: + # 形如 "v/vt/vn" 或 "v//vn" 或 "v" + seg = token.split("/") + v_idx = int(seg[0]) - 1 # OBJ 1-based → 0-based + vt_idx = int(seg[1]) - 1 if len(seg) > 1 and seg[1] else v_idx + if v_idx != vt_idx: + raise ValueError( + f"this loader assumes pos_idx == uv_idx, " + f"got v={v_idx + 1} vt={vt_idx + 1} in line: {line}" + ) + tri.append(v_idx) + triangles.append((tri[0], tri[1], tri[2])) + + if pos_count != len(uv_list): + raise ValueError( + f"vertex count {pos_count} != uv count {len(uv_list)}; " + "obj loader assumes 1:1 correspondence" + ) + + uvs = np.asarray(uv_list, dtype=np.float32) + tris = np.asarray(triangles, dtype=np.int32) + return FaceMesh(uvs=uvs, triangles=tris)