AI-深度学习

口鼻遮挡工程实录:06 PIPNet98关键点与响应

展开合集目录
  1. 口鼻遮挡工程实录:01 需求与判断边界
  2. 口鼻遮挡工程实录:02 方案探索与演进
  3. 口鼻遮挡工程实录:03 总体架构与完整时序
  4. 口鼻遮挡工程实录:04 图像预处理与坐标转换
  5. 口鼻遮挡工程实录:05 头部检测与YuNet
  6. 口鼻遮挡工程实录:06 PIPNet98关键点与响应
  7. 口鼻遮挡工程实录:07 FaceOcc分割与口鼻覆盖率
  8. 口鼻遮挡工程实录:08 姿态与几何分析
  9. 口鼻遮挡工程实录:09 多证据融合规则
  10. 口鼻遮挡工程实录:10 跟踪与持续确认
  11. 口鼻遮挡工程实录:11 YOLO-World物体复核
  12. 口鼻遮挡工程实录:12 模型转换与海思部署
  13. 口鼻遮挡工程实录:13 板端运行与调试闭环
  14. 口鼻遮挡工程实录:14 测试评估与问题复盘
  15. 口鼻遮挡工程实录:A 附录A-参数字典
  16. 口鼻遮挡工程实录:B 附录B-状态与结果字段
  17. 口鼻遮挡工程实录:C 附录C-模型与代码索引
  18. 口鼻遮挡工程实录:D 附录D-完整教学样例
口鼻遮挡工程实录:06 PIPNet98关键点与响应的封面

系列编排日期为 2026 年 8 月;正文依据 2026-10-12 核对的实现整理。历史实测保留真实日期,教学数字不代表实测;本次未重新执行板端推理。

返回系列目录 · 本篇为 14 章+4 份附录中的一篇。

PIPNet 在这条链路中的职责

PIPNet 提供鼻嘴区域的位置,还允许观察每个点的响应强弱及不同预测之间的一致性。它本身没有给当前系统输出一个经过校准的“手遮嘴概率”。PIPNet 的原始方法称为 Pixel-in-Pixel Net,研究入口见 官方仓库;以下张量、阈值和统计均按本地部署代码说明。

五个输出张量

输出 本地形状 用途
cls_map [1,98,8,8] 为每个点选择最强响应网格
offset_x [1,98,8,8] 网格内 x 偏移
offset_y [1,98,8,8] 网格内 y 偏移
nb_x [1,980,8,8] 每个点对十个邻居的 x 预测
nb_y [1,980,8,8] 每个点对十个邻居的 y 预测

256 输入配合 stride 32 得到 8×8 网格。输出虽然空间分辨率小,坐标仍由连续偏移精修,不能把结果精度简单理解成每点只能落在 64 个位置。

板端检查输出数、尺寸、指针和所有值是否有限。解码失败保持 numPoints=0,主流程转为错误处理;不能沿用上一帧的点位。

自身预测与邻居预测

对第 i 个点,找到 cls_map[i] 的最大位置 (col,row),在相同位置取偏移:

own_x = (col + offset_x[i,col,row]) / 8
own_y = (row + offset_y[i,col,row]) / 8

假设最大网格为 (3,4)、偏移为 (0.25,0.5),自身归一化坐标为 (0.40625,0.5625),即 256 坐标系中的 (104,144)。随后还要加入其他点对该点的邻居预测,不能在这里直接结束解码。

meanface 数据生成邻接关系;反向索引回答“哪些预测通道指向当前这个点”。本地实现按照补齐的反向索引表,将自身与邻居预测平均,以保持与参考解码一致。meanface 表不是人脸模板直接输出,也不是一张运行时待匹配的人脸照片。

peak 与 gap 的具体计算

peak_i = 当前点响应图中的最大原始值
gap_i  = 最大值 − 排除最大位置后的次大值

原始响应不经过概率归一化,可以低于零或超过一。gap 较小意味着两个位置竞争接近;peak 较低意味着响应弱。但它们受脸尺寸、光照、姿态、图像质量及模型转换影响,不能单独对应遮挡。

如果两个位置都为 0.10,peak=0.10、gap=0;即使 peak 超过 0.08,gap 仍会触发弱点条件。仅看均值会掩盖这种局部歧义。

dispersion 为什么需要去重

坐标解码保持原补齐表的平均规则;分散度统计则去除补齐造成的重复邻居。设去重后的自身与邻居预测集合为 Q:

中心 μ = Q 中二维坐标的均值
dispersion = sqrt(mean((qx−μx)² + (qy−μy)²))

它使用裁剪归一化坐标,不是脸宽归一化坐标,也不是跨帧抖动方差。两个预测为 (0.4,0.5) 和 (0.5,0.5) 时,中心 (0.45,0.5),分散度为 0.05。它衡量同一次推理内部多个预测的一致性。

若重复索引被计数多次,某个预测会获得不应有的统计权重。当前代码用集合去重仅用于分散度,不能顺便改变原坐标解码规则,否则与参考实现产生另一种差异。

98 点索引及两种嘴部点集

分组 索引(含两端) 点数
下颌轮廓 0~32 33
眉部 33~50 18
鼻部 51~59 9
双眼 60~75 16
外唇 76~87 12
内唇 88~95 8
最后两点 96~97 2

鼻尖使用 54;嘴中心使用外唇 76~87 的均值。嘴部响应统计使用 76~95,共 20 点;嘴部面积 ROI 只用外唇 76~87,共 12 点。代码的半开区间 [76,96) 和 [76,88) 正是在表达这一差别。

从逐点证据到区域证据

当前弱点规则为:peak<0.08 OR gap<0.01 OR dispersion>0.05。区域弱点比例达到 25% 即 suspect=true。鼻部九个点至少三个弱点会达到阈值;嘴部二十个点至少五个弱点会达到阈值。

区域同时记录均值与弱点索引,判定使用逐点逻辑后的比例,不是“区域平均 peak 低于 0.08”。例如五个嘴点很弱、十五个点很强,均值仍可能高,但弱点比例已经达到 25%。

roi_spread_max=0.08 是另一项参考:标记局部不稳定、参与旧规则和物体证据可靠性判断。当前可见优先策略不会仅因此把区域覆盖率改成无效。

应如何验证

比较同一张裁剪的五个原始输出、argmax、邻居索引、最终点坐标、peak、gap 和 dispersion。不要只比较画出来的点是否“看着差不多”。板端卸载后输出必须仍有效;非有限值、错误输出顺序和布局错误应作为错误处理,而不是降低阈值放行。

代码入口:PipNet.cpp::decodePipNet()、PipNetMeanfaceData.h、FaceOcclusionPolicy.cpp::response()。本章教学数字可在附录 D 手工复算。


上一篇:头部检测与YuNet · 系列目录 · 下一篇:FaceOcc分割与口鼻覆盖率