用MTCNN挑戰最簡單的Face Alignment

Rice Yang
7 min readFeb 21, 2021

--

Face Alignment by MTCNN

Face Alignment是許多人臉應用中必要的前處理,目的是減少輸入影像的旋轉(Rotation)、平移(Translation)、縮放(Scale)變化而造成的精度損失。

通常上Git找到的Face Alignment code都是落落長,抄起來很不舒服。於是我用Python+OpenCV+MTCNN來挑戰最簡單實作的Face Alignment,總共只有31行,希望大家抄得開心。完整的Code在這裡:

簡述 MTCNN

MTCNN出自論文Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks,這篇論文的主要貢獻包含三個:

  1. 建立了同時可以檢測框(Bounding Box)跟特徵點(Landmarks)的多任務Cascaded CNN框架
  2. 使用Online Hard Sample Mining(線上難樣本挖掘)來提升訓練效果
  3. Benchmark實驗

因為這篇論文出的有點久了,我就不描述裡面的原理。時至今日,我覺得裡面必須要理解的概念是多任務學習(Multi-Task Learning)的核心概念與損失函數設計。

多任務學習的核心概念

MTCNN使用3個網路同時學習人臉框與特徵點

多任務學習在今天來看已經不是特別新奇。MTCNN在2016年證實把人臉檢測+特徵點檢測共用一個骨幹網路(Backbone CNN)一起做學習會得到效果加成。2017的Mask-RCNN也證明了Object Detection/Keypoint/Instance Mask三個任務共用骨幹網路也會得到增益。

多任務學習也呼應了監督學習的一個明顯的現象:標注越多越好;如果一個Backbone可以同時使用多個任務的Labeld Data來訓練,相當於加入了更多的監督資訊,可以強迫Backbone去注意更有代表性的特徵,各種任務彼此也可以互相補足。

舉個簡單的例子,單獨學習人臉檢測的時候,Backbone學到的特徵完全不一定是臉,也可能是無關的特徵,比方「肩膀上面的圓球」。但是當人臉檢測+特徵點檢測一起訓練的時候,間接地會把「人臉必定包含眼睛、鼻子、嘴巴」這個隱式規則也學習進去,進而提升人臉檢測的效果。

多任務學習的損失函數

多任務學習的好處之一就是可以融合多個資料集一起訓練,當每個資料集的標註格式都相同時,多任務學習的損失函數(Loss function)可以用加權下面方程式表示:

公式1: Vanilla Multitask Learning Loss

其中 𝛼 代表的是loss的權重(0到1),是固定不變的常數,i 代表不同的任務。以MTCNN為例,i有3個:detection, bounding box, landmarks,分別對應的 𝛼 分別是1、0.5、0.5。

MTCNN將訓練集分成四類,除了Landmark Faces之外,其他的類別都沒有Landmarks標注

MTCNN中,因為他混用了三種公開資料集(FDDB, WIDER FACE, AFLW),而且只有AFLW的情況是有特徵點標註的,所以不能直接套用公式1。這時候就要用另一個參數去「遮住」Label:

公式2:MTCNN的Loss。𝛼 代表固定權重、𝛽 代表Label Mask(在原論文被稱為”sample type indicator”),L 代表任務損失函數,i 代表樣本、j 代表任務

𝛽 是非0即1的二元參數。當Missing Label存在樣本 i 時,𝛽i = 0,略過這次的損失計算;反之如果Label存在,𝛽i = 1。

想要更進一步理解每個任務的Loss設計以及模型架構的同學,可以參考這篇:

人臉對齊 Face Alignment

使用MTCNN取得特徵點

MTCNN的Python library封裝得很好,只需要宣告一個detector就可以用了。下面再稍微解說一下code要注意的部分

  • MTCNN 的參數 steps_threshold

用來設置MTCNN裡面三個網路的threshold,分別是P-Net, R-Net, O-Net。這裡不設置就會採用預設值,我這邊設為0是確保一定有臉被偵測到。

  • 一般我們的圖片儲存都是BGR格式的,注意輸入MTCNN前要轉成RGB
  • detect_faces的回傳值是list of dictionary。格式如下:
[
{
'box': [277, 90, 48, 63],
'keypoints':
{
'nose': (303, 131),
'mouth_right': (313, 141),
'right_eye': (314, 114),
'left_eye': (291, 117),
'mouth_left': (296, 143)
},
'confidence': 0.99851983785629272
}
]
  • line 6的語法可以直接取出confidence最大的人臉dictionary。

影像處理

Face Alignment的4個步驟

上圖圖示了Face Alignment的四個步驟,前面三個都可以用影像的矩陣運算來完成:

因為都是矩陣運算,所以可以把所有矩陣都融合為一個仿射矩陣(Affine Matrix):

在OpenCV裡面,可以呼叫cv2.warpAffine來實現全部步驟。

其中scale參數可以用來控制輸出圖片的大小,設置為1的話圖片寬度就是左右眼的寬度。可以根據你之後的用途來調整scale的大小,當然也可以修改成tuple來輸出非正方形的圖片。

--

--

Rice Yang
Rice Yang

Written by Rice Yang

A Tech Manager in AI. Experienced in NVIDIA, Alibaba, Pony.ai. Familiar with Deep Learning, Computer Vision, Software Engineering, Autonomous Driving

No responses yet