This commit is contained in:
root
2026-10-09 23:22:28 +08:00
parent f7902b86c8
commit 658b232a39
13 changed files with 1019 additions and 705 deletions
+23 -12
View File
@@ -73,8 +73,8 @@
var HINT_KEEP = '保持不动';
var HINT_TURN_LEFT = '请向左转头'; // 用户向自己的左侧转
var HINT_TURN_RIGHT = '请向右转头'; // 用户向自己的右侧转
var HINT_RAISE = '请抬头';
var HINT_LOWER = '请低头';
var HINT_RAISE = '请略微抬头';
var HINT_LOWER = '请略微低头';
var HINT_FRONT = '请正对屏幕';
var RAD2DEG = 180 / Math.PI;
@@ -157,8 +157,8 @@
/**
* check(points, target, mirrored) -> { ok, hint }
* target: 'front' | 'left' | 'right'
* 'front' : |yaw|<=15 且 |pitch|<=18;不 ok 时一律 hint='请正对屏幕'
* (产品要求 2026-09-28:正脸步不提示左右转头/抬头低头,只引导回正)
* 'front' : |yaw|<=15 且 |pitch|<=18;不 ok 时按超出更多的一项给方向提示
* (UI 反馈 2026-10:动态提示「请向左转头」「请略微抬头」等,取代此前只提示回正)
* 'left' : 画面中看到左脸 = 被摄者头向右转(语义 yaw ∈ [-75°,-28°]),|pitch|<=20
* 'right' : 画面中看到右脸 = 被摄者头向左转(语义 yaw ∈ [28°,75°]),|pitch|<=20
* ok=true 时 hint='保持不动';输入非法(含 estimate 返回 null 的退化特征点)时 ok=false、hint='请正对屏幕'。
@@ -181,8 +181,12 @@
if (Math.abs(sYaw) <= FRONT_YAW_MAX && Math.abs(pitch) <= FRONT_PITCH_MAX) {
return { ok: true, hint: HINT_KEEP, yaw: sYaw };
}
// 正脸步只提示回正(产品要求:不区分左右转头/抬头低头,避免正脸阶段引导混乱)
return { ok: false, hint: HINT_FRONT, yaw: sYaw };
// 按超出阈值比例更大的一项引导回正:头偏向自己左侧(yaw>0)→请向右转头;抬头过多(pitch>0)→请略微低头
var yawOver = Math.abs(sYaw) / FRONT_YAW_MAX, pitchOver = Math.abs(pitch) / FRONT_PITCH_MAX;
if (yawOver >= pitchOver) {
return { ok: false, hint: sYaw > 0 ? HINT_TURN_RIGHT : HINT_TURN_LEFT, yaw: sYaw };
}
return { ok: false, hint: pitch > 0 ? HINT_LOWER : HINT_RAISE, yaw: sYaw };
}
if (target === 'left' || target === 'right') {
@@ -293,22 +297,29 @@ if (typeof module !== 'undefined' && typeof require !== 'undefined' && require.m
ok(bc.ok === true, '反向侧脸 target=left ok');
ok(HeadPose.check(back, 'right', false).ok === false, '反向侧脸 target=right 拒绝');
// 7) 侧脸做 front check → 拒绝并只引导回正(产品要求:正脸步不再提示左右转头)
// 7) 侧脸做 front check → 拒绝并引导转回(被摄者左转 → 请向右转头;反向 → 请向左转头)
var sc = HeadPose.check(makeSide(), 'front', false);
ok(sc.ok === false && sc.hint === '请正对屏幕', '侧脸 front 拒绝,hint=请正对屏幕');
ok(sc.ok === false && sc.hint === '请向右转头', '左转侧脸 front 拒绝,hint=请向右转头');
var scb = makeSide();
scb[30] = { x: 182.3, y: 140 };
scb[33] = { x: 182.3, y: 161.5 };
ok(HeadPose.check(scb, 'front', false).hint === '请向左转头', '右转侧脸 front 拒绝,hint=请向左转头');
// 8) roll:右眼(45 点)下移 10px → roll≈5.7°
var tilted = makeFrontal();
tilted[45] = { x: 250, y: 110 };
ok(Math.abs(HeadPose.estimate(tilted, false).roll - 5.71) < 0.2, 'roll≈5.71°');
// 9) 低头:鼻底上移 → pitch<0,front 拒绝并只提示回正(正脸步不再提示抬头/低头)
// 9) 低头:鼻底上移 → pitch<0,front 拒绝并提示略微抬头
var down = makeFrontal();
down[33] = { x: 200, y: 100 };
var de = HeadPose.estimate(down, false);
var dc = HeadPose.check(down, 'front', false);
ok(de.pitch < -30, '低头 pitch<0 (got ' + de.pitch.toFixed(2) + ')');
ok(dc.ok === false && dc.hint === '请正对屏幕', '低头 front 拒绝,hint=请正对屏幕');
ok(dc.ok === false && dc.hint === '请略微抬头', '低头 front 拒绝,hint=请略微抬头');
var up = makeFrontal();
up[33] = { x: 200, y: 200 };
ok(HeadPose.check(up, 'front', false).hint === '请略微低头', '抬头过多 front 拒绝,hint=请略微低头');
// 10) 非法输入:check 不抛异常,返回兜底引导
var bad = HeadPose.check(null, 'front', false);
@@ -327,7 +338,7 @@ if (typeof module !== 'undefined' && typeof require !== 'undefined' && require.m
ok(HeadPose.estimate(tiny, false) === null, 'faceHeight 过小 → estimate 返回 null');
ok(HeadPose.check(tiny, 'front', false).hint === '请正对屏幕', 'faceHeight 过小 check 兜底');
// 13) 正脸阈值放宽到 |yaw|≤15°(产品要求 2026-09-28):yaw≈14.9° 应通过,yaw≈16.2° 应拒绝且只提示回正
// 13) 正脸阈值放宽到 |yaw|≤15°(产品要求 2026-09-28):yaw≈14.9° 应通过,yaw≈16.2° 应拒绝并引导转回
ok(HeadPose.config.FRONT_YAW_MAX === 15, 'config.FRONT_YAW_MAX = 15');
var slight = makeFrontal();
slight[30] = { x: 205.6, y: 140 }; // 偏移 5.6 → yaw≈14.9°(YAW_COEFF=3.8 标定)
@@ -342,7 +353,7 @@ if (typeof module !== 'undefined' && typeof require !== 'undefined' && require.m
var se2 = HeadPose.estimate(slight2, false);
ok(se2.yaw > 15 && se2.yaw < 17.5, '偏头 yaw∈(15,17.5) (got ' + se2.yaw.toFixed(2) + ')');
var sc3 = HeadPose.check(slight2, 'front', false);
ok(sc3.ok === false && sc3.hint === '请正对屏幕', 'yaw≈16.2° front 拒绝,hint=请正对屏幕');
ok(sc3.ok === false && sc3.hint === '请向右转头', 'yaw≈16.2° front 拒绝,hint=请向右转头');
if (failures > 0) {
console.error('\n' + failures + ' 项自测失败');