3個CNN,勝過1個諸葛亮

作者簡介

CW,廣東深圳人,畢業於中山大學(SYSU)數據科學與電腦學院,畢業後就業於騰訊電腦系統有限公司技術工程與事業群(TEG)從事Devops工作,期間在AI LAB實習過,實操過道路交通元素與醫療病例影像分割、影片實時人臉檢測與表情識別、OCR等項目。

目前也有在一些自媒體平台上參與外包項目的研發工作,項目專註於CV領域(傳統影像處理與深度學習方向均有)。

前言

MTCNN(Multi-Task Cascaded Convolutional Networks)是2016年提出的,如其名,演算法採用了級聯CNN的結構實現了多任務學習——人臉檢測 和 人臉對齊,最終能夠預測出人臉框(bounding box)和關鍵點(landmarks)的位置。

MTCNN在 FDDB、WIDER FACE 和 AFLW 數據集上均取得了當時(2016年4月)最好的效果,而且速度也快(在當時來說),被廣泛用於人臉識別流程中的前端部分。

總地來說,MTCNN的效果主要得益於以下幾點:

  1. 級聯的CNN架構是一個coarse-to-fine(由粗到細)的過程;

  2. 在訓練過程中使用了在線困難樣本挖掘(OHEM,Online Hard Example Mining)的策略;

  3. 加入了人臉對齊的聯合學習(Joint Face Alignment Learning)

下面,請諸位客官進入MTCNN的世界裡進行參觀。

MTCNN的「宣傳海報」


一網路結構

MTCNN由3個網路組成,共同構成級聯的CNN架構。這3個網路依次為 P-Net、R-Net 和 O-Net,前者的輸出會作為後者的輸入。

P-Net(Proposal Network)

P-Net

顧名思義,這個網路主要用於輸出包含的人臉候選區域。輸出包含3部分:分類結果(二分類),代表是否人臉、檢測到的人臉框(bbox)位置 以及 定位到的關鍵點(landmarks)位置。

需要注意的是,這裡回歸輸出的bbox和landmarks並非是坐標值本身,而是歸一化的offset,具體在後文會講解,這裡先埋個坑~

另外,P-Net是一個FCN(Fully Convolutonal Network),輸出的是一個map,channel為2+4+10=16,2對應二分類的score,4對應bbox左上角和右下角橫縱坐標的offset,而10則對應5個關鍵點(左、右眼、鼻、左、右嘴角)橫縱坐標的offset,後續R-Net和O-Net的輸出意義也與此相同。

或許你會疑惑,為何P-Net要設計成FCN呢?從上圖可以看到,輸入影像的size是12×12,最終輸出的size變為1×1,完全沒有必要嘛~其實仔細看下本文前言里展示的那幅圖的最上面部分,應該就知道答案了。

R-Net(Refine Network)

R-Net

R-Net不再是FCN,最後使用全連接層,相比於P-Net,其輸入size和每層的通道數也比較大,可以認為,其擬合的結果會更精確,主要作用是對P-Net的結果進行校正,消除其中的誤判(FP,False-Positive)。

O-Net(Output Network)

O-Net

O-Net的結構與P-Net較為類似,只不過輸入size、寬度以及深度都更大,因此可使最終輸出結果更加精確。

從上述展示的結構中我們可以feel到,P-Net->R-Net->O-Net 是一個coarse-to-fine的過程。


推理過程

推理過程的pipeline依次是:對輸入影像進行處理生成影像金字塔 -> 輸入到P-Net -> 對P-Net的輸出進行後處理 -> 輸入到R-Nnet -> 對R-Net的輸出進行後處理 -> 輸入到O-Net -> 對O-Net的輸出進行後處理得到最終預測結果。

另外,推理時P-Net和R-Net可以不必輸出landmarks分量,因為此時預測的人臉框位置還不準,根據offset計算出對應的landmarks位置沒有太大意義,而且也沒有必要,最終的輸出還是取決於O-Net。

影像金字塔

由上一節展示的P-Net網路架構可知,其是在單尺度(12×12 size)上做訓練的,為了檢測到不同尺寸的人臉,所以在推理時需要先生成影像金字塔,而P-Net為何設計成FCN的原因也在於此。

首先,設置一個想要檢測的最小人臉尺寸min_size,比如20×20,其次,設定一個縮放因子fator,通常為0.707。

然後,將影像的最短邊乘以 12 / 20,進行一次縮放,接著不斷對前面縮放的尺寸乘以fator進行縮放,比如最短邊初始為s,接下來就會縮放得到:s x 12 / 20、s x 12/ 20 x factor、s x 12 / 20 x factor ^2、…,直至s不大於12時停止。

