Fix V-face deformation with lower-jaw landmark pins; pass regression

这个提交包含在:
dayu 于 2026-10-22 16:26:42 +08:00 提交
1 父节点 58f09e5756
当前提交 7fa3298e02
19 个文件已更改
+566 -36

没有与搜索条件相匹配的文件

+42
查看文件
@@ -0,0 +1,42 @@
# V 脸下颌区域修复
2026-10-22,针对用户报告「V 脸作用到眼睛,应作用于下颌」。目标为本机 MSE18V2 2.4.0(20260724150000),产品修复版本为 1.3.1(16)。
## 原因与修改
1.3.0 仍使用脸框上的宽范围高斯带及纵向位移近似 V 脸。它不依赖真实下颌轮廓,在真实人像上能测到眼区变化。不是面板标签或参数 ID 接错;本次只替换 V 脸几何场。
新版目标的 AIR 按 `69→39、65→35、70→26、64→34` 顺序执行四组局部逆向采样。起点都是下颌轮廓,锚点都是外唇。每步使用前一步更新后的 q:
```text
r = length(anchor − origin)
if r > 0.0001:
weight = clamp(1 − length(q − origin) / r, 0, 1)
q = clamp(q − (anchor − origin) × ratio × weight, 0, 1)
```
CPU 函数 `0x10002fb74` 从参数 `+0x90` 读取 V 值,乘位于 `0x100085ea0` 的 double `0.065` 和公共强度,再转 float 写入 shape 结构的 `+8`。新版三个 shader helper 都没有旧版的 `280/尺寸` 增益;本项目 V 使用 `clamp(faceV,0,1)×0.065`,整体混合沿用现有产品链。公共强度各调用方的完整来源尚未追踪,不将整体混合宣称为原版该参数的等价重建。
生产实现复用局部 pin 核心,四步严格顺序更新,与图像/四张支持蒙版共享同一坐标场;完整 76 点缺失或不合法时安全直通。Core Image 坐标和关键点一起转换到 Y 向下的全图 UV,结束后一起转回,支持非零图像原点、横竖画幅和歪头。
## 静态证据与复现
原始 APP、metallib、完整 AIR 与用户帧仅留本机 build,不是构建依赖。源码没有嵌入目标二进制、私有模型或授权逻辑。
- 原 APP 嵌套 Mach-O(fat)SHA-256:`577303e0de72e07feb576c882e82382b3f056b023a7e987d990ffb37f6b16109`。
- arm64 切片 SHA-256:`afc71d0d21fd3c1ca95ca745ddafcd729e36ad95f17d8638009f2e45d9b7e8df`。
- metallib SHA-256:`856849c45cea2c8f083eeba06a9e318c450f4a56694b438d1a5ba8ef752a0ee0`。
- `xcrun metal-objdump --metallib --disassemble` 输出 SHA-256:`1d5bd8d5a3917afbb3b4fe1c40b44480760614102685ac826e84ad2e30a450f9`;V 分支 3364–3431 行,四组点索引在 3374、3376、3378、3380 行。
- 精简 AIR 摘录:[vface-air.txt](vface-air.txt);CPU 字段/系数与分析条件:[vface-findings.json](vface-findings.json);REA CPU 汇编和常量证据:[rea-vface-evidence.json](rea-vface-evidence.json)。REA 操作为只读,未运行原 APP 或原 shader。
## 验证
修改前隔离 V 测试复现:NASA 人像瞳孔 6 的位移约 0.031493 像素;宿主物理行序测试四种原点组合的 V 输出与独立 upright 参考均不符。原宿主输出两眼区像素变化量分别为 12824、19304,下颌为 195206。
修改后瞳孔检查通过;宿主四种原点组合的 V 眼区像素变化量均为 0,下颌为 39246,独立 upright 对照最大差 1/255、均差 0.000124/255。数值场覆盖 4 种画幅、正侧脸和歪头、半强度、小脸不带旧增益、顺序组合、缺点/坏点以及四张蒙版同步。独立的真实解剖位置检查要求下颌有位移且两瞳孔位移小于 0.002 像素,避免只用复制实现的数值公式验收。
完整自动回归:1901 项通过(57 Beauty、116 Face、1033 几何、370 Host ASan、98 OSC ASan、227 Inspector ASan)。真实用户帧专项另记交付验证;与基础用例重叠,不相加。正式安装和原生宿主 V 脸视觉验收状态见 [验证记录](../验证记录.md)。
## 范围
V 脸现在加入已恢复的五项局部控制。瘦脸、下巴、短脸、下颌骨沿用此前版本的尺寸增益;未将新版目标的其他差异混入本次修复。大眼、窄脸、颧骨和小头仍为近似,整条混合控制链的数学、顺序和最终像素尚未全部对齐。静态重建、离屏/接口检查不等于原版 shader 的运行时逐像素比较,也不等于 Motion/FCP 原生视觉验收。
+1
查看文件
@@ -0,0 +1 @@
{"artifacts":[{"architecture":"arm64","digest":{"sha256":"afc71d0d21fd3c1ca95ca745ddafcd729e36ad95f17d8638009f2e45d9b7e8df"},"format":"mach-o"}],"captures":[],"environments":[],"providers":[{"id":"ghidra","name":"Ghidra","version":"12.1.4"}],"records":[{"analysis_profile":{"digest":"20565088524a2d0359b9b96f46ac48e679d774c7b0092c56abc06de8fdbec11c","parameters":{"analyzer_preset":"ghidra-default","annotation_policy":"atomic-function-entry-metadata-v1","architecture":"arm64","available_architectures":["arm64"],"compiler_spec_id":"auto-default","decompiler_jump_loads":true,"function_body_evidence":"complete-inclusive-ranges-v1","function_boundary_observations":"ghidra-terminal-call-limitations-v1","function_references":"complete-body-and-entry-reference-manager-v2","import_mode":"ephemeral-source-immutable","instruction_flow_evidence":"decoded-return-pcode-v1","jump_table_evidence":"typed-case-default-blocks-v1","language_id":"auto-from-header","load_image_observations":"source-mappings-entry-context-v2","loader":"auto-from-header","location_resolution":"explicit-address-exact-entry-symbol-first-v3","no_return_repair":"returning-imports-decoded-return-v2","process_launch":"inspected-jvm-launch-support-v1","string_inventory_evidence":"defined-data-coverage-v1","target_format":"mach-o","target_kind":"executable"},"provider":{"id":"ghidra","name":"Ghidra","version":"12.1.4"}},"authority":"shipped-artifact","confidence":"observed","environment":null,"evidence_id":"ev_32b6ee46d4fb5eab563883ba73e35a458d5da21229b8977fddcb4df656517152","evidence_links":[],"limitations":["The session serves operations only after Ghidra reports default auto-analysis complete; incomplete analysis does not expose partial results.","The imported Program and temporary project are ephemeral and deleted on close. Annotation operations edit session database metadata; original executable bytes are never written.","Cancelling an active Ghidra request terminates its ephemeral database and discards session annotations. The selected target remains open; the next provider query imports the original artifact again.","Default-space addresses use lowercase 0x-prefixed hexadecimal; other address spaces use <percent-encoded-space>:0x<hex>.","Bytes reflect Ghidra's initialized memory, including loader fixups. Reads stop at an unmapped or uninitialized byte and report completeness explicitly.","macOS sessions require a matching executable Ghidra native decompiler; REA checks for it but does not build native components or change Gatekeeper quarantine state."],"locations":[],"normalized_result":{"address":"0x100085ea0","bytes_hex":"a4703d0ad7a3b03f9a9999999999a93f","complete":true,"requested_bytes":16,"returned_bytes":16},"operation":"read_bytes","parameters":{"address":"0x100085ea0","length":16},"predicate_type":"rea.analysis","provider":{"id":"ghidra","name":"Ghidra","version":"12.1.4"},"raw_result":{"address":"0x100085ea0","bytes_hex":"a4703d0ad7a3b03f9a9999999999a93f","complete":true,"requested_bytes":16,"returned_bytes":16},"subject":{"architecture":"arm64","digest":{"sha256":"afc71d0d21fd3c1ca95ca745ddafcd729e36ad95f17d8638009f2e45d9b7e8df"},"format":"mach-o","local_path":"/Users/dayu/Documents/PaintFCP/build/body-analysis/MSE18V2-arm64","name":"MSE18V2-arm64"}},{"analysis_profile":{"digest":"20565088524a2d0359b9b96f46ac48e679d774c7b0092c56abc06de8fdbec11c","parameters":{"analyzer_preset":"ghidra-default","annotation_policy":"atomic-function-entry-metadata-v1","architecture":"arm64","available_architectures":["arm64"],"compiler_spec_id":"auto-default","decompiler_jump_loads":true,"function_body_evidence":"complete-inclusive-ranges-v1","function_boundary_observations":"ghidra-terminal-call-limitations-v1","function_references":"complete-body-and-entry-reference-manager-v2","import_mode":"ephemeral-source-immutable","instruction_flow_evidence":"decoded-return-pcode-v1","jump_table_evidence":"typed-case-default-blocks-v1","language_id":"auto-from-header","load_image_observations":"source-mappings-entry-context-v2","loader":"auto-from-header","location_resolution":"explicit-address-exact-entry-symbol-first-v3","no_return_repair":"returning-imports-decoded-return-v2","process_launch":"inspected-jvm-launch-support-v1","string_inventory_evidence":"defined-data-coverage-v1","target_format":"mach-o","target_kind":"executable"},"provider":{"id":"ghidra","name":"Ghidra","version":"12.1.4"}},"authority":"shipped-artifact","confidence":"observed","environment":null,"evidence_id":"ev_6a88310573f4dfd2f23feef7d12c3f58eba366db1717861770656d55375e07a1","evidence_links":[],"limitations":["The session serves operations only after Ghidra reports default auto-analysis complete; incomplete analysis does not expose partial results.","The imported Program and temporary project are ephemeral and deleted on close. Annotation operations edit session database metadata; original executable bytes are never written.","Cancelling an active Ghidra request terminates its ephemeral dataLine truncated
+71
查看文件
@@ -0,0 +1,71 @@
MSE18V2 2.4.0 AIR excerpt; original complete-text line numbers.
SHA256: 1d5bd8d5a3917afbb3b4fe1c40b44480760614102685ac826e84ad2e30a450f9
3364: 158: ; preds = %109, %85
3365: %159 = phi <2 x float> [ %155, %109 ], [ %86, %85 ]
3366: %160 = tail call fast float @air.fast_fabs.f32(float %5) #2
3367: %161 = fcmp fast ogt float %160, 0x3EB0C6F7A0000000
3368: br i1 %161, label %162, label %209
3369:
3370: 162: ; preds = %158
3371: %163 = bitcast [4 x <2 x i32>]* %17 to i8*
3372: call void @llvm.lifetime.start.p0i8(i64 32, i8* nonnull %163) #10
3373: %164 = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* %17, i64 0, i64 0
3374: store <2 x i32> <i32 69, i32 39>, <2 x i32>* %164, align 8
3375: %165 = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* %17, i64 0, i64 1
3376: store <2 x i32> <i32 65, i32 35>, <2 x i32>* %165, align 8
3377: %166 = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* %17, i64 0, i64 2
3378: store <2 x i32> <i32 70, i32 26>, <2 x i32>* %166, align 8
3379: %167 = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* %17, i64 0, i64 3
3380: store <2 x i32> <i32 64, i32 34>, <2 x i32>* %167, align 8
3381: %168 = insertelement <2 x float> undef, float %5, i64 0
3382: %169 = shufflevector <2 x float> %168, <2 x float> undef, <2 x i32> zeroinitializer
3383: br label %171
3384:
3385: 170: ; preds = %205
3386: call void @llvm.lifetime.end.p0i8(i64 32, i8* nonnull %163) #10
3387: br label %209
3388:
3389: 171: ; preds = %205, %162
3390: %172 = phi <2 x float> [ %159, %162 ], [ %206, %205 ]
3391: %173 = phi i32 [ 0, %162 ], [ %207, %205 ]
3392: %174 = zext i32 %173 to i64
3393: %175 = getelementptr inbounds [4 x <2 x i32>], [4 x <2 x i32>]* %17, i64 0, i64 %174
3394: %176 = load <2 x i32>, <2 x i32>* %175, align 8
3395: %177 = extractelement <2 x i32> %176, i64 0
3396: %178 = add nsw i32 %177, %2
3397: %179 = sext i32 %178 to i64
3398: %180 = getelementptr inbounds %struct.MSSFaceThinPoint, %struct.MSSFaceThinPoint addrspace(2)* %1, i64 %179, i32 0
3399: %181 = load <2 x float>, <2 x float> addrspace(2)* %180, align 8, !tbaa !74
3400: %182 = extractelement <2 x i32> %176, i64 1
3401: %183 = add nsw i32 %182, %2
3402: %184 = sext i32 %183 to i64
3403: %185 = getelementptr inbounds %struct.MSSFaceThinPoint, %struct.MSSFaceThinPoint addrspace(2)* %1, i64 %184, i32 0
3404: %186 = load <2 x float>, <2 x float> addrspace(2)* %185, align 8, !tbaa !74
3405: %187 = fsub fast <2 x float> %181, %186
3406: %188 = tail call fast float @air.dot.v2f32(<2 x float> %187, <2 x float> %187) #2
3407: %189 = tail call fast float @air.fast_sqrt.f32(float %188) #2
3408: %190 = fcmp fast ugt float %189, 0x3F1A36E2E0000000
3409: br i1 %190, label %191, label %205
3410:
3411: 191: ; preds = %171
3412: %192 = fsub fast <2 x float> %186, %181
3413: %193 = fsub fast <2 x float> %172, %181
3414: %194 = tail call fast float @air.dot.v2f32(<2 x float> %193, <2 x float> %193) #2
3415: %195 = tail call fast float @air.fast_sqrt.f32(float %194) #2
3416: %196 = fdiv fast float %195, %189
3417: %197 = fsub fast float 1.000000e+00, %196
3418: %198 = tail call fast float @air.fast_clamp.f32(float %197, float 0.000000e+00, float 1.000000e+00) #2
3419: %199 = insertelement <2 x float> undef, float %198, i64 0
3420: %200 = shufflevector <2 x float> %199, <2 x float> undef, <2 x i32> zeroinitializer
3421: %201 = fmul fast <2 x float> %192, %169
3422: %202 = fmul fast <2 x float> %201, %200
3423: %203 = fsub fast <2 x float> %172, %202
3424: %204 = tail call fast <2 x float> @air.fast_clamp.v2f32(<2 x float> %203, <2 x float> zeroinitializer, <2 x float> <float 1.000000e+00, float 1.000000e+00>) #2
3425: br label %205
3426:
3427: 205: ; preds = %191, %171
3428: %206 = phi <2 x float> [ %204, %191 ], [ %172, %171 ]
3429: %207 = add nuw nsw i32 %173, 1
3430: %208 = icmp eq i32 %207, 4
3431: br i1 %208, label %170, label %171, !llvm.loop !89
+258
查看文件
@@ -0,0 +1,258 @@
{
"authority": "Static shipped Apple AIR and Mach-O byte/assembly inspection; target app and shaders not executed",
"sources": {
"metallib": "/Users/dayu/Downloads/MSE18V2.app/Contents/PlugIns/MSE18V2.pluginkit/Contents/Resources/default.metallib",
"metallib_sha256": "856849c45cea2c8f083eeba06a9e318c450f4a56694b438d1a5ba8ef752a0ee0",
"command": [
"xcrun",
"metal-objdump",
"--metallib",
"--disassemble",
"/Users/dayu/Downloads/MSE18V2.app/Contents/PlugIns/MSE18V2.pluginkit/Contents/Resources/default.metallib"
],
"air_sha256": "1d5bd8d5a3917afbb3b4fe1c40b44480760614102685ac826e84ad2e30a450f9",
"binary": "/Users/dayu/Downloads/MSE18V2.app/Contents/PlugIns/MSE18V2.pluginkit/Contents/MacOS/MSE18V2",
"binary_arm64_sha256": "afc71d0d21fd3c1ca95ca745ddafcd729e36ad95f17d8638009f2e45d9b7e8df",
"double065_file_offsets_in_arm64_slice": [
548512
]
},
"new_version_vface": {
"struct_field": "MSSFaceShapeParams.vlian offset8; helper parameter5",
"render_params_field": "faceV double offset0x90",
"cpu_function": "0x10002fb74",
"cpu_coefficient_address": "0x100085ea0",
"cpu_coefficient": 0.065,
"cpu_ratio": "float(clamp(faceV,0,1)*0.065*double(float(clamp(commonStrength,0,1))))",
"pin_order": [
[
69,
39
],
[
65,
35
],
[
70,
26
],
[
64,
34
]
],
"pin_fields": [
"origin",
"direction/radius anchor"
],
"coordinate_system": "full-image normalized UV; q and points must share the same vertical axis",
"radius": "length(Panchor-Porigin), unscaled UV metric; skip radius<=0.0001",
"weight": "clamp(1-length(q-Porigin)/radius,0,1)",
"step": "q=clamp(q-(Panchor-Porigin)*ratio*weight,0,1)",
"sequential": true,
"ratio_threshold": 1e-06,
"shader_lines": {
"helper": 3159,
"vface_gate": 3364,
"pins": [
3374,
3376,
3378,
3380
],
"loop": 3389,
"radius": 3405,
"offset": 3412,
"clamp": 3424,
"count": 3430,
"metadata": 4132
},
"order": "thin17 -> narrow16 -> V4 -> jaw6 -> cheek6 -> chin3 -> short -> smallHead -> bigEye",
"helper_copies": [
{
"start_line": 3159,
"v_pins": [
[
69,
39
],
[
65,
35
],
[
70,
26
],
[
64,
34
]
],
"has_old_pixel_gain_constant": false
},
{
"start_line": 6840,
"v_pins": [
[
69,
39
],
[
65,
35
],
[
70,
26
],
[
64,
34
]
],
"has_old_pixel_gain_constant": false
},
{
"start_line": 8682,
"v_pins": [
[
69,
39
],
[
65,
35
],
[
70,
26
],
[
64,
34
]
],
"has_old_pixel_gain_constant": false
}
]
},
"version_difference": {
"old_air": "build/pose-analysis/face-thin.air.txt",
"old_gain_lines": [
592,
633
],
"old_vface_lines": [
830,
897
],
"old_cpu_coefficient_address": "0x10005f9a0",
"coefficient_unchanged": true,
"old_extra_gain": "clamp(280/max(length((P75-P59)*pixelSize),2*length((P67-(P74+P60)/2)*pixelSize),1),1,2.25)",
"new_extra_gain": "Absent from all3 new shader helper copies and the complete new AIR text; CPU helper is plain clamped-control*.065*commonStrength",
"anatomy": "Origin indices64,65,69,70 are lower contour; anchor indices26,34,35,39 are outer lips; eyes0..13 are not controls."
},
"eye_support_probe": {
"authority": "Derived from existing local public-API Vision probe; no new image coordinates or original plug-in execution",
"settings": {
"vface": 1,
"common_strength": 1,
"coefficient": 0.065,
"pins": [
[
69,
39
],
[
65,
35
],
[
70,
26
],
[
64,
34
]
]
},
"samples": [
{
"seconds": 0,
"minimum_eye_distance_over_pin_radius": 2.86112178668839,
"max_eye_weight": 0,
"max_sequential_eye_displacement_pixels": 0
},
{
"seconds": 2,
"minimum_eye_distance_over_pin_radius": 2.7386373955689196,
"max_eye_weight": 0,
"max_sequential_eye_displacement_pixels": 0
},
{
"seconds": 4,
"minimum_eye_distance_over_pin_radius": 2.0723834235969316,
"max_eye_weight": 0,
"max_sequential_eye_displacement_pixels": 0
},
{
"seconds": 6,
"minimum_eye_distance_over_pin_radius": 2.7994186406360964,
"max_eye_weight": 0,
"max_sequential_eye_displacement_pixels": 0
},
{
"seconds": 8,
"minimum_eye_distance_over_pin_radius": 2.720538093620307,
"max_eye_weight": 0,
"max_sequential_eye_displacement_pixels": 0
},
{
"seconds": 10,
"minimum_eye_distance_over_pin_radius": 2.7459899006401245,
"max_eye_weight": 0,
"max_sequential_eye_displacement_pixels": 0
},
{
"seconds": 12,
"minimum_eye_distance_over_pin_radius": 2.8522571566241655,
"max_eye_weight": 0,
"max_sequential_eye_displacement_pixels": 0
},
{
"seconds": 14,
"minimum_eye_distance_over_pin_radius": 2.7849986024852744,
"max_eye_weight": 0,
"max_sequential_eye_displacement_pixels": 0
},
{
"seconds": 16,
"minimum_eye_distance_over_pin_radius": 2.86097776991491,
"max_eye_weight": 0,
"max_sequential_eye_displacement_pixels": 0
},
{
"seconds": 18,
"minimum_eye_distance_over_pin_radius": 2.4994391012873294,
"max_eye_weight": 0,
"max_sequential_eye_displacement_pixels": 0
},
{
"seconds": 20,
"minimum_eye_distance_over_pin_radius": 2.3076941598447127,
"max_eye_weight": 0,
"max_sequential_eye_displacement_pixels": 0
}
]
},
"limits": [
"No reference shader runtime or pixel comparison performed.",
"The commonStrength caller-source semantics are not fully traced; formula reports the helper input.",
"CPU prechecks/license/module gates are observed but are outside the independently authored geometry reconstruction.",
"Eye support results apply to the11 existing saved Vision samples, not every possible pose.",
"No product sources, app build, host session or Git were changed."
]
}
@@ -0,0 +1,5 @@
Beauty renderer: 57 checks, 0 failures (Metal).
2026-10-22 16:24:20.836 face-tests[22582:8025448] FBBA: creating VNFaceBBoxAligner from VNFaceDetectorRevision2: VNFaceDetectorRevision2
Face processing: 116 checks passed
2026-10-22 16:24:34.977 slim-tests[22589:8025534] FBBA: creating VNFaceBBoxAligner from VNFaceDetectorRevision2: VNFaceDetectorRevision2
PASS: 1033 slim alignment checks; maximum UV oracle error 1.09828022e-05
@@ -0,0 +1,37 @@
2026-10-22 16:21:55.726 host-tests[22385:8017721] FBBA: creating VNFaceBBoxAligner from VNFaceDetectorRevision2: VNFaceDetectorRevision2
Default IOSurface maximum byte difference: 0
Alternate destination tag maximum byte difference: 0
Anatomy default 0/0 max=0 mean=0.0000000 eye=0/0 chin=0 inverted=0
Anatomy default 0/1 max=0 mean=0.0000000 eye=0/0 chin=0 inverted=0
Anatomy default 1/0 max=0 mean=0.0000000 eye=0/0 chin=0 inverted=0
Anatomy default 1/1 max=0 mean=0.0000000 eye=0/0 chin=0 inverted=0
Anatomy big-eye 0/0 max=2 mean=0.0008917 eye=33510/33880 chin=0 inverted=0
Anatomy big-eye 0/1 max=2 mean=0.0008917 eye=33510/33880 chin=0 inverted=0
Anatomy big-eye 1/0 max=2 mean=0.0008917 eye=33510/33880 chin=0 inverted=0
Anatomy big-eye 1/1 max=2 mean=0.0008917 eye=33510/33880 chin=0 inverted=0
Anatomy chin-positive 0/0 max=1 mean=0.0001459 eye=0/0 chin=116812 inverted=0
Anatomy chin-positive 0/1 max=1 mean=0.0001459 eye=0/0 chin=116812 inverted=0
Anatomy chin-positive 1/0 max=1 mean=0.0001459 eye=0/0 chin=116812 inverted=0
Anatomy chin-positive 1/1 max=1 mean=0.0001459 eye=0/0 chin=116812 inverted=0
Anatomy chin-negative 0/0 max=1 mean=0.0000849 eye=0/0 chin=60426 inverted=0
Anatomy chin-negative 0/1 max=1 mean=0.0000849 eye=0/0 chin=60426 inverted=0
Anatomy chin-negative 1/0 max=1 mean=0.0000849 eye=0/0 chin=60426 inverted=0
Anatomy chin-negative 1/1 max=1 mean=0.0000849 eye=0/0 chin=60426 inverted=0
Anatomy short-positive 0/0 max=2 mean=0.0011072 eye=0/0 chin=285953 inverted=0
Anatomy short-positive 0/1 max=2 mean=0.0011072 eye=0/0 chin=285953 inverted=0
Anatomy short-positive 1/0 max=2 mean=0.0011072 eye=0/0 chin=285953 inverted=0
Anatomy short-positive 1/1 max=2 mean=0.0011072 eye=0/0 chin=285953 inverted=0
Anatomy short-negative 0/0 max=2 mean=0.0008583 eye=0/0 chin=225648 inverted=0
Anatomy short-negative 0/1 max=2 mean=0.0008583 eye=0/0 chin=225648 inverted=0
Anatomy short-negative 1/0 max=2 mean=0.0008583 eye=0/0 chin=225648 inverted=0
Anatomy short-negative 1/1 max=2 mean=0.0008583 eye=0/0 chin=225648 inverted=0
Anatomy jaw 0/0 max=1 mean=0.0001974 eye=0/0 chin=12951 inverted=0
Anatomy jaw 0/1 max=1 mean=0.0001974 eye=0/0 chin=12951 inverted=0
Anatomy jaw 1/0 max=1 mean=0.0001974 eye=0/0 chin=12951 inverted=0
Anatomy jaw 1/1 max=1 mean=0.0001974 eye=0/0 chin=12951 inverted=0
Anatomy v-face 0/0 max=1 mean=0.0001240 eye=0/0 chin=39246 inverted=0
Anatomy v-face 0/1 max=1 mean=0.0001240 eye=0/0 chin=39246 inverted=0
Anatomy v-face 1/0 max=1 mean=0.0001240 eye=0/0 chin=39246 inverted=0
Anatomy v-face 1/1 max=1 mean=0.0001240 eye=0/0 chin=39246 inverted=0
Legacy fallback upright comparison: max=2 mean=0.0010357
Host adapter: 370 checks, 0 failures
@@ -0,0 +1 @@
Inspector: 227 checks, 0 failures
+21
查看文件
@@ -0,0 +1,21 @@
2026-10-22 16:24:26.444 osc-tests[22624:8025751] PGFaceOSC point-write desired=(0.25,0.75) setter=(0.25,0.75) readback=(0.25,0.75) mode=normalized verified=1
2026-10-22 16:24:26.452 osc-tests[22624:8025751] PGFaceOSC coordinates selection=(0.25,0.75) objectBounds=(-100,-50,200,100) canvas=(80,180) surface=320x240 origin=0
2026-10-22 16:24:26.887 osc-tests[22624:8025751] PGFaceOSC point-write desired=(0.8,0.3) setter=(1152,-432) readback=(0.8,0.3) mode=centered-pixels verified=1
2026-10-22 16:24:26.887 osc-tests[22624:8025751] PGFaceOSC coordinates selection=(0.7,0.4) objectBounds=(-1920,-1080,3840,2160) canvas=(152,78) surface=320x240 origin=0
2026-10-22 16:24:26.944 osc-tests[22624:8025751] PGFaceOSC point-write desired=(0.8,0.3) setter=(0.8,0.3) readback=(0.12345,0.87654) mode=normalized verified=0
2026-10-22 16:24:26.944 osc-tests[22624:8025751] PGFaceOSC point-write desired=(0.75,0.25) setter=(0.75,0.25) readback=(0.75,0.25) mode=normalized verified=1
2026-10-22 16:24:26.944 osc-tests[22624:8025751] PGFaceOSC coordinates selection=(0.75,0.25) objectBounds=(-100,-50,200,100) canvas=(160,60) surface=320x240 origin=0
2026-10-22 16:24:26.994 osc-tests[22624:8025751] PGFaceOSC point-write desired=(0.625,0.375) setter=(0.625,0.375) readback=(0.625,0.375) mode=normalized verified=1
2026-10-22 16:24:26.994 osc-tests[22624:8025751] PGFaceOSC coordinates selection=(0.625,0.375) objectBounds=(-100,-50,200,100) canvas=(240,60) surface=320x240 origin=0
2026-10-22 16:24:27.043 osc-tests[22624:8025751] PGFaceOSC point-write desired=(0.25,0.75) setter=(0.25,0.75) readback=(0.25,0.75) mode=normalized verified=1
2026-10-22 16:24:27.043 osc-tests[22624:8025751] PGFaceOSC coordinates selection=(0.25,0.75) objectBounds=(-100,-50,200,100) canvas=(144,180) surface=320x240 origin=0
2026-10-22 16:24:27.094 osc-tests[22624:8025751] PGFaceOSC point-write desired=(0.5,0.5) setter=(0.5,0.5) readback=(0.5,0.5) mode=normalized verified=1
2026-10-22 16:24:27.094 osc-tests[22624:8025751] PGFaceOSC coordinates selection=(0,1) objectBounds=(-100,-50,200,100) canvas=(100,140) surface=320x240 origin=0
2026-10-22 16:24:27.144 osc-tests[22624:8025751] PGFaceOSC coordinates selection=(0.25,0.75) objectBounds=(-100,-50,200,100) canvas=(nan,nan) surface=320x240 origin=0
2026-10-22 16:24:27.194 osc-tests[22624:8025751] PGFaceOSC point-write desired=(0.5,0.5) setter=(0.5,0.5) readback=(0.5,0.5) mode=normalized verified=1
2026-10-22 16:24:27.194 osc-tests[22624:8025751] PGFaceOSC coordinates selection=(0.25,0.75) objectBounds=(-100,-50,200,100) canvas=(inf,nan) surface=320x240 origin=0
2026-10-22 16:24:27.242 osc-tests[22624:8025751] PGFaceOSC point-write desired=(0.5,0.5) setter=(0.5,0.5) readback=(0.5,0.5) mode=normalized verified=1
2026-10-22 16:24:27.242 osc-tests[22624:8025751] PGFaceOSC coordinates selection=(0.25,0.75) objectBounds=(-100,-50,200,100) canvas=(80,nan) surface=320x240 origin=0
2026-10-22 16:24:27.304 osc-tests[22624:8025751] PGFaceOSC point-write desired=(0.5,0.5) setter=(0.5,0.5) readback=(0.5,0.5) mode=normalized verified=1
2026-10-22 16:24:27.304 osc-tests[22624:8025751] PGFaceOSC point-write desired=(0.5,0.5) setter=(0.5,0.5) readback=(0.5,0.5) mode=normalized verified=1
OSC adapter: 98 checks, 0 failures
@@ -0,0 +1,2 @@
2026-10-22 16:25:35.195 slim-tests[22704:8027100] FBBA: creating VNFaceBBoxAligner from VNFaceDetectorRevision2: VNFaceDetectorRevision2
PASS: 1561 slim alignment checks; maximum UV oracle error 1.09828022e-05
+31
查看文件
@@ -0,0 +1,31 @@
{
"status": "passed",
"version": "1.3.1",
"build": "16",
"checks": {
"beauty": 57,
"face": 116,
"geometry": 1033,
"hostASan": 370,
"oscASan": 98,
"inspectorASan": 227
},
"total": 1901,
"extraRealPoseASan": {
"checks": 1561,
"inputs": "NASA astronaut plus 11 local user frames; frame images and full Vision points not uploaded",
"overlapsBaseline": true
},
"maximumUVOracleError": 1.09828022e-05,
"isolatedV": {
"eyeChange": [
0,
0
],
"lowerFaceChange": 39246,
"originsCompared": 4,
"uprightMax255": 1,
"uprightMean255": 0.000124
},
"nativeVisualQA": "pending user"
}
+6 -3
查看文件
@@ -2,6 +2,8 @@
更新时间:2026-10-22,Asia/Shanghai。项目根目录:`/Users/dayu/Documents/PaintFCP`。
正在准备 **1.3.1(16)** 的 V 脸下颌修复;1901 项自动检查通过,正式安装尚未替换。
当前正式安装的 APP 为 **1.3.0(构建 15)**,已完成通用 Release 编译、正式签名、Apple 公证、票据验证及唯一正式路径安装。新增磨皮参数迁移与 1636 项自动检查已完成,原生效果视觉仍待用户实测。公开文章、PKG 与 GitHub Release 继续对应 **1.2.0**;本次未更新这些发行资料,也未覆盖模板或宣传图。
代码由 **OpenAI + Codex 全程编写,站长仅参与调试和测试**。文章和仓库须保留这个表述,不使用“站长原创代码”等说法。免费版本无需账号、激活码或付费授权;“自动注册”指系统插件注册。
@@ -84,18 +86,19 @@ Xcode 工程:`beatygril/beatygril.xcodeproj`。外层 scheme 为 `Wrapper Appl
本项目几何历史只取当前请求之前的近时记录,原版还存在近未来历史分支;冷启动、热缓存、乱序渲染、同尺寸换源和多人交叉仍有差异边界。旧离线分析字段保留兼容,但当前新面板的渲染统一使用实时自动跟随。
### 已完成的四项局部算法
### 已完成的五项局部算法
| 控制项 | 当前实现 | 防止回归的要点 |
| --- | --- | --- |
| 瘦脸 | 76 点、17 组轮廓到鼻部或瞳孔锚点的局部逆向采样 | 不恢复整脸框水平挤压;保留尺寸增益、组顺序和逐步 clamp |
| V 脸 | `69→39`、`65→35`、`70→26`、`64→34` 四组下颌到外唇局部位移 | 新版 2.4.0 使用 0.065 系数、无旧尺寸增益;两瞳孔保持不动 |
| 下巴 | `68→38`、`67→37`、`66→36` 三组局部位移 | 正值上收、负值延伸,保留正负不同系数 |
| 下颌骨 | 六组相邻轮廓半径的顺序局部位移 | 半径来自相邻轮廓点,方向锚点为 P29;不能同时求和替代逐步更新 |
| 短脸 | P62 至 P72 的下半脸闭合区域,沿 P46−P48 鼻梁轴位移 | 正值收短、负值延长;不是太阳穴区域或脸框纵向压缩 |
这四项共享由实际图像像素尺寸计算的增益。完整合法 76 点缺失时,四项安全直通,不退回猜测的脸框场。图像与磨皮、肤色、牙齿、眼睛蒙版共用几何变形路径,避免效果与蒙版错位。
此前四项沿用由实际图像像素尺寸计算的增益;V 脸对齐新版目标,不带该额外增益。完整合法 76 点缺失时,五项安全直通,不退回猜测的脸框场。图像与磨皮、肤色、牙齿、眼睛蒙版共用几何变形路径,避免效果与蒙版错位。
**仍为近似实现的五项:大眼、窄脸、V 脸、颧骨、小头。** 原版完整链为 `thin → narrow → V → jaw → cheek → chin → short → small-head → eyes`,本项目尚未完全恢复整条组合链的数学及顺序。用户单项验收不代表所有参数组合逐像素等价。详细索引、系数和独立数值场验证见[下巴与坐标分析](analysis/下巴与坐标分析.md)、[短脸与下颌骨分析](analysis/短脸与下颌骨分析.md)。
**仍为近似实现的四项:大眼、窄脸、颧骨、小头。** 原版完整链为 `thin → narrow → V → jaw → cheek → chin → short → small-head → eyes`,本项目尚未完全恢复整条组合链的数学及顺序。用户单项验收不代表所有参数组合逐像素等价。V 脸修复见 [下颌区域分析](analysis/V脸下颌区域修复.md)。详细索引、系数和独立数值场验证见[下巴与坐标分析](analysis/下巴与坐标分析.md)、[短脸与下颌骨分析](analysis/短脸与下颌骨分析.md)。
### 坐标约定
+5
查看文件
@@ -138,3 +138,8 @@ Motion:独立普通视频项目,源PTS0、1920×1080/25fps/10秒,媒体通
按用户纠正后的截图需求,迁移连续五官保护、非肤色区保护和局部微细锐化;保留旧 bool、全局磨皮/锐化 ID 与旧工程行为。正式签名源码 `2f2c081980dc610ac810f8daf92da8966f310802`。1636 项通过:57 Beauty、116 Face、796 几何、341 宿主适配 ASan、98 OSC ASan、228 Inspector ASan(含 1 项可选 PNG 输出)。保护 0/50/100 像素响应、色彩覆盖隔离、透明度、v1 状态迁移、新控件归档/插值/输入/重置/旁路/松手前发布均有检查;离屏面板已查看。
通用 Release 正式签名、公证 Accepted(`ca96837f-bf33-44fa-8d58-799026ce5c7d`)、票据、双架构严格签名、安装身份、Gatekeeper、PluginKit 正式路径与临时副本清理通过。独立从 origin 克隆签名源码节点,205 个受跟踪文件逐字节匹配且 strict/full fsck 通过。本次没有原生新滑杆/效果视觉验收,也没有生成新 PKG 或更新文章;用户已保存并退出宿主后才执行安装。详见 `verification/v1.3.0/` 与 `analysis/新版磨皮参数迁移.md`。
## 1.3.1(16)V 脸下颌区域修复(构建前)
移除 V 脸的脸框近似宽带,改为新版目标的四组下颌到外唇 pin,单项映射为 clamp(V,0,1)×0.065,不叠加旧尺寸增益。无合法76点时直通,图像与四张蒙版同场变形。1901项自动检查通过:57 Beauty、116 Face、1033几何、370 Host ASan、98 OSC ASan、227 Inspector ASan。原失败复现、点位/CPU/AIR证据和未对齐范围见 analysis/V脸下颌区域修复.md。另对 NASA 人像和本机用户视频11帧运行1561项几何ASan专项(含重复基础用例,不相加),通过;用户帧和完整点坐标未上传。安装及用户视觉待完成,当前正式APP仍为1.3.0。