第 19 / 30 课。 前置:上一课。本篇的运行范围以实验说明和验证记录为准,构造样例不代表真实任务精度或板端性能。
人脸框只是流程的开始
人脸检测输出框;关键点模型给出眼、鼻、嘴等位置;对齐把这些位置映射到特征模型约定的模板;特征模型才产生身份表示。RetinaFace 等模型可以联合输出框和关键点,但具体解码仍须遵守其实现。
对齐模板取决于识别模型训练方式,不能在任意两套模型间随意交换。本课五点坐标为教学构造,不是某个权重的官方模板,也不读取真实人脸。
相似变换保留什么
二维相似变换包含旋转、统一缩放和平移,通常有四个自由度。它比一般六参数仿射变换限制更强,不会独立拉伸横纵方向。三维大侧脸投影带来的变化不能全部靠这个二维模型消除。
关键点必须顺序一致:左眼、右眼、鼻、左嘴角、右嘴角中的“左”要按模型定义统一。眼睛交换会让估计产生不合理旋转,不能只检查矩阵非空。
几何实验
脚本先把模板点通过已知变换移动,作为模拟检测点,然后估计从检测点回模板的矩阵。检查所有点的回投影误差,再用同一矩阵变换构造图片。输入与输出图像会发生重采样,像素不能要求逐位可逆。
真实识别还需处理裁剪边界、填充颜色、RGB/BGR、归一化与低质量拒绝。这些改变即使不报错,也可能改变相似度分布。
练习与答案
给一个关键点加 20 像素偏差,比较普通最小二乘与鲁棒估计;删掉一半关键点后,说明为什么不能照常认为结果可靠。
交付关键点顺序、模板尺寸和误差门限。几何误差小仅说明点符合该变换,不能证明检测正确,更不能证明身份正确;活体检测也属于另外的任务。
配套实验与运行记录
实验:人脸处理流程:检测、关键点与对齐
查看完整代码:main.py
"""用五点几何实验验证相似变换与裁剪,建立人脸识别前的输入契约。"""
import cv2
import numpy as np
def main():
template = np.array([[30, 35], [70, 35], [50, 55], [35, 75], [65, 75]], np.float32)
forward = cv2.getRotationMatrix2D((50, 50), 15, 1.2)
forward[:, 2] += np.array([8, 4])
observed = cv2.transform(template[None], forward)[0]
matrix, inliers = cv2.estimateAffinePartial2D(observed, template, method=cv2.LMEDS)
assert matrix is not None
aligned = cv2.transform(observed[None], matrix)[0]
error = float(np.linalg.norm(aligned - template, axis=1).max())
assert error < 1e-3
image = np.zeros((128, 128, 3), np.uint8)
for point in observed:
cv2.circle(image, tuple(np.round(point).astype(int)), 3, (0, 255, 0), -1)
crop = cv2.warpAffine(
image, matrix, (100, 100), flags=cv2.INTER_LINEAR, borderValue=(0, 0, 0)
)
assert crop.shape == (100, 100, 3)
print(
"max landmark error",
error,
"crop shape",
crop.shape,
"inliers",
int(inliers.sum()),
)
if __name__ == "__main__":
main()
在项目根目录执行;下载包解压后,在解压目录执行 python3 main.py。
cd 'content/posts/AI-深度学习/嵌入式视觉模型进阶/19-人脸处理流程/code' && python3 main.py
在本篇代码目录执行 python3 main.py。依赖安装、可选入口见包内 README.md;实际运行结果见 verification.md。下载包包含本课使用的辅助模块与样例。
参考与进一步阅读
原始论文或官方文档用于核对结构、接口和适用范围。本篇代码是围绕教学目标编写的最小实验;除明确注明的完整入口外,不视为对应论文模型的完整复现。