系列编排日期为 2026 年 8 月;正文依据 2026-10-12 核对的实现整理。历史实测保留真实日期,教学数字不代表实测;本次未重新执行板端推理。
返回系列目录 · 本篇为 14 章+4 份附录中的一篇。
二维姿态代理的用途
姿态分析用于解释点位的相对分布,区分侧向贴边、倾斜及不可靠几何。它没有相机标定、三维人脸拟合、床面位置或睡眠标签,因此不输出可靠的三维 yaw/pitch/roll,也不确认睡眠状态。
本文的左右均指画面方向。摄像头或播放器镜像后,画面左右与人的解剖左右可能相反,必须保持标注和 JSON 采用同一约定。
先恢复裁剪长宽比
PIPNet 的输入被直接缩放为正方形,但原脸部 crop 可能是矩形。若直接在 256×256 上算倾角,长宽拉伸会改变方向。
设原裁剪宽高为 w、h,归一化点为 (u,v):
|
这是恢复长宽比例后再施加统一尺度,不需要回到可能很大的原图尺寸。后续投影与角度因此保持原裁剪几何。
以眼线与轮廓建立坐标系
当前姿态锚点为下颌 0~32 与眼部 60~75,共 49 点。至少 75% 同时满足 peak、分散度及裁剪范围条件,才尝试建立参考系。
左右眼中心分别取 60~67、68~75 的平均,再按画面 x 排序。眼线单位方向记为 e,其垂直向下方向记为 n;两眼中点为 o。轮廓端点 0、32 沿 e 投影,得到左右边界及脸宽 Wf。
|
原点在眼线与轮廓投影中线的交点,X 向画面右,Y 向下。眼间距小于 8、脸宽小于 24 或眼距/脸宽超过 0.9,会拒绝这个参考系;这里的长度处于上述统一尺度坐标中。
coordinates_valid 与 posture.valid 不完全相同。坐标可以已计算出来,但鼻尖落在轮廓投影范围外,使姿态参考被标记无效。读 JSON 时不能只看是否存在一组坐标。
整脸凸包为什么排除鼻嘴
轮廓近似由 0~32 下颌点与 33~50 眉点建立。若把鼻嘴点也纳入,漂移出去的鼻嘴可能撑大边界,反过来被判成“仍在脸内”。当前代码要求边界点可靠比例至少 85%,包含 0、16、32,且可靠眉点至少八个,凸包归一化面积至少 0.08。
点到凸包的有符号距离:内部为正,外部为负。诊断使用 1e-6 的脸宽容差,默认 outside_margin=0.02 用于标记较明显越界。凸包是几何近似,不是 FaceOcc 分割的真实边界。
当前规则不让整脸凸包可靠性否决已经满足条件的鼻嘴放行;legacy_state 仍可显示旧版 LANDMARK_UNRELIABLE。
同高度脸颊距离
左右脸颊分别使用 0~12 与 20~32 的相邻可靠线段,排除下巴中央和眉部。在某个鼻嘴点的高度 y,与脸颊线段求交,得到该高度的边界 x。没有覆盖该高度的可靠线段时,距离记为缺失,不跨缺口外推。
|
距离都除过脸宽,仍为内正外负。默认接触带为 −0.15 ≤ d ≤ 0.04,即脸外 15% 到脸内 4% 的区间。
侧向候选不是一个点贴边就成立
同一侧必须同时满足鼻部和嘴部条件:中心在接触带内,各组至少 50% 点在接触带内,没有超过外侧上限的极端点,各组至少 75% 点 peak 达标且分散度不超过局部参考上限。嘴中心来自外唇,但嘴组接触比例统计 76~95。
只有恰好一侧满足鼻嘴共同条件时才成为候选。鼻贴左、嘴贴右,不属于同侧;孤立飞点远离脸颊,也不应被解释成正常侧向姿态。
持续同方向达到时间和次数门槛后,SIDE_LEFT_CANDIDATE 升为 SIDE_LEFT_SUSPECTED,右侧同理。方向变化会重计。
与最终遮挡状态的关系
当前顺序是:无效鼻嘴 ROI 先输出不确定;两区域覆盖均达标先输出可见;其余情况才考虑同侧候选、可靠倾斜,最后使用分割与响应融合状态。独立 pose_state 仍可保留姿态诊断。
可靠倾角绝对值达到默认 30° 时可输出 POSE。旧版鼻嘴中线偏移、脸宽比仍在诊断字段中,但不能把它们当作当前单独触发侧向主状态的阈值。
当前 pose_action=observe 只观察姿态;设为 abnormal 才允许姿态进入持续异常候选。它仍没有增加外部报警动作。
核对函数:posture()、outline()、lateral()、selectState(),均在 FaceOcclusionPolicy.cpp。测试应覆盖横竖裁剪、倾斜、缺失脸颊、左右切换和鼻嘴漂移。
