跳到主要内容

人脸检测与识别 — 从「框出脸」到「认出人」

这一章讲三件事: 人脸识别系统的五道工序各解决什么; MTCNN 用「三个小网络接力」同时做好检测与对齐(把脸摆正); 以及为什么识别的关键不在网络在损失函数——从 softmax 到 ArcFace 的三级跳。 这是全书第一个「完整产品级流水线」的实例:前一层的输出就是后一层的输入,环环相扣。

1. 顶层全景:五道工序

图像采集 → 人脸检测 → 对齐 → 特征提取 → 人脸识别(比对)
│ │ │ │
找到脸在哪 把脸摆正 脸 → 向量 向量比距离
(MTCNN 的活) (关键点+ (深度卷积网) (超过阈值=同一人)
旋转缩放)

图说:狭义「人脸识别」只指最后一步;广义系统包含整条流水线。
书里先认这个区分,再逐段讲。

书里给的现实压力是这条流水线的背景:场景从单一限定走向广场、车站、地铁口,人脸尺度多变、数量大、姿态杂、遮挡多(帽子口罩)、光照恶劣1。另外它属生物特征识别——靠人脸、指纹、虹膜这类「人身上的特征」区分个体,人脸路线的优势是自然、不易被察觉2

2. 检测的地基:目标检测的演进逻辑

人脸检测是目标检测的特例。目标检测=找出图里所有感兴趣的目标,既报类别又报位置;难点在外观姿态各异、光照遮挡干扰,是视觉领域最有挑战的问题之一3。书里把演进线拉出来,逻辑比年代重要:

阶段代表解决了什么遗留什么
前深度学习Viola Jones、HOG人工特征+滑窗能跑了特征靠人设计
R-CNN(2014)区域+CNN 特征从「经验驱动特征」转向「数据驱动特征」,检测性能较以往提升 50%4每个候选区域都要跑一遍 CNN,慢
Fast R-CNN整图共享特征+ROI 池化全图只提一次特征,端到端可求导、训练更易仍依赖慢速的「选择性搜索」出候选
Faster R-CNN区域候选网络 RPN让网络自己出候选,摆脱选择性搜索,实现完全端到端5

读法:这条线的主题是「候选区域从哪来、特征在哪里算」两件事被逐步交给网络,人工环节逐个清场。

3. MTCNN:三个小网络接力

人脸检测输出的是「脸在哪」,但识别还需要「脸摆正」——对齐:找出眼角、鼻尖、嘴角等关键点,用相似变换(旋转、缩放、平移)把脸变换到标准姿态,消除姿态表情差异6MTCNN(多任务级联卷积网络,深圳先进技术研究院乔宇团队)用一套架构同时做检测与对齐7

它的聪明处在「接力」而非「一口吃」8:

① 图像金字塔:把原图放大缩小一串,适应远近不同的人脸
② P-Net(小网,快):全图粗筛候选窗 + 边框回归校正
+ 非极大值抑制(NMS,压掉同一张脸的重叠框)
③ R-Net(中网):拒掉大部分假窗口,继续校正+NMS
④ O-Net(大网,最准最慢):输出最终人脸框 + 5 个关键点

从 P 到 R 到 O,输入越来越大、通道越来越多、网络越来越深,准确率也越来越高、速度越来越慢。为什么要三个? 书里的算术很直白:直接上 O-Net 全图扫,速度会非常慢;P 先过滤一轮、R 再过滤一轮,最慢最准的网只看最少的窗口,每一步都提前减少待判数量9。这是工程上「用流水线换吞吐(单位时间的处理量)」的教科书案例——快网管排除,慢网管决断。

4. 深水区:分类损失为什么不适合识别

检测之后的任务是「认出人」:把对齐后的脸图喂进深度卷积网络,变成一个向量,再比较向量距离10。问题藏在损失函数里。普通分类用 softmax,它只要求最后一层输出的特征「可分」——不要求同类紧凑、异类远离,这恰恰不适合人脸11

书里用 MNIST 做了个可见的演示:让分类网络把每张图输出成 2 维向量(为了能画出来),训练完画散点——同一类的点彼此散得很开,不同类的点在中心区域粘在一起12。以「向量距离近=同一个人」的判据衡量,这种特征不合格:两张同一个人的脸,距离可能比两张陌生人的脸还远。