記錄下以上縮放過程中(最短邊還大於12時)的各個scale:12 / 20、12 / 20 x factor、12 / 20 x factor^2、…,最後依次按照每個scale對影像採用雙線性插值的方式進行縮放從而得到影像金字塔。提問時間到!為何縮放因子是0.707?

這個數字不覺得有點眼熟嗎?是的,它約等於

,那麼這又代表什麼呢?通常,按照我們凡夫俗子的思維,縮放係數都習慣於取0.5,如果邊長都縮放0.5倍的話,那麼矩形框面積就縮小了1/4,跨度未免有點大,可能會漏掉許多要檢測的人臉。要知道,按照P-Net的意思,每個尺度對應的就是一張人臉。於是我們可以讓面積縮放1/2,減小這之間的跨度,相應地,邊長的縮放係數就為

十萬個為什麼系列之第二個靈魂拷問——min_size和factor對推理過程會產生什麼樣的影響?

由小學數學知識可知,min_size越大、fator越小,影像最短邊就越快縮放到接近12,從而生成影像金字塔的耗時就越短,同時各尺度的跨度也更大。因此,加大min_size、減小factor能加速影像金字塔的生成,但同時也更易造成漏檢。

好了,不問了,真要問十萬個估計我的手要碼到殘廢了..剩下的諸位自行yy。

由上述可知,影像金字塔的缺點就是慢!慢在需要不斷resize生成各個尺寸的影像,還慢在這些影像是一張張輸入到P-Net中進行檢測的(每張的輸出結果代表一張人臉候選區域),相當於做了多次推斷過程,你說可不可怕..

P-Net獲取人臉候選區域

將影像金字塔中每個尺寸的影像依次輸入到P-Net,對於每個尺度的影像都會對應輸出一個map,輸出map的每點都會有分類score和回歸的bbox offset。先保留置信度較高的一批位置點,然後將每點還原出對應的人臉區域,接著用NMS剔除重複的區域,得到所有尺寸影像保留下來的結果後,再用一次NMS進行去重(CW做過實驗,不同scale下輸出的影像之間NMS沒有效果,說明不同scale下沒有重複的,也符合不同scale檢測不同尺寸人臉的意思),最後使用回歸得到的offset對人臉候選區域進行校正得到bbox位置。十萬個為什麼系列再次上線——如何還原出輸出map每點對應的人臉區域?

根據P-Net的結構設計可知,輸出feature map的一點實際對應的是輸入中12×12的區域,而P-Net中有一個池化層進行了2倍的下取樣(對卷積層帶來的尺寸損失不計),於是對於輸出feature map的一點(x, y),我們可以這麼做來進行還原:

i). 先還原出其在輸入影像的位置:(x2, y2);

ii). 將其作為人臉區域的左上角,對應地,右下角為:(x2 + 12, y2 + 12);

iii). 由於在生成影像金字塔時進行了縮放,因此還要除以當時縮放的scale:(x1 = x2 / scale, y1 = y2 / scale)、(x2 = (x2 + 12) / scale, y2 = (y2 + 12) / scale)

以上(x1, y1, x2, y2)便是還原出來在原圖上對應的人臉區域。

你們應該還沒有吃飽,繼續問——如何用回歸得到的offset計算出人臉bbox位置?

x1_true = x1 + tx1*w

y1_true = y1 + ty1*h

x2_true = x2 + tx2*w

y2_true = y2 + ty2*h

使用以上公式就能計算得到結果,其中x*_true和y*_true代表人臉bbox的位置,tx*、ty*代表回歸得到的offset,w和h就是人臉區域(x1, y1, x2, y2)的寬和高。

至於為什麼能這麼計算,這是由訓練前製作label的時候決定的,在下一節講訓練過程時會說明,這裡先hold著。

P-Net輸出的bbox不夠精準,僅作為包含人臉的候選區域,接下來交由R-Net進行校正。

R-Net基於P-Net的結果進一步校正

R-Net並不是直接將P-Net的輸出結果拿來用,他還是個細心boy,先對這些輸出「做了一番洗剪吹」,成為這條街上最靚的仔後再拿來用,處理過程如下:

i). 為了儘可能涵蓋到人臉,將P-Net輸出的候選區域都按其各自的長邊resize方形;

ii). 檢查這些區域的坐標是否在原圖範圍內,在原圖內的像素值設置為原圖對應位置的像素值,其它則置為0;

iii). 將以上處理得到的圖片區域使用雙線性插值resize到24×24大小

處理完後,所有輸入都是24×24大小,網路輸出的後處理與P-Net類似,先篩選置信度較高的一批結果,然後用NMS剔除重複的,最後使用offset計算出bbox位置。此處使用offset計算時用到的(x1,y1,x2,y2)就是P-Net輸出的bbox。

又要問了——為何不直接對原圖有效範圍內的區域進行resize?

