注意:这里说的人脸对齐和传统的Face Alignment差别较大,传统的Face Alignment是指从人脸图片上检测人脸关键点,然后用仿射变换将人脸归正。而本文说的人脸对齐只是指仿射变换的部分。
参考代码https://github.com/foamliu/InsightFace-PyTorch/blob/master/align_faces.py
人脸对齐可分为如下步骤:
由检测到的人脸关键点和目标关键点位置得到仿射变换的变换矩阵
当人脸大小为(96/w,112/h)时,目标关键点的位置为(该出处不明)
REFERENCE_FACIAL_POINTS = [
[30.29459953, 51.69630051],
[65.53179932, 51.50139999],
[48.02519989, 71.73660278],
[33.54930115, 92.3655014],
[62.72990036, 92.20410156]
]
DEFAULT_CROP_SIZE = (96, 112)
然后需要根据需要的人脸shape和内外padding的大小改变关键点的位置。 具体说明可以查看代码及其中说明align_faces.py
得到变换矩阵共有三种方法:
函数的输入src_pts和dst_pts均为ndarray:(5,2) 输出变换矩阵为ndarray:(3,2)
np.linalg是numpy中的线性代数库, np.linalg.lstsq(a, b, rcond='warn')lstsq 是 LeaST SQuare (最小二乘)的意思,即求使得|| ax - b ||最小的x的值。函数返回一个包含四个值的元组:
通过三个点即可获得仿射变换矩阵
tfm = cv2.getAffineTransform(src_pts[0:3], ref_pts[0:3])
相似变换的矩阵如下:
s∗cosθs∗sinθ0s∗(−sinθ)cosθ0txty1
相比仿射变换,相似变换的自由度较小,左上角2×2矩阵为旋转部分,tx和ty为平移因子,它有4个自由度,即旋转,x方向平移,y方向平移和缩放因子s。
本部分内容参考《计算机图形学导论》第五章:几何变换
三维空间的变换矩阵是一个3*3的矩阵W, $P2 = W.dot(P1)$ , P1的坐标可以写作 $(x,y,1)$,其中第三维表示bias。
将 $(x,y)$ 平移到 $(x+t_x,y+t_y)$ , 变换矩阵为:
[xy1]∗10tx01ty001=[x+txy+ty1] 将 $(x,y)$ 缩放到 $(xs_x,ys_y)$ , 变换矩阵为:
[xy1]∗sx000sy0001=[x∗sxy∗sy1] 将 $(x,y)$ 顺时针旋转 $\theta$ 角度
[xy1]∗cosθ−sinθ0sinθcosθ0001=[x∗cosθ−y∗sinθx∗sinθ+y∗cosθ1] [xy1]∗100a10001=[xa∗x+y1] 仿射变换公有6个自由度,两个旋转因子,两个缩放因子,x和y的平移因子,共6个。
以 $(t_x,t_y)$ 为中心旋转 $\theta$ 度,先平移 $(-x,-y)$,然后以原点为中心旋转,最后再平移 $(x,y)$
[xy1]∗10−tx01−ty001∗cosθ−sinθ0sinθcosθ0001∗10tx01ty001 crop_img = cv2.warpAffine(src_img, tfm, (crop_size[0], crop_size[1]))
其中tfm是shape=(2,3)的变换矩阵