判断(我们的,不是书里的): 「分类可分 ≠ 度量可用」这一课远不止人脸在用。今天所有以「向量相似度」为检索(按相似度查找)依据的系统(以图搜图、语义检索)都继承同一个要求:做检索的嵌入空间要「类内紧、类间远」。本章的损失函数三级跳,是理解一切「嵌入检索」系统的最小案例。 如果错,会错在: 如果某类检索任务的评测其实只按分类精度算,那「度量学习必要」的论断就超出了任务需要——判据要看下游怎么比相似度。

5. 主走查:损失函数的三级跳

本章的主走查不是一段训练循环,而是损失函数的演进——每一步都针对上一步的具体短板。

第一级:softmax 损失(起点)。 直接拿分类损失训人脸。收敛快,但准确率到 0.9 左右就上不去——它显式优化的只是「分类对」,不显式管类内类间距离13

第二级:Triplet Loss(把「距离」写进损失)。 属于度量学习(metric learning:直接学习「怎么量距离」)。每次取三张图:两张同一人(基准 a、正样本 p)、一张别人(负样本 n),目标是「a 到 p 的距离 + 余量 < a 到 n 的距离」,不满足就罚14。方向完全正确,但书里如实说短板:三元组怎么挑讲究技巧,而且要求数据集大——负样本要足够「像而不同」,学习才有梯度15

第三级:Center Loss + ArcFace(把约束做进几何)。 Center Loss 给每个类别维护一个中心点,把每个样本的特征往自己的中心拉;总损失 L = softmax 损失 + λ·Center 损失——softmax 管类间分离,Center 管类内聚拢,λ 调两股力的比例16。短板在内存:类别一多(超过 1 万类)每类存一个中心,显存吃不消17

ArcFace 是集大成者,它的转化值得一走:

分类打分 = 权重 W 与特征 x 的内积
= |W||x|·cos θ (θ 是两者夹角)
ArcFace 第一步:把 W 和 x 都归一化(长度变 1)→ 打分只剩 cos θ
「距离」从此全部由「角度」代表
第二步:给目标类的角度直接加上一个余量 m → cos(θ+m)
要求网络把同类特征压得更紧,角度间隔拉得更开
第三步:乘一个 scale s(书里 s=30.0, m=0.50),把分类投到大半径超球面上[^18]

效果:著名的 MegaFace 赛事成绩长期停在 91% 左右,
洞见实验室用 ArcFace 提交后迅速提到 98%[^19]

书里还给了九步伪代码和可跑的实现,核心操作就一个:one_hot.scatter_ 把 cos(θ+m) 放回目标类位置、其余类保留原 cos θ——「只为难目标类」18。演进线的后半段书里有谱系:FaceNet 用 Triplet 开路,L-Softmax/SphereFace 逐步归一化权重,AM-Softmax 到 ArcFace 收束成「直接在角度上加余量」——角度距离比余弦(用夹角的 cos 值量两个向量像不像)距离对间隔的影响更直接19

6. 实战串讲,以及 100% 该怎么读

书里的实战流水线:先用 MTCNN 批量检测对齐——5749 张图跑了约 35 分钟(进度条显示 2.69it/s);删掉样本少于 4 张的人;再用预训练的 resnet18 变体提特征比对,在 LFW 测试集上输出「准确率: 100%,阀值: 0.11820279」20

这组数字要打折看,书里没说但我们替它说: LFW 是几百人量级、正面对照为主的小基准,与「车站人流、戴口罩」的 §1 场景是两个世界;阈值 0.118 是在同分布数据上挑出来的,换场景必须重标。流水线本身(检测→对齐→特征→阈值比对)是可迁移的,数字不是。

7. 作者的判断与证据

给了证据的: 损失三级跳每级都配了动机与短板;MegaFace 91%→98% 给了可查的赛事背景;实战的 2.69it/s、样本过滤规则、最终准确率输出都是实跑。

转述文献的: MTCNN 与 ArcFace 都注明了论文来源(R-CNN 还给了 arXiv 编号);「softmax 准确率卡在 0.9」属经验观察,未附实验。