可以這麼想,如果有效範圍內的區域剛好正是人臉區域,絲毫不差,那麼resize後必定會有像素損失,從而丟失細節。

O-Net檢測出人臉和關鍵點位置

看到R-Net是個細心boy,O-Net當然也是很自覺地對R-Net的輸出結果做了處理,處理方式與R-Net類似,只不過最終resize到的大小是48×48。

由於O-Net會輸出landmarks的offset,因此還需要計算出landmarks的位置:

x_true = x_box + tx*w

y_true = y_box + ty*h

(x_true, y_true)代表一個關鍵點的位置,tx、ty代表對應的offset,(x_box, y_box)代表R-Net輸出bbox的左上角位置,w、h代表bbox的寬、高。至於bbox位置的計算、後處理等這些也都和之前的類似,這裡不再闡述了。

哦,另外,在此處NMS計算IoU時,分母可以不取並集,而是取當前置信度最高的bbox和其餘bbox面積的較小者,這樣分母會變大,從而導致IoU計算結果偏高,相當於變向降低NMS閥值,對重複檢測的要求更為苛刻。

三訓練過程

MTCNN的三個網路是依次分別訓練的,先訓練P-Net,待其訓練好後,將其檢測結果用於R-Net的訓練數據,然後對R-Net進行訓練。同樣地,R-Net訓練完後,將其檢測結果用於O-Net的訓練數據,最後訓練O-Net。

數據樣本分類

MTCNN是集成了人臉檢測和人臉對齊的多任務架構,通常使用兩個數據集來訓練,其中一個訓練人臉檢測,另一個訓練人臉對齊(這部分其實也能訓練人臉檢測)。在處理訓練數據時,會對影像進行隨機裁剪,具體方法後文會講解,這裡再埋個坑。可以將訓練樣本分為4類:

i). Positive:裁剪後圖片與人臉標註框 IoU >= 0.65,類別標籤為1;

ii). Part:裁剪後圖片與人臉標註框 IoU

[0.4, 0.65),類別標籤為-1;

iii). Negative:裁剪後圖片與人臉標註框 IoU < 0.3,類別標籤為0;

iv). Landmarks:來自訓練人臉對齊的數據集,類別標籤為-2

使用Positive和Negative樣本計算分類損失,使用Positive和Part樣本計算bbox回歸損失,而僅使用Landmarks樣本計算landmarks回歸損失。

十萬個為什麼時間到——為何只使用Postive和Negative計算分類損失?

應該是考慮到這些正負樣本與標註框的IoU差別明顯,區分度大,使模型更易收斂。

標籤製作

填坑時間到!之前埋下的2個坑會在這裡填上,打起精神咯!

P-Net、R-Net和O-Net的標籤處理過程有些許差別,下面依次介紹。

P-Net

負樣本Negative

  1. 對影像進行隨機裁剪,裁剪後為方形,邊長s=(12, min(H, W) ),H、W分別為影像的高和寬。將影像左上角向右下方進行移動,移動後橫、縱坐標分別為

(0, W – s)、

(0, H – s),於是裁剪後影像右下角坐標為(x2=x1 + s, y2=y1 + s)。

  1. 計算裁剪後影像與原圖中所有標註框的IoU,若最大IoU<0.3,則將這張裁剪後的影像作為負樣本Negative,resize至12×12大小,對應的類別標籤記為0,保存下來待訓練時用。

  2. 重複1、2直至生成了50個負樣本影像。

  3. 對影像中的每個標註框重複5次隨機裁剪,也是用於生成負樣本。裁剪後邊長s與1中的相同,移動bbox的左上角(x1, y1),移動後(nx1=x1 + delta_x, ny1=y1 + delta_y),其中delta_x

[max(-s, -x1), w),delta_y

[max(-s, -y1), h),也就是對標註框左上角隨機進行上下左右移動,w、h分別bbox的寬和高。對應地,bbox右下角坐標變為(nx2=nx1 + s, ny2=ny1 + s)。若右下角坐標超出原圖範圍,則捨棄該裁剪圖片,進行下一次裁剪。

正樣本Positive和Part

  1. 緊接著4,在一個標註框隨機裁剪5次後,再重複隨機裁剪20次,用於生成正樣本Postive和Part。裁剪後影像邊長s

即bbox短邊的0.8倍至長邊的1.25倍。對bbox的中心點隨機進行左右上下移動,移動範圍delta_

[-0.2w, 0.2w),delta_

[-0.2h, 0.2h),於是移動後中心點坐標為

,

相應地,左上角和右下角坐標為

