這篇blog是我剛入目標檢測方向,導師發給我的文獻導讀,深入淺出總結了object detection two-stage流派Faster R-CNN的發展史,讀起來非常有趣。我一直想翻譯這篇博客,在知乎上發現已經有人做過了,而且翻譯的很好,我將其轉載到這里。
這里貼一下我對R-CNN、Fast R-CNN、Faster R-CNN、Mask R-CNN的對比,看完下面的文章后不妨回來看看我的總結,有問題的地方歡迎討論。
以下內容轉載自CNN圖像分割簡史:從R-CNN到Mask R-CNN(譯)
原文A Brief History of CNNs in Image Segmentation: From R-CNN to Mask R-CNN
在Athelas中可以看到,卷積神經網絡(Convolutional Neural Networks,CNNs)應用非常廣泛,不僅僅是用於解決分類問題。這篇博文主要介紹如何利用CNNs進行圖像實例分割。
自從Alex Krizhevsky, Geoff Hinton, and Ilya Sutskever贏得ImageNet 2012,CNNs開始成為圖像分類任務中的黃金准則。事實上,CNNs之后不斷提升ImageNet比賽中的圖像分類精度,甚至超過了人類的水准。
雖然分類結果非常驚人,但圖像分類任務相對於人類視覺理解任務的復雜性和多樣性來說是非常簡單的。
圖像分類任務中的一張圖像一般只關注一個目標,從而預測圖像是什么(如圖2所示)。但是我們在觀察周圍世界時要完成非常復雜的事情。
現實世界中的復雜場景一般存在相互重疊的目標和不同背景,我們在觀察時不僅能夠分辨不同的目標,而且可以識別不同目標的邊界、差異以及他們之間的(空間)關系。
CNNs是否可以幫助我們完成如此復雜的任務?也就是說,給定一張復雜的圖像,我們是否可以利用CNNs識別圖像中的不同目標以及他們的邊界呢?Ross Girshick和他的同事近幾年的研究表明,答案是當然可以!
本文目標
本博文涵蓋目標檢測和分割中所用主要技術背后的知識,以及這些技術的演化過程,特別是R-CNN(Regional CNN)(CNNs最初應用於檢測和分割問題的方法)及其派生Fast R-CNN和Faster R-CNN,最后我們會講述Facebook Research最新提出的Mask R-CNN,對這類目標檢測問題擴展到像素級圖像分割。本博文中引用的論文如下:
- R-CNN: [1311.2524] Rich feature hierarchies for accurate object detection and semantic segmentation
- Fast R-CNN: [1504.08083] Fast R-CNN
- Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks
- Mask R-CNN: [1703.06870] Mask R-CNN
2014: R-CNN - An Early Application of CNNs to Object Detection
受Toronto大學Hinton實驗室研究成果的啟發,UC Berkeley大學Jitendra Malik教授的團隊提出當今看來不可避免的問題:
Krizhevsky等的研究成果如何才能擴展到目標檢測?
目標檢測任務從圖像中找到不同的物體並對其進行分類(如圖5所示)。Ross Girshick (a name we’ll see again)、Jeff Donahue和Trevor Darrel團隊發現目標檢測問題可以借助於Krizhevsky的成果並在PASCAL VOC數據集(ImageNet挑戰中的目標檢測數據集)中進行測試,文中提到:
這篇論文首次表明了在PASCAL VOC數據集上的目標檢測任務中,CNNs能夠獲得比傳統特征(如HOG特征等)好很多的性能。
接下來我們一起理解一下Regions CNNs(R-CNN)工作的架構。
理解R-CNN
R-CNN的目標是從圖像中正確識別出主要的物體(采用bounding box進行標注):
- 輸入:圖像
- 輸出:圖像中每個物體的Bounding Box+標簽
如何找出這些bounding box呢?R-CNN采用我們直覺上認為的方式:給出一堆圖像可能的box,然后判斷這些box是否和物體相關。
R-CNN采用Selective Search的方法給出region proposals。從高層理解,Selective Search通過不同尺寸的窗口在圖像中進行滑動(如圖6所示),對於每個尺寸方法采用紋理、顏色或亮度對鄰近的像素進行聚合,從而識別物體。
獲得region proposals集合之后,R-CNN將這些區域變換為標准的方形尺寸,並采用AlexNet的修改版本判斷其是否是有效region(如圖7所示)。
在CNN的最后一層,R-CNN增加了一個簡單的分類器Support Vector Machine(SVM),用於判斷區域是否是物體,以及物體的類別。
精化Bounding Box
現在已經找到Box中的物體,接下來是否可以tighten bounding box(進一步調整物體邊界,使其更貼近物體周圍),從而獲取物體的真實范圍呢?當然,這也是R-CNN的最后一步,R-CNN對region proposals進行簡單的線性回歸,從而生成tighten之后的Bounding Box做為最終結果。回歸模型的輸入和輸出如下:
- 輸入:物體在圖像中的sub-regions
- 輸出:sub-resions中物體的新Bounding Box坐標
總結一下,R-CNN的步驟如下:
- 生成regions proposals集合作為Bounding Box;
- 采用預訓練的AlexNet+SVM判斷Bouding Box對應圖像的物體類型;
- 對已分類物體的Bounding Box進行線性回歸,輸出Box對應的tighter bounding boxes。
2015: Fast R-CNN - Speeding up and Simplifying R-CNN
R-CNN效果非常好,但是效率太低了,主要的原因:
- 對於每張圖像的每個region proposal都需要進行前向的CNN(AlexNet)計算,大概每張圖像需要2000次的前向CNN;
- 方法中的三個模型是分別訓練的——CNN提取圖像特征、分類器預測類別、回歸模型tighten bounding box的邊界,這也導致流程不易訓練。
2015年,R-CNN的作者Ross Girshick解決了上述兩個問題,並提出了Fast R-CNN的算法,接下來介紹一下Fast R-CNN。
RoI(Region of Interest)Pooling
Ross Girshick發現,每張圖像的proposed regions總是朴素重疊的,從而導致重復的CNN前向計算(可能達到2000次)。他的想法非常簡單——為什么不每張圖像計算一次CNN,為2000個proposed regions找到一種計算共享的方法?
Fast R-CNN采用RoIPool(Region of Interest Pooling)解決此問題。作為方法的核心,RoIPool分享整幅圖像的CNN前向計算給不同的regions。如圖8所示,特別注意每個區域的CNN特征如何從CNN的特征圖像中選擇對應區域特征的。接下來對每個區域的特征進行pool操作(一般采用max pooling)。這樣的話我們只需要一次原始圖像的CNN前向計算,而非R-CNN中的2000次!
Combine All Models into One Network
Fast R-CNN第二個想法是將CNN、分類和邊界線性回歸的訓練融合到一個單獨的網絡中。不像R-CNN中的特征提取(CNN)、分類(SVM)和邊界tighten(回歸)分別采用三個不同的模型,Fast R-CNN采用一個單獨網絡實現上述三個步驟。
圖9展示了具體融合的過程,Fast R-CNN采用softmax layer取代了SVM分類器作為CNN網絡的類別輸出層,方法增加了一個平行於softmax layer的linear regression layer作為網絡的邊界坐標輸出層,這樣所有的輸出需要來自於同一個網絡!整個模型的輸入和輸出如下:
- 輸入:圖像以及region proposals
- 輸出:每個區域對應物體的類別以及物體的tighter bounding boxes
2016: Faster R-CNN - Speeding Up Region Proposal
經過上述的改進,Fast R-CNN仍然存在一個瓶頸——region proposer。目標檢測方法的第一步就是生成用於測試的潛在bouding box集合或者regions of interest,Fast R-CNN中采用的Selective Search速度非常慢,這也是限制整個算法效率的主要瓶頸。
2015年中,微軟的研究團隊(Shaoqing Ren, Kaiming He, Ross Girshick, and Jian Sun)提出一種Faster R-CNN的方法,使得region proposal非常高效。
Faster R-CNN的想法來源於region proposals的特征計算依賴於圖像的特征(采用CNN一次性計算整幅圖像的特征),那么為何不重用這些相同的CNN特征進行region proposals,從而取代單獨的selective search算法呢?
實際上,這就是Faster R-CNN方法的核心。圖10描述了單獨CNN完成region proposals和分類的過程。這樣只需要訓練一個CNN,region proposals的計算基本可以忽略。文中描述:
我們發現用於檢測區域的卷積特征圖(類似於Fast R-CNN)同樣可以用來生成region proposals(因此使得region proposals變得毫不費力)。
模型的輸入和輸出如下:
- 輸入:圖像(不需要region proposals)
- 輸出:圖像中物體的類別及其對應的bounding box坐標
How the Regions are Generated
接下來討論一下Faster R-CNN如何從CNN特征圖中生成region proposals。Faster R-CNN在CNN特征的上層增加了一個全卷積網絡,即Region Proposal Network.
Region Proposal Network在CNN特征圖上進行滑動窗口操作,然后每個窗口,輸出k個潛在的bounding box和分數,k個boxes如何選擇和表達呢?
直覺上,我們會認為圖像中的物體應該符合一定的大小和長寬比,比如行人的形狀更可能是長方形的box。類似地,我們一般也不會關注那些非常窄的boxes。據此,我們構建了k個這樣的common aspect ratios,並稱作anchor boxes。每個anchor box輸出bounding box和對應的位置圖像的分數。
考慮這些anchor boxes,Region Proposal Network的輸入和輸出如下:
- 輸入:CNN特征圖
- 輸出:每個anchor對應的bounding box以及分數(表示bounding box中對應圖像部分是物體的可能性)
然后,將Region Proposal Network中輸出的目標可能bounding box輸入到Fast R-CNN,並生成類別和tightened bounding box。
2017: Mask R-CNN - Extending Faster R-CNN for Pixel Level Segmentation
到這里我們已經可以利用CNN特征快速定位圖像中不同目標的bounding boxes了,那么接下來是否可以繼續延伸一下,提取像素級的目標實例而不是僅僅給出bounding boxes呢?這就是經典的圖像分割問題,Kaiming He和他的團隊(包括Girshick)在Facebook AI實驗室中采用的架構,Mask R-CNN。
類似於Fast R-CNN和Faster R-CNN,Mask R-CNN的潛在創意來源也是很直接的,鑒於Faster R-CNN在目標檢測中的效果,我們是否可以將其擴展到像素級的圖像分割中呢?
Maks R-CNN在Faster R-CNN的基礎上增加一個分支,用於輸出一個二值掩膜(Binary Mask),判斷給定像素是否屬於物體。上述分支(圖14中的白色部分)就是一個置於CNN特征圖上層的全卷積神經網絡。模型的輸入和輸出如下:
- 輸入:CNN特征圖
- 輸出:指示像素是否屬於物體的二值矩陣
但是Mask R-CNN的作者做了少量調整使得整個網絡輸出期望的結果。
RoiAlign - Realigning RoIPool to be More Accurate
直接采用Faster R-CNN的架構執行Mask R-CNN可能導致RoIPool選擇區域的特征圖與原始圖像區域存在少量的偏離。由於圖像分割需要像素級的標記,因此這樣自然會導致精度下降。
Mask R-CNN采用RoIAlign的方法對RoIPool進行調整使其更精確對齊。
假設有一幅128*128大小的圖像,對應的特征圖大小為25*25,如果要將原始圖像左上角15*15大小的像素映射到特征圖中(如圖16所示),如何從特征圖中選擇像素呢?顯然原始圖像中每個像素對應特征圖中的25*128個像素,要選擇原始圖像中的15個像素,需要選擇15*25/128=2.93個像素。
在RoIPool中,我們會四舍五入選擇3個像素,從而會導致微小的偏移。在RoIAlign中,我們要避免這樣的近似。取而代之的是采用bilinear interpolation獲取精確的對應值,即選擇像素2.93,從而能夠避免RoIPool導致的偏移。
生成這些mask之后,Mask R-CNN結合Faster R-CNN中生成的分類和bounding box,生成精確的分割結果。
源碼
如果你想自己試驗一下這些算法,這里是相關的源碼庫:
Faster R-CNN
- Caffe: rbgirshick/py-faster-rcnn
- PyTorch: longcw/faster_rcnn_pytorch
- MatLab: ShaoqingRen/faster_rcnn
Mask R-CNN
- PyTorch: felixgwu/mask_rcnn_pytorch
- TensorFlow: CharlesShang/FastMaskRCNN