作者未做的: 没有给 Triplet/Center/ArcFace 三者在同一数据上的对照实验——三级跳的「跳」是文献谱系,不是本书的消融实验(逐个拆件对比)。读者引用优劣结论时应回原论文。

8. 边界与局限

  • 活体与攻击不在本章。 照片翻拍、面具、视频注入这些落地必答题书里没碰(对抗攻击在第 12 章只讲数字图像)。
  • 检测谱系止于 Faster R-CNN。 YOLO、SSD 这类单阶段检测器书里没有——它们才是今天实时场景的主流。
  • ArcFace 的 margin 选取(m)、数据清洗对最终精度的影响,书里没有给调参指引。
  • 隐私与合规问题全书未提;人脸数据的收集与存储在今天有明确的法律边界(补充(不在书里,来自通用知识))。

9. 可带走的

  1. 人脸识别是五道工序的流水线,「识别」狭义只指最后的比对一步;
  2. 目标检测的演进主题:候选区域与特征计算逐步全交给网络(R-CNN→Faster R-CNN);
  3. MTCNN 的接力逻辑:快网粗筛、慢网决断,层层过滤让最贵的计算只花在最少候选上;
  4. 对齐=关键点+相似变换,把姿态差异从特征里剥离;
  5. 分类只要求「可分」,识别还要求「类内紧、类间远」——softmax 特征画出来同类散开;
  6. Triplet Loss 把距离写进损失但依赖挑样本;Center Loss 拉向类中心但类多爆内存;
  7. ArcFace 的核心转化:W 与特征归一化后「距离」变「角度」,给目标类角度加余量 m;MegaFace 91%→98%;
  8. 基准成绩要问「多少人、什么姿态、阈值怎么定的」——LFW 的 100% 不等于车站里的 100%。

10. 原文地图

主题原书章原文位置
场景挑战第9章 人脸检测与识别text/10-ch09.txt:7(搜「尺度多变」)
广义流程与生物特征第9章 人脸检测与识别text/10-ch09.txt:1(搜「人脸检测」) · text/10-ch09.txt:28(搜「生物特征识别」)
目标检测难题第9章 人脸检测与识别text/10-ch09.txt:56(搜「最具有挑战性」)
R-CNN 与 50%第9章 人脸检测与识别text/10-ch09.txt:84(搜「50%」)
Fast/Faster 演进第9章 人脸检测与识别text/10-ch09.txt:96(搜「ROI」) · text/10-ch09.txt:105(搜「RPN」)
对齐与相似变换第9章 人脸检测与识别text/10-ch09.txt:125(搜「相似变换」)
MTCNN 三网接力第9章 人脸检测与识别text/10-ch09.txt:136(搜「乔宇」) · text/10-ch09.txt:144(搜「金字塔」) · text/10-ch09.txt:154(搜「5个特征点」)
渐进过滤的理由第9章 人脸检测与识别text/10-ch09.txt:160(搜「最慢」) · text/10-ch09.txt:161(搜「降低了计算时间」)
softmax 不适合识别第9章 人脸检测与识别text/10-ch09.txt:183(搜「类内紧凑和类间分离」)
MNIST 二维散点第9章 人脸检测与识别text/10-ch09.txt:187(搜「2维向量」)
softmax 卡 0.9第9章 人脸检测与识别text/10-ch09.txt:200(搜「0.9」)
Triplet Loss第9章 人脸检测与识别text/10-ch09.txt:207(搜「度量学习」) · text/10-ch09.txt:216(搜「数据集比较大」)
Center Loss第9章 人脸检测与识别text/10-ch09.txt:223(搜「类别中心」) · text/10-ch09.txt:230(搜「λLc」) · text/10-ch09.txt:237(搜「10000」)
ArcFace 折成角度第9章 人脸检测与识别text/10-ch09.txt:238(搜「ArcFace」) · text/10-ch09.txt:249(搜「超球面」)
MegaFace 91→98第9章 人脸检测与识别text/10-ch09.txt:254(搜「91%」) · text/10-ch09.txt:254(搜「98%」)
ArcFace 代码 s=30 m=0.5第9章 人脸检测与识别text/10-ch09.txt:289(搜「30.0」)
谱系收束到 ArcFace第9章 人脸检测与识别text/10-ch09.txt:357(搜「FaceNet」) · text/10-ch09.txt:373(搜「ArcFace可以看做」)
实战:检测与过滤第9章 人脸检测与识别text/10-ch09.txt:414(搜「2.69」) · text/10-ch09.txt:430(搜「min_num」)
实战:识别结果第9章 人脸检测与识别text/10-ch09.txt:478(搜「resnet18」) · text/10-ch09.txt:502(搜「0.11820279」)

