MTCNN應用詳解

MTCNN應用詳解

很多人應該是讀過MTCNN這篇文章的,所以這裏沒有簡單的流程介紹,如果只是簡單地算法介紹,百度上已經有很多了。

開始之前,先確認以下幾個問題

  • 爲什麼要做圖像金字塔,圖像金字塔在MTCNN中帶來的優勢和劣勢分別是什麼?
  • MTCNN爲什麼可以接受任意尺寸的圖片輸入?
  • 檢測最小人臉尺寸ninSize爲什麼是12?縮放因子factor爲什麼是0.709?
  • 什麼是邊框迴歸?
  • 爲什麼ONet可以同時輸出人臉位置和5個關鍵點位置?

現在從頭開始將MTCNN梳理一遍

1、讀取一張圖片,按照設置的檢測最小人臉參數minSize,來進行圖像金字塔操作

    float scale = 12.f / minSize;
    float minWH = std::min(imgHeight, imgWidth) *scale;
    std::vector<float> scales;
    while (minWH >= 12) {
        scales.push_back(scale);
        minWH *= factor;
        scale *= factor;
    }

scale的個數就是圖像金字塔的層數,從這裏看出minSize越大,圖像金字塔的層數越少

然後將金字塔中不同層的圖像分別輸入PNet網絡

for (int i = 0; i < scales.size(); i++)
{
    int ws = (int)std::ceil(imgWidth*scales[i]);
    int hs = (int)std::ceil(imgHeight*scales[i]);
    cv::resize(img, resized, cv::Size(ws, hs));
		warpPNetInput(img);
    PNet->Forward();
}

從上面可以看出,圖像金字塔有多少層就進行了多少次的PNet的forward運算。

很明顯,上面的問題已經有了答案

  • 圖像金字塔的優勢就是可以輸入多尺寸的圖像到CNN,提升CNN對多尺度目標的檢出能力;劣勢也很明顯,直接增加了運算次數,也就成比例地增加了推理時間。在通用目標檢測領域,影響召回率的兩大難題:1,目標尺寸過小;2,目標尺度變化過大。工業界應用中提升召回率常用兩種方法

  • 圖像金字塔,在輸入端進行多尺度變化,以適應多尺度檢測,但是其缺點明顯就是耗時

  • 特徵金字塔,在特徵圖上進行多尺度,淺層特徵負責檢出大目標,深層特徵負責檢出小目標,例如SSD,FPN

  • MTCNN可以接受任意尺寸的圖像輸入。因爲PNet是一個全卷積網絡,沒有全連接層,常見的卷積,池化,非線性激活層都是可以接受任意尺度的輸入運算的,全連接是需要事先定義好連接數量所以不能接受任意尺度運算,當然也有例外,例如Kaiming He的SPP。MTCNN文章截圖如下圖1所示,但是實際開源的代碼中跟這個結構略有不同,PNet沒有進行landmark的迴歸,只有兩個分支,一個用來分類人臉得到confidence值,另外一個用來回歸box位置
    PNet
    PNet-out

  • 圖像金字塔生成的圖像尺寸要和12儘量接近,因爲訓練PNet的數據是歸一化到12大小的。在文章中說明了,圖像金字塔低層的面積是上一層的0.5,也就是面積的scale是0.5,對應的邊長的scale就是sqrt(0.5),即0.709。minSize和factor兩個參數直接影響到算法性能和推理時間

2、PNet輸出的位置迴歸

按照PNet的網絡結構,可以得到這樣一個結論,12x12的矩陣可以得到1個prob(就是上面softmax的輸出也就是人臉的概率)和一個4值向量(上面conv4-2輸出,人臉的迴歸值)。

由於PNet不限制輸入尺寸,所以輸入的尺寸肯定有很多比12大的。由於卷積池化都是在輸入特徵圖上“滑動”,所以現在把PNet看成是一個判別器,判斷每一個12x12區域是否有人臉輸出1個confidence和4個regression值,這樣PNet就被看成一個12x12的“滑動核”。

假設一個輸入圖片中,某一個12x12塊,左上角爲(x,y)。其對應輸出特徵圖大小應該是(x/2-5,y/2-5),所以根據輸出信息反推回去,就可以知道哪一個12x12的塊出現了人臉。假設PNet輸出的特徵圖中某一個點檢測出現人臉,反推回去原圖上的座標,例如輸出特徵圖中(x,y)點反推回原圖左上角(x1,y1)右下角(x2,y2)。

x1 = x * 2;y1 = y * 2;x2 = x1 + 12;y2 = y1 + 12,由於PNet做了圖像金字塔,所以還需要還原Scale倍。

上面的內容只說明了某一個12*12區域是否存在人臉,但是具體位置還不知道,所以需要另外的4個迴歸值。

4個迴歸值分別代表的是中心點橫座標,縱座標,寬,高 四個值的偏移量。這樣有了座標值,有了偏移量,就可以得到原圖上精確座標。

bbox迴歸,個人覺得也是一個非常重要的知識點,所以準備單獨用一篇文章的篇幅來總結,這裏先不寫。

3、landmark檢測

在Onet輸出的時候,有三個分支,如下圖,prob1是人臉confidence,conv6-2是人臉位置迴歸值,conv6-3是landmark迴歸值。

prob1是softmax的分類輸出,conv6-2和conv6-3都是全連接層輸出。在訓練階段,人臉使用交叉熵loss,landmark使用均方差損失,兩者加權求和作爲整個網絡loss訓練

4、mtcnn推理時間分析

經過觀察mtcnn的三個網絡結構,結構非常簡單,計算參數量也非常少,主要耗時都存在於金字塔的生成過程中。三個階段的耗時大約爲:Pnet佔75%,RNet佔15%,ONet佔10%。

但是通過工具計算單個網絡參數量之後發現,PNet由於其最簡單的網絡結構,其參數量只有6.83K個,但是爲啥耗時最多呢?原因是圖像金字塔操作都在CPU上完成,然後forword操作再gpu上完成,這樣導致數據不停地在顯存和內存中拷貝,數據IO時間消耗已經不能被忽略了,並且在CPU上進行的resize操作時間消耗也不能被忽略。

  • MTCNN的推理優化主要從PNet下手,找到金字塔層數和待檢測目標大小之間的平衡
  • 控制顯存和內存之間IO交互的時間,例如將resize在gpu上實現。

5、mtcnn拓展

mtcnn的思想爲工業界開闊了很大的視野,有很多使用mtcnn做的其他應用。例如mtcnn做行人檢測,mtcnn做人頭檢測,mtcnn做人臉跟蹤等等。

  • github上zuoqing大佬對mtcnn做了魔改,並且有一系列的拓展,強烈推薦看一下。
  • 人臉跟蹤。第一幀採用完整mtcnn檢測,檢測到人臉之後,在第二幀中利用上一幀人臉位置稍微外擴一點,然後在此小圖上直接使用ONet推理,直接就可以輸出人臉位置。這樣對於單人臉檢測跟蹤效果不錯。

MTCNN是2016年的CVPR文章,再過一個月,馬上就2020年了。時間總是在推着技術向前發展,我們也要跟上時代的步伐。雖然現在很多方法已經把MTCNN甩在後面了,但是我們不能忘記mtcnn對人臉檢測算法做出的貢獻。


關注公衆號: 卡本特
內容持續輸出

發佈了62 篇原創文章 · 獲贊 61 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章