(

)若右下角坐標超出原圖範圍,則捨棄此次裁剪的結果,繼續執行下一次隨機裁剪。

  1. 若裁剪後影像與該bbox的IoU>=0.65,則作為正樣本Positive,resize到12×12大小,類別標籤記為1;否則若IoU>=0.4,則作為Part,同樣也resize成12×12,類別標籤記為-1;

  2. 對於Postive和Part樣本,計算bbox左上角和右下角的offset標籤:

其中,(x, y)為標註框左上角/右下角的橫、縱坐標,(nx, ny)為裁剪圖片的左上角/右下角坐標,s為其邊長。也就是標註框兩個角相對於裁剪圖片對應兩角的歸一化位移。最後將Postive和Part樣本對應的裁剪影像、類別標籤、offset標籤保存下來待訓練時用。

關鍵點樣本Landmarks

  1. Landmarks樣本在另一個數據集中單獨處理,每張圖片是一個單獨的人臉,對每張圖重複10次隨機裁剪,裁剪方式與生成Positive和Part樣本時相同,若裁剪後影像右下角坐標不在原圖範圍內,或者裁剪後影像與標註框IoU<0.65,則捨棄此次裁剪結果,進行下一次隨機裁剪。

  2. 計算bbox和landmarks的offset標籤,其中bbox的計算方式與Postive以及Part的相同,這裡不再闡述,而landmarks的如下:

其中,(x, y)為標註的關鍵點坐標,

為裁剪後影像的左上角坐標,s為裁剪後影像的邊長,即標註的關鍵點相對於裁剪影像左上角的歸一化位移。

R-Net

在R-Net的標籤製作前需要使用訓練好的P-Net的數據集進行檢測,後續的數據處理過程與P-Net類似,下面進行介紹。

  1. 使用訓練好的P-Net對數據集的圖片進行檢測,將原圖、標註框以及檢測出的bbox位置對應保存下來。

  2. 將原圖、標註以及圖中檢測出的bbox依次取出,對每個bbox依次處理,若尺寸小於20(min_size,代表想要檢測的最小人臉size)或者 坐標不在原圖範圍內,則捨棄該檢測出的bbox,繼續處理下一個bbox;否則,將bbox對應的區域從原圖中裁出並resize到24×24備用。

負樣本Negative

  1. 計算bbox與所有標註框的IoU,若最大IoU<0.3且當前生成的負樣本數量小於60個,則將裁剪出的影像作為負樣本,類別標籤記為0,保存下來待訓練時用。

正樣本Positive和Part

  1. 否則,若最大IoU>=0.65或0.4<=最大IoU<0.65,則對應地將裁剪出的影像記為正樣本Positive或Part,類別標籤記為1或-1。同時,取出最大IoU對應的標註框,用於計算offset,計算方式與P-Net中提到的相同,最後將裁剪出的影像、類別標籤、offset標籤保存好待訓練時使用。

O-Net

在製作O-Net的數據標籤前需要依次使用訓練好的P-Net和R-Net對數據集做檢測,然後將R-Net預測的bbox和對應的原圖以及標註保存下來供O-Net使用。

標籤製作過程和R-Net的幾乎相同,只不過沒有最小負樣本數量的限制(P-Net有50個、R-Net有60個)。另外,若landmarks數據集的標註框最長邊小於40或坐標不在原圖範圍內,則捨棄這個樣本。

Loss函數

loss由三部分組成:分類損失、bbox回歸損失、landmarks回歸損失。

每個網路的loss都由這3種loss加權而成,其中分類損失使用交叉熵損失,回歸損失均使用L2距離損失。

上式中,j代表不同的任務(分類、bbox回歸、landmarks回歸),

即不同任務對應的loss權重,對於P-Net和R-Net,它們的分類loss、bbox回歸loss、landmarks回歸loss的權重比為1:0.5:0.5,而O-Net中為1:0.5:1。

是第i個樣本在任務j中是否需要貢獻loss,需要則為1,否則為0。例如,對於Negative樣本,它在回歸任務中這個β值就為0。

OHEM(Online Hard Example Mining)

在線困難樣本挖掘的策略僅在計算分類loss時使用。直白來說,就是挑選損失最大的前70%作為困難樣本,在反向傳播時僅使用這70%困難樣本產生的損失。作者在paper中的實驗表明,這樣做在FDDB數據集上能帶來1.5個點的性能提升。

四總結

最後,總結下MTCNN的整個pipeline:

首先,對待檢測圖片生成影像金字塔,輸入P-Net,得到輸出,通過分類置信度和NMS篩選出人臉候選區域;

然後,基於這些候選區域去原圖crop出對應的影像,輸入R-Net,得到輸出後同樣是使用分類置信度和NMS,過濾掉false-positive,得到更精準的一批候選;

最後,基於得到的這批候選去原圖crop出對應的影像,輸入O-Net,輸出最終預測的bbox和landmark位置。