Footnotes

  1. 出处:「第9章 人脸检测与识别」第 7 段(text/10-ch09.txt:7,搜「尺度多变」)。

  2. 出处:「第9章 人脸检测与识别」第 28 段(text/10-ch09.txt:28,搜「生物特征识别」)与第 35 段(text/10-ch09.txt:35,搜「自然性」)。

  3. 出处:「第9章 人脸检测与识别」第 56 段(text/10-ch09.txt:56,搜「最具有挑战性」)。

  4. 出处:「第9章 人脸检测与识别」第 84 段(text/10-ch09.txt:84,搜「50%」)与第 88 段(text/10-ch09.txt:88,搜「数据驱动特征」)。

  5. 出处:「第9章 人脸检测与识别」第 105 段(text/10-ch09.txt:105,搜「RPN」)。

  6. 出处:「第9章 人脸检测与识别」第 125 段(text/10-ch09.txt:125,搜「相似变换」)。

  7. 出处:「第9章 人脸检测与识别」第 136 段(text/10-ch09.txt:136,搜「乔宇」)。

  8. 出处:「第9章 人脸检测与识别」第 144 段(text/10-ch09.txt:144,搜「金字塔」)、第 147 段(text/10-ch09.txt:147,搜「候选窗口」)、第 152 段(text/10-ch09.txt:152,搜「部分假窗口」)与第 154 段(text/10-ch09.txt:154,搜「5个特征点」)。

  9. 出处:「第9章 人脸检测与识别」第 160 段(text/10-ch09.txt:160,搜「最慢」)与第 161 段(text/10-ch09.txt:161,搜「降低了计算时间」)。

  10. 出处:「第9章 人脸检测与识别」第 170 段(text/10-ch09.txt:170,搜「转换为一个向量」)。

  11. 出处:「第9章 人脸检测与识别」第 183 段(text/10-ch09.txt:183,搜「类内紧凑和类间分离」)。

  12. 出处:「第9章 人脸检测与识别」第 187 段(text/10-ch09.txt:187,搜「2维向量」)与第 190 段(text/10-ch09.txt:190,搜「距离可能较大」)。

  13. 出处:「第9章 人脸检测与识别」第 200 段(text/10-ch09.txt:200,搜「0.9」)。

  14. 出处:「第9章 人脸检测与识别」第 207 段(text/10-ch09.txt:207,搜「度量学习」)与第 211 段(text/10-ch09.txt:211,搜「每次从训练数据中取出」)。

  15. 出处:「第9章 人脸检测与识别」第 216 段(text/10-ch09.txt:216,搜「数据集比较大」)。

  16. 出处:「第9章 人脸检测与识别」第 223 段(text/10-ch09.txt:223,搜「类别中心」)与第 230 段(text/10-ch09.txt:230,搜「λLc」)。

  17. 出处:「第9章 人脸检测与识别」第 237 段(text/10-ch09.txt:237,搜「10000」)。

  18. 出处:「第9章 人脸检测与识别」第 327 段(text/10-ch09.txt:327,搜「one_hot」)。

  19. 出处:「第9章 人脸检测与识别」第 357 段(text/10-ch09.txt:357,搜「FaceNet」)与第 373 段(text/10-ch09.txt:373,搜「ArcFace可以看做」)。

  20. 出处:「第9章 人脸检测与识别」第 414 段(text/10-ch09.txt:414,搜「2.69」)、第 430 段(text/10-ch09.txt:430,搜「min_num」)、第 478 段(text/10-ch09.txt:478,搜「resnet18」)与第 502 段(text/10-ch09.txt:502,搜「0.11820279」)。