diff --git a/h5/js/capture-quality.js b/h5/js/capture-quality.js index b4e2bf0..7bafc18 100644 --- a/h5/js/capture-quality.js +++ b/h5/js/capture-quality.js @@ -6,7 +6,7 @@ 'use strict'; // Real-phone feedback: ease alignment and normal hand/head movement while // retaining two checked frames, one face, framing and final JPEG validation. - var config = Object.freeze({ version: '2026-10-15-light-110-220-v6', score: 0.4, + var config = Object.freeze({ version: '2026-10-15-pitch-roll-relaxed-v7', score: 0.4, near: 0.30, far: 0.68, center: 0.16, edge: 0.01, dark: 110, bright: 220, holdMs: 450, minFrames: 2, maxGapMs: 2000, yawDrift: 8, pitchDrift: 8, centerDrift: 0.055, sizeDrift: 0.065 }); diff --git a/h5/js/head-pose.js b/h5/js/head-pose.js index a0cd666..1408c40 100644 --- a/h5/js/head-pose.js +++ b/h5/js/head-pose.js @@ -66,11 +66,11 @@ // as side views. These empirical angles are not upstream quality scores. // 2026-10-15: expand accepted angles by 20%; lower side minimum by 20%. var FRONT_YAW_MAX = 18; - var FRONT_PITCH_MAX = 21.6; + var FRONT_PITCH_MAX = 26; var SIDE_YAW_MIN = 24; var SIDE_YAW_MAX = 84; - var SIDE_PITCH_MAX = 24; - var ROLL_MAX = 18; + var SIDE_PITCH_MAX = 29; + var ROLL_MAX = 22; var HINT_KEEP = '保持不动'; var HINT_TURN_LEFT = '请向左转头'; // 用户向自己的左侧转 @@ -159,10 +159,10 @@ /** * check(points, target, mirrored) -> { ok, hint } * target: 'front' | 'left' | 'right' - * 'front' : |yaw|<=18 且 |pitch|<=21.6、|roll|<=18;角度不合格只提示回正, + * 'front' : |yaw|<=18 且 |pitch|<=26、|roll|<=22;角度不合格只提示回正, * 不在正脸拍摄完成前播侧脸转头指令。 - * 'left' : 画面中看到左脸 = 被摄者头向右转(语义 yaw ∈ [-84°,-24°]),|pitch|<=24 - * 'right' : 画面中看到右脸 = 被摄者头向左转(语义 yaw ∈ [24°,84°]),|pitch|<=24 + * 'left' : 画面中看到左脸 = 被摄者头向右转(语义 yaw ∈ [-84°,-24°]),|pitch|<=29 + * 'right' : 画面中看到右脸 = 被摄者头向左转(语义 yaw ∈ [24°,84°]),|pitch|<=29 * ok=true 时 hint='保持不动';输入非法(含 estimate 返回 null 的退化特征点)时 ok=false、hint='请正对屏幕'。 */ function check(points, target, mirrored) { diff --git a/h5/test/capture-quality-browser.mjs b/h5/test/capture-quality-browser.mjs index 658f463..c01d793 100644 --- a/h5/test/capture-quality-browser.mjs +++ b/h5/test/capture-quality-browser.mjs @@ -153,7 +153,7 @@ try { const row = body.capture_diagnostics.views[key]; assert.equal(row.mode, 'live'); assert.equal(row.direction_checked, true); assert(row.score >= .4 && row.luma >= 110 && row.luma <= 220); - assert(Math.abs(row.roll) <= 18); + assert(Math.abs(row.roll) <= 22); } assert(Math.abs(body.capture_diagnostics.views.front.yaw) <= 18); assert(body.capture_diagnostics.views.left.yaw <= -24 && body.capture_diagnostics.views.left.yaw >= -84); diff --git a/h5/test/customer-feedback-fourth.js b/h5/test/customer-feedback-fourth.js index c97cb9a..f27c4b5 100644 --- a/h5/test/customer-feedback-fourth.js +++ b/h5/test/customer-feedback-fourth.js @@ -35,19 +35,19 @@ for (const yaw of [-18.01, 18.01, -45, 45]) { assert.equal(check(face(yaw)).hint, '请正对屏幕', 'front correction must not ask for a side view before capture'); assert.equal(check(face(yaw), { mirrored: true }).hint, '请正对屏幕'); } -for (const pitch of [-21.59, 21.59]) assert(check(face(0, pitch)).ok); -for (const pitch of [-21.61, 21.61]) assert.equal(check(face(0, pitch)).hint, '请正对屏幕'); +for (const pitch of [-25.99,25.99]) assert(check(face(0, pitch)).ok); +for (const pitch of [-26.01,26.01]) assert.equal(check(face(0, pitch)).hint, '请正对屏幕'); assert.equal(check(face(0), { target: 'right' }).hint, '请向左转头', 'side step retains its proper turn instruction'); assert.equal(check(face(0), { target: 'left' }).hint, '请向右转头'); assert(check(face(0, 0, 12)).ok, 'normal tilt now passes'); -assert(check(face(0,0,17.99)).ok); -assert.equal(check(face(0, 0, 18.01)).hint, '请勿歪头'); +for(const roll of [-21.99,21.99]) assert(check(face(0,0,roll)).ok); +for(const roll of [-22.01,22.01]) assert.equal(check(face(0,0,roll)).hint,'请勿歪头'); for (const target of ['left','right']) { const sign=target==='left'?-1:1; for (const yaw of [23.99,84.01]) assert(!check(face(sign*yaw),{target}).ok); for (const yaw of [24.01,83.99]) assert(check(face(sign*yaw),{target}).ok); - for (const pitch of [-23.99,23.99]) assert(check(face(sign*45,pitch),{target}).ok); - for (const pitch of [-24.01,24.01]) assert(!check(face(sign*45,pitch),{target}).ok); + for (const pitch of [-28.99,28.99]) assert(check(face(sign*45,pitch),{target}).ok); + for (const pitch of [-29.01,29.01]) assert(!check(face(sign*45,pitch),{target}).ok); } assert(check(face(45), { target: 'right' }).ok); assert(!check(face(45), { target: 'left' }).ok); @@ -116,7 +116,7 @@ assert.equal(Diagnostics.assess(raw).views.right.status, 'valid'); const normalized = Diagnostics.normalize({ version: Quality.config.version, secret: 'discard', views: { front: { mode: 'live', yaw: 1, score: .9, luma: Infinity, secret: 'discard' }, left: { mode: 'unchecked', reason: 'model-unavailable' } } }); assert.equal(normalized.policy.capture.holdMs, 450); assert.equal(normalized.policy.capture.minFrames, 2); -assert.equal(normalized.version, '2026-10-15-light-110-220-v6'); +assert.equal(normalized.version, '2026-10-15-pitch-roll-relaxed-v7'); assert.equal(normalized.views.front.luma, undefined); assert(!JSON.stringify(normalized).includes('discard')); assert.equal(Diagnostics.normalize({ version: '