我們前面分享了PCA,Fisher Face,LBPH三種傳統的人臉識別算法,Dlib人臉檢測算法。今天我們開始分享一下MTCNN算法,這個算法可以將人臉檢測和特徵點檢測結合起來,並且MTCNN的級聯結構對現代的人臉識別也產生了很大的影響。上篇為大家介紹MTCNN的算法原理和訓練技巧,下篇為大家解析MTCNN算法的代碼和進行demo演示。論文地址為:https://arxiv.org/ftp/arxiv/papers/1604/1604.02878.pdf
原理MTCNN是英文Multi-task Cascaded Convolutional Neural Networks的縮寫,翻譯過來就是多任務級聯卷積神經網絡。該網絡在誕生之初是表現最優的,雖然當前表現已經不是最優的了,但該網絡具有很大的意義,第一次將人臉檢測和人臉特徵點定位結合起來,而得到的人臉特徵點又可以實現人臉校正。該算法由3個階段組成:
第二階段,通過更複雜一點的CNN精煉候選窗體,丟棄大量的重疊窗體。第三階段,使用更強大的CNN,實現候選窗體去留,同時回歸5個面部關鍵點。第一階段是使用一種叫做PNet(Proposal Network)的卷積神經網絡,獲得候選窗體和邊界回歸向量。同時,候選窗體根據邊界框進行校準。然後利用非極大值抑制去除重疊窗體。第二階段是使用R-Net(Refine Network)卷積神經網絡進行操作,將經過P-Net確定的包含候選窗體的圖片在R-Net中訓練,最後使用全連接網絡進行分類。利用邊界框向量微調候選窗體,最後還是利用非極大值抑制算法去除重疊窗體。第三階段,使用Onet(Output Network)卷積神經網絡進行操作,該網絡比R-Net多一層卷積層,功能與R-Net類似,只是在去除重疊候選窗口的同時標定5個人臉關鍵點位置。
MTCNN網絡在經過3個卷積網絡處理之前,先進行了多尺度變換,將一幅人臉圖像縮放為不同尺寸的圖片,這樣就構成了圖像金字塔。然後這些不同尺度的圖像作為3個階段的輸入數據進行訓練,這樣可以令MTCNN檢測到不同尺寸的人臉。MTCNN三個階段所做的事情如下圖:
網絡結構在這裡插入圖片描述訓練MTCNN的訓練是一件極為複雜的事,沒有真正訓練過的人是難以體會其中的困難的。我也只能從理論方面說明一下,有興趣可以去參與訓練一下。
損失函數MTCNN特徵描述子主要包括3個部分,分別是人臉-非人臉二分類器、邊界框回歸、以及人臉特徵點。下面分別介紹這3個部分的損失函數。首先要對人臉進行分類,即判斷該區域是否包含人臉的二分類器。人臉分類的交叉熵損失函數如下:其中,
其中,
和邊界回歸過程相同,人臉關鍵點定位也是一個回歸問題,該步驟的損失函數仍然是計算經過預測的關鍵點位置和實際位置之間的偏差,距離度量使用歐氏距離。關鍵點定位過程中的損失函數如下:
其中,
最終MTCNN要優化的損失為:其中,N為訓練樣本數量,
在訓練過程中,為了取得較好的結果,MTCNN作者每次只反向傳播前70%樣本的梯度,用以保證傳遞的都是有效數據。
訓練MTCNN復現論文結果論文中作者主要使用了Wider_face 和CelebA資料庫,其中Wider_face主要用於檢測任務的訓練,CelebA主要用於關鍵點的訓練。訓練集分為四種:負樣本,正樣本 ,部分樣本,關鍵點樣本. 三個樣本的比例為3: 1: 1: 2。Wider_face包含人臉邊框標註數據,大概人臉在20萬,CelebA包含邊框標註數據和5個點的關鍵點信息.對於三個網絡,提取過程類似,但是圖像尺寸不同。
訓練包含三大任務,即是:
正負樣本,部分樣本,關鍵點樣本提取1.從Wider_face隨機選出邊框,然後和標註數據計算IOU,如果大於0.65,則為正樣本,大於0.4小於0.65為部分樣本,小於0.4為負樣本。2.計算邊框偏移.對於邊框,(x1,y1)為左上角坐標,(x2,y2)為右下角坐標,新剪裁的邊框坐標為(xn1,yn1),(xn2,yn2),width,height。則offset_x1 = (x1 - xn1)/width,同上,計算另三個點的坐標偏移。3.對於正樣本,部分樣本均有邊框信息,而對於負樣本不需要邊框信息。4. 從celeba中提取關鍵點樣本,可以根據標註的邊框,在滿足正樣本的要求下,隨機裁剪出圖片,然後調整關鍵點的坐標。
Caffe訓練Loss修改由於訓練過程中需要同時計算3個loss,但是對於不同的任務,每個任務需要的loss不同。所有在整理數據中,對於每個圖片進行了15個label的標註信息。具體如下:1.第1列:為正負樣本標誌,1正樣本,0負樣本,2部分樣本,3關鍵點信息2.第2-5列:為邊框偏移,為float類型,對於無邊框信息的數據,全部置為-13.第6-15列:為關鍵點偏移,為floagt類型,對於無邊框信息的數據,全部置為-1
所以,我們需要修改softmax_loss_layer.cpp增加判斷,只對於1,0計算loss值,修改euclidean_loss_layer.cpp 增加判斷,對於置為-1的不進行loss計算。
困難樣本選擇論文中作者對於人臉分類任務,採用了在線困難樣本選擇,實現過程如下:修改softmax_loss_layer.cpp,根據計算出的loss值,進行排序,只對於70%的值較低的數據。
MTCNN訓練自己的數據這一部分已經有非常多的開原始碼了,可以白用,推薦下面這一個:https://github.com/dlunion/mtcnn。訓練非常方便,並且有一個配套的純c++版本的mtcnn-light,非常利於進行源碼理解,我的MTCNN算法詳解下篇即會深入到該代碼中進行源碼解析。
後記雖然MTCNN當時取得了人臉檢測的最高SOAT結果,但是技術的發展是非常快的,當前在人臉檢測權威數據集WIDER FACE上,MTCNN的前列已經有比較多了。WIDER FACE的官方地址如下:http://mmlab.ie.cuhk.edu.hk/projects/WIDERFace/WiderFace_Results.html,我們從下面的PR曲線看出這點。(這三張圖像分別代表針對不同難度的樣本的PR曲線)可以看出DFS算法真的很棒啊,有機會看一看?