如何用SphereFace+纯Python刷分Megaface

如何用SphereFace+纯Python刷分Megaface

SphereFace 是今年CVPR的一篇论文, 理论直观优美, 作者的代码和调参功力也足够深厚. 已经有部分人用项目中release的20层模型在Megaface-challenge-1中刷到了70%以上的准确率. 例如Normface作者.

但目前看到的代码都是基于matlab的, 对python党来说不够友好. 下面说一下如何用纯python复现.

其中最关键的一步是如何用python做人脸对齐. 参照这里的方法, 对齐大概分以下几步:

  1. 用MTCNN检测图片的人脸区域和关键点(5个,眼睛*2,鼻子,嘴角*2)
  2. 如果有多个人脸区域, 计算这些人脸区域与数据源标定区域的IoU, 取最大的.
  3. 如果未检测到任何人脸区域, 两种方案:
    1. 对标定区域降低阈值强制检测人脸.
    2. 直接对图片取center crop.

MTCNN检测用Matlab或者python版本问题都不大. 重点是检测到关键点后如何对齐?

对齐在matlab中对应的函数是cp2tformimtransform. cp2tform获取两组坐标之间的2D变换参数. imtransform 利用参数转换图像并切割到固定大小.

先看一下例子, 以下是原图(取自facescrub, image_id:14680):

用MTCNN+matlab cp2tform+ imtransform 对齐后:

可以看到效果不错.

然后我们试几个python实现,


1. 全仿射变换:

src = np.array([                                                                                                                                                                     
 [30.2946, 51.6963],                                                                                                                                                                
 [65.5318, 51.5014],                                                                                                                                                                
 [48.0252, 71.7366],                                                                                                                                                                
 [33.5493, 92.3655],                                                                                                                                                                
 [62.7299, 92.2041] ], dtype=np.float32 )
dst = mtcnn_landmark.astype(np.float32)
M = cv2.estimateRigidTransform( dst.reshape(1,5,2), src.reshape(1,5,2), True)
warped = cv2.warpAffine(img,M,(shape[1],shape[0]), borderValue = 0.0)

效果如下,有点失真:



2. 再来带约束的仿射变换:

M = cv2.estimateRigidTransform( dst.reshape(1,5,2), src.reshape(1,5,2), False)
warped = cv2.warpAffine(img,M,(shape[1],shape[0]), borderValue = 0.0)

效果如下,好一些, 也能用了, 但是和matlab的版本还是不一样(旋转角度有区别). 因为作者提供的模型是用matlab的对齐算法训练的, 所以我们必须和他保持一致.



3.继续, 相似变换, 用skimage的similarity transform:

from skimage import transform as trans

tform = trans.SimilarityTransform()                                                                                                                                                  
tform.estimate(dst, src)
M = tform.params[0:2,:]
warped = cv2.warpAffine(img,M,(shape[1],shape[0]), borderValue = 0.0)

效果, 基本和matlab一致, 除了缩放比例有一些细微的差别, 但应该不影响测试了.


对齐后的测试方法就比较简单了, 用对齐后的人脸及其翻转镜像送入caffe模型得到向量相加, 并归一化做为特征.


测试结果(Megaface challenge-1 Top-1 Accuracy):

  1. 全仿射变换: 44%.
  2. 带约束的仿射变换: 47%.
  3. skimage similarity transform: 69.5%.

检测及对齐部分还有提高空间.

ps: 如果训练时就用第一(?)或者第二种对齐方法的话, 可能最终准确率差不了多少.


下一步就是自己训练模型了.

发布于 2017-09-20