參考博文:https://www.cnblogs.com/xiaoboge/p/10502697.html
1.FCN概述
CNN做圖像分類甚至做目標檢測的效果已經被證明並廣泛應用,圖像語義分割本質上也可以認為是稠密的目標識別(需要預測每個像素點的類別)。
傳統的基於CNN的語義分割方法是:將像素周圍一個小區域(如25*25)作為CNN輸入,做訓練和預測。這樣做有3個問題:
- - 像素區域的大小如何確定
- - 存儲及計算量非常大
- - 像素區域的大小限制了感受野的大小,從而只能提取一些局部特征
為什么需要FCN?
我們分類使用的網絡通常會在最后連接幾層全連接層,它會將原來二維的矩陣(圖片)壓扁成一維的,從而丟失了空間信息,最后訓練輸出一個標量,這就是我們的分類標簽。而圖像語義分割的輸出需要是個分割圖,且不論尺寸大小,但是至少是二維的。所以,我們需要丟棄全連接層,換上全卷積層,而這就是全卷積網絡了。具體定義請參看論文:Fully Convolutional Networks for Semantic Segmentation。 Berkeley團隊提出 Fully Convolutional Networks(FCN)方法用於圖像語義分割,將圖像級別的分類擴展到像素級別的分類(圖1),獲得 CVPR2015 的 best paper。
圖1. FCN實現了 end-to-end 的圖像語義分割
文章《【總結】圖像語義分割之FCN和CRF》 認為,發展到現在,基於深度學習的圖像語義分割“通用框架已經確定”:前端 FCN(包含基於此的改進 SegNet、DeconvNet、DeepLab)+ 后端 CRF/MRF (條件隨機場/馬爾科夫隨機場)優化
圖2. 圖像語義分割通用框架(摘自這里)
FCN原理及網絡結構
一句話概括原理:FCN將傳統卷積網絡后面的全連接層換成了卷積層,這樣網絡輸出不再是類別而是 heatmap;同時為了解決因為卷積和池化對圖像尺寸的影響,提出使用上采樣的方式恢復。
核心思想
本文包含了當下CNN的三個思潮 :
- - 不含全連接層(fc)的全卷積(fully conv)網絡。可適應任意尺寸輸入。
- - 增大數據尺寸的反卷積(deconv)層。能夠輸出精細的結果。
- - 結合不同深度層結果的跳級(skip)結構。同時確保魯棒性和精確性。
網絡結構
網絡結構示意圖:
網絡結構詳圖。輸入可為任意尺寸圖像彩色圖像;輸出與輸入尺寸相同,深度為:20類目標+背景=21。
3. 全卷積網絡( Fully Convolutional Networks)
3.1 CNN 與 FCN
CNN
通常CNN網絡在卷積層之后會接上若干個全連接層, 將卷積層產生的特征圖(feature map)映射成一個固定長度的特征向量。以AlexNet為代表的經典CNN結構適合於圖像級的分類和回歸任務,因為它們最后都期望得到整個輸入圖像的一個數值描述(概率),比如AlexNet的ImageNet模型輸出一個1000維的向量表示輸入圖像屬於每一類的概率(softmax歸一化)。栗子:下圖中的貓, 輸入AlexNet, 得到一個長為1000的輸出向量, 表示輸入圖像屬於每一類的概率, 其中在“tabby cat”這一類統計概率最高。
FCN
FCN對圖像進行像素級的分類,從而解決了語義級別的圖像分割(semantic segmentation)問題。與經典的CNN在卷積層之后使用全連接層得到固定長度的特征向量進行分類(全聯接層+softmax輸出)不同,FCN可以接受任意尺寸的輸入圖像,采用反卷積層對最后一個卷積層的feature map進行上采樣, 使它恢復到輸入圖像相同的尺寸,從而可以對每個像素都產生了一個預測, 同時保留了原始輸入圖像中的空間信息, 最后在上采樣的特征圖上進行逐像素分類。
最后逐個像素計算softmax分類的損失, 相當於每一個像素對應一個訓練樣本。下圖是Longjon用於語義分割所采用的全卷積網絡(FCN)的結構示意圖:
簡單的來說,FCN與CNN的區域在把於CNN最后的全連接層換成卷積層,輸出的是一張已經Label好的圖片。
CNN與FCN的區別與聯系
其實,CNN的強大之處在於它的多層結構能自動學習特征,並且可以學習到多個層次的特征:
- 較淺的卷積層感知域較小,學習到一些局部區域的特征;
- 較深的卷積層具有較大的感知域,能夠學習到更加抽象一些的特征。
這些抽象特征對物體的大小、位置和方向等敏感性更低,從而有助於識別性能的提高。下圖CNN分類網絡的示意圖:
這些抽象的特征對分類很有幫助,可以很好地判斷出一幅圖像中包含什么類別的物體,但是因為丟失了一些物體的細節,不能很好地給出物體的具體輪廓、指出每個像素具體屬於哪個物體,因此做到精確的分割就很有難度。
基於CNN的分割方法與FCN的比較
傳統的基於CNN的分割方法:為了對一個像素分類,使用該像素周圍的一個圖像塊作為CNN的輸入用於訓練和預測。這種方法有幾個缺點:
- 一是存儲開銷很大。例如對每個像素使用的圖像塊的大小為15x15,然后不斷滑動窗口,每次滑動的窗口給CNN進行判別分類,因此則所需的存儲空間根據滑動窗口的次數和大小急劇上升。
- 二是計算效率低下。相鄰的像素塊基本上是重復的,針對每個像素塊逐個計算卷積,這種計算也有很大程度上的重復。
- 三是像素塊大小的限制了感知區域的大小。通常像素塊的大小比整幅圖像的大小小很多,只能提取一些局部的特征,從而導致分類的性能受到限制。
而全卷積網絡(FCN)則是從抽象的特征中恢復出每個像素所屬的類別。即從圖像級別的分類進一步延伸到像素級別的分類。
3.2 全連接層-->卷積層
全連接層與卷積層的相互轉化原理
全連接層和卷積層之間唯一的不同就是卷積層中的神經元只與輸入數據中的一個局部區域連接,並且在卷積列中的神經元共享參數。然而在兩類層中,神經元都是計算點積,所以它們的函數形式是一樣的。因此,將此兩者相互轉化是可能的:
- 對於任一個卷積層,都存在一個能實現和它一樣的前向傳播函數的全連接層。權重矩陣是一個巨大的矩陣,除了某些特定塊,其余部分都是零。而在其中大部分塊中,元素都是相等的。
相反,任何全連接層都可以被轉化為卷積層。比如,一個 全連接層轉化為卷積層:在兩種變換中,將全連接層轉化為卷積層在實際運用中更加有用。假設一個卷積神經網絡的輸入是
- 針對第一個連接區域是[7x7x512]的全連接層,令其濾波器尺寸為F=7,這樣輸出數據體就為[1x1x4096]了。
- 針對第二個全連接層,令其濾波器尺寸為F=1,這樣輸出數據體為[1x1x4096]。
- 對最后一個全連接層也做類似的,令其F=1,最終輸出為[1x1x1000]
實際操作中,每次這樣的變換都需要把全連接層的權重W重塑成卷積層的濾波器。那么這樣的轉化有什么作用呢?它在下面的情況下可以更高效:讓卷積網絡在一張更大的輸入圖片上滑動,得到多個輸出,這樣的轉化可以讓我們在單個向前傳播的過程中完成上述的操作。
實例:利用單個卷積層向前傳播網絡進行多位置評分
如果我們想讓224×224尺寸的浮窗,以步長為32在384×384的圖片上滑動,把每個經停的位置都帶入卷積網絡,最后得到6×6個位置的類別得分。上述的把全連接層轉換成卷積層的做法會更簡便。如果224×224的輸入圖片經過卷積層和下采樣層之后得到了[7x7x512]的數組,那么,384×384的大圖片直接經過同樣的卷積層和下采樣層之后會得到[12x12x512]的數組。然后再經過上面由3個全連接層轉化得到的3個卷積層,最終得到[6x6x1000]的輸出((12 – 7)/1 + 1 = 6)。這個結果正是浮窗在原圖經停的6×6個位置的得分!
note:面對384×384的圖像,讓(含全連接層)的初始卷積神經網絡以32像素的步長獨立對圖像中的224×224塊進行多次評價,其效果和使用把全連接層變換為卷積層后的卷積神經網絡進行一次前向傳播是一樣的。
Evaluating the original ConvNet (with FC layers) independently across 224x224 crops of the 384x384 image in strides of 32 pixels gives an identical result to forwarding the converted ConvNet one time.
將全連接層轉化為卷積層-->全卷積網絡
如下圖所示,FCN將傳統CNN中的全連接層轉化成卷積層,對應CNN網絡FCN把最后三層全連接層轉換成為三層卷積層。在傳統的CNN結構中,前5層是卷積層,第6層和第7層分別是一個長度為4096的一維向量,第8層是長度為1000的一維向量,分別對應1000個不同類別的概率。FCN將這3層表示為卷積層,卷積核的大小 (通道數,寬,高) 分別為 (4096,1,1)、(4096,1,1)、(1000,1,1)。看上去數字上並沒有什么差別,但是卷積跟全連接是不一樣的概念和計算過程,使用的是之前CNN已經訓練好的權值和偏置,但是不一樣的在於權值和偏置是有自己的范圍,屬於自己的一個卷積核。因此FCN網絡中所有的層都是卷積層,故稱為全卷積網絡。
CNN
下圖是一個全卷積層,與上圖不一樣的是圖像對應的大小下標,CNN中輸入的圖像大小是同意固定resize成 227x227 大小的圖像,第一層pooling后為55x55,第二層pooling后圖像大小為27x27,第五層pooling后的圖像大小為13*13。而FCN輸入的圖像是H*W大小,第一層pooling后變為原圖大小的1/4,第二層變為原圖大小的1/8,第五層變為原圖大小的1/16,第八層變為原圖大小的1/32(勘誤:其實真正代碼當中第一層是1/2,以此類推)。
FCN
經過多次卷積和pooling以后,得到的圖像越來越小,分辨率越來越低。其中圖像到
FCN圖像放大
最后的輸出是1000張heatmap經過upsampling變為原圖大小的圖片,為了對每個像素進行分類預測label成最后已經進行語義分割的圖像,這里有一個小trick,就是最后通過逐個像素地求其在1000張圖像該像素位置的最大數值描述(概率)作為該像素的分類。因此產生了一張已經分類好的圖片,如下圖右側有狗狗和貓貓的圖。
4. 上采樣upsample
這里僅提供架構介紹,詳見:
1).CNN中的卷積、反卷積與反池化:https://blog.csdn.net/qinghuaci666/article/details/80848642
2).圖像上采樣--雙線性插值:https://blog.csdn.net/qinghuaci666/article/details/80832259
上采樣,簡單來說就是pooling的逆過程,pooling采樣后數據數量減少,upsample采樣后數據數量增多。FCN作者在論文中討論了3種upsample方法,最后選用的是反卷積的方法(FCN作者稱其為后卷積)使圖像實現end to end,可以理解upsample就是使大小比原圖像小得多的特征圖變大,使其大小為原圖像大小。
具體來講,作者通過upsampling得到dense prediction,研究過3種方案:
(1)shift-and-stitch:
設原圖與FCN所得輸出圖之間的降采樣因子是f,那么對於原圖的每個f*f的區域(不重疊),“shift the input x pixels to the right and y pixels down for every (x,y) ,0 < x,y < f." 把這個f*f區域對應的output作為此時區域中心點像素對應的output,這樣就對每個f*f的區域得到了f^2個output,也就是每個像素都能對應一個output,所以成為了dense prediction。
詳見:語義分割--FCN中的Shift-and-stitch的詳解:https://blog.csdn.net/qinghuaci666/article/details/80833866
(2)filter rarefaction:
就是放大CNN網絡中的subsampling層的filter的尺寸,得到新的filter:
其中s是subsampling的滑動步長,這個新filter的滑動步長要設為1,這樣的話,subsampling就沒有縮小圖像尺寸,最后可以得到dense prediction。
以上兩種方法作者都沒有采用,主要是因為這兩種方法都是trade-off的,原因是:
對於第二種方法, 下采樣的功能被減弱,使得更細節的信息能被filter看到,但是receptive fileds會相對變小,可能會損失全局信息,而且會對卷積層引入更多運算,學習比較困難。
對於第一種方法,雖然receptive fileds沒有變小,但是由於原圖被划分成f*f的區域輸入網絡,使得filters無法感受更精細的信息(why?此部分正確性有待探究)。
(3)反卷積(deconvolutional)
upsampling的操作可以看成是反卷積(deconvolutional),卷積運算的參數和CNN的參數一樣是在訓練FCN模型的過程中通過bp算法學習得到。
反卷積(Deconvolution),當然關於這個名字不同框架不同,Caffe和Kera里叫Deconvolution,而tensorflow里叫conv_transpose。CS231n這門課中說,叫conv_transpose更為合適。
眾所諸知,普通的池化會縮小圖片的尺寸,比如VGG16 五次池化后圖片被縮小了32倍。為了得到和原圖等大的分割圖,我們需要上采樣/反卷積。
反卷積和卷積類似,都是相乘相加的運算。只不過后者是多對一,前者是一對多。而反卷積的前向和后向傳播,只用顛倒卷積的前后向傳播即可。所以無論優化還是后向傳播算法都是沒有問題。圖解如下:
5 跳躍結構
獲取heatmap
經過前面操作,基本就能實現語義分割了,但是直接將全卷積后的結果進行反卷積,得到的結果往往比較粗糙。
如上圖所示,對原圖像進行卷積conv1、pool1后原圖像縮小為1/2;之后對圖像進行第二次conv2、pool2后圖像縮小為1/4;接着繼續對圖像進行第三次卷積操作conv3、pool3縮小為原圖像的1/8,此時保留pool3的featureMap;接着繼續對圖像進行第四次卷積操作conv4、pool4,縮小為原圖像的1/16,保留pool4的featureMap;最后對圖像進行第五次卷積操作conv5、pool5,縮小為原圖像的1/32,然后把原來CNN操作中的全連接變成卷積操作conv6、conv7,圖像的featureMap數量改變但是圖像大小依然為原圖的1/32,此時圖像不再叫featureMap而是叫heatMap。
跳躍結構實現精細分割
現在我們有1/32尺寸的heatMap,1/16尺寸的featureMap和1/8尺寸的featureMap,1/32尺寸的heatMap進行upsampling操作之后,因為這樣的操作還原的圖片僅僅是conv5中的卷積核中的特征,限於精度問題不能夠很好地還原圖像當中的特征。因此在這里向前迭代,把conv4中的卷積核對上一次upsampling之后的圖進行反卷積補充細節(相當於一個插值過程),最后把conv3中的卷積核對剛才upsampling之后的圖像進行再次反卷積補充細節,最后就完成了整個圖像的還原。
具體來說,就是將不同池化層的結果進行上采樣,然后結合這些結果來優化輸出,分為FCN-32s,FCN-16s,FCN-8s三種,第一行對應FCN-32s,第二行對應FCN-16s,第三行對應FCN-8s。 具體結構如下:
圖中,image是原圖像,conv1,conv2..,conv5為卷積操作,pool1,pool2,..pool5為pool操作(pool就是使得圖片變為原圖的1/2),注意con6-7是最后的卷積層,最右邊一列是upsample后的end to end結果。必須說明的是圖中nx是指對應的特征圖上采樣n倍(即變大n倍),並不是指有n個特征圖,如32x upsampled 中的32x是圖像只變大32倍,不是有32個上采樣圖像,又如2x conv7是指conv7的特征圖變大2倍。
(1)FCN-32s過程
只需要留意第一行,網絡里面有5個pool,所以conv7的特征圖是原始圖像1/32,可以發現最左邊image的是32x32(假設以倍數計),同時我們知道在FCN中的卷積是不會改變圖像大小(或者只有少量像素的減少,特征圖大小基本不會小很多)。看到pool1是16x16,pool2是8x8,pool3是4x4,pool4是2x2,pool5是1x1,所以conv7對應特征圖大小為1x1,然后再經過32x upsampled prediction 圖片變回32x32。FCN作者在這里增加一個卷積層,卷積后的大小為輸入圖像的32(2^5)倍,我們簡單假設這個卷積核大小也為32,這樣就是需要通過反饋訓練32x32個權重變量即可讓圖像實現end to end,完成了一個32s的upsample。FCN作者稱做后卷積,他也提及可以稱為反卷積。事實上在源碼中卷積核的大小為64,同時沒有偏置bias。還有一點就是FCN論文中最后結果都是21×*,這里的21是指FCN使用的數據集分類,總共有21類。
(2)FCN-16s過程
現在我們把1,2兩行一起看,忽略32x upsampled prediction,說明FCN-16s的upsample過程。FCN作者在conv7先進行一個2x conv7操作,其實這里也只是增加1個卷積層,這次卷積后特征圖的大小為conv7的2倍,可以從pool5與2x conv7中看出來。此時2x conv7與pool4的大小是一樣的,FCN作者提出對pool4與2x conv7進行一個fuse操作(事實上就是將pool4與2x conv7相加,另一篇博客說是拼接,個人認為是拼接)。fuse結果進行16x upsampled prediction,與FCN-32s一樣,也是增加一個卷積層,卷積后的大小為輸入圖像的16(2^4)倍。我們知道pool4的大小是2x2,放大16倍,就是32x32,這樣最后圖像大小也變為原來的大小,至此完成了一個16s的upsample。現在我們可以知道,FCN中的upsample實際是通過增加卷積層,通過bp反饋的訓練方法訓練卷積層達到end to end,這時卷積層的作用可以看作是pool的逆過程。
(3)FCN-8s過程
這是我們看第1行與第3行,忽略32x upsampled prediction。conv7經過一次4x upsample,即使用一個卷積層,特征圖輸出大小為conv7的4倍,所得4x conv7的大小為4x4。然后pool4需要一次2x upsample,變成2x pool4,大小也為4x4。再把4x conv7,2x pool4與pool3進行fuse,得到求和后的特征圖。最后增加一個卷積層,使得輸出圖片大小為pool3的8倍,也就是8x upsampled prediction的過程,得到一個end to end的圖像。實驗表明FCN-8s優於FCN-16s,FCN-32s。
我們可以發現,如果繼續仿照FCN作者的步驟,我們可以對pool2,pool1實現同樣的方法,可以有FCN-4s,FCN-2s,最后得到end to end的輸出。這里作者給出了明確的結論,超過FCN-8s之后,結果並不能繼續優化。
結合上述的FCN的全卷積與upsample,在upsample最后加上softmax,就可以對不同類別的大小概率進行估計,實現end to end。最后輸出的圖是一個概率估計,對應像素點的值越大,其像素為該類的結果也越大。FCN的核心貢獻在於提出使用卷積層通過學習讓圖片實現end to end分類。
事實上,FCN有一些短處,例如使用了較淺層的特征,因為fuse操作會加上較上層的pool特征值,導致高維特征不能很好得以使用,同時也因為使用較上層的pool特征值,導致FCN對圖像大小變化有所要求,如果測試集的圖像遠大於或小於訓練集的圖像,FCN的效果就會變差。
6 訓練過程
訓練過程分為四個階段,也體現了作者的設計思路,值得研究。
第1階段
以經典的分類網絡為初始化。最后兩級是全連接(紅色),參數棄去不用。
第2階段
從特征小圖(16*16*4096)預測分割小圖(16*16*21),之后直接升采樣為大圖。
反卷積(橙色)的步長為32,這個網絡稱為FCN-32s。
這一階段使用單GPU訓練約需3天。
第3階段
升采樣分為兩次完成(橙色×2)。
在第二次升采樣前,把第4個pooling層(綠色)的預測結果(藍色)融合進來。使用跳級結構提升精確性。
第二次反卷積步長為16,這個網絡稱為FCN-16s。
這一階段使用單GPU訓練約需1天。
第4階段
升采樣分為三次完成(橙色×3)。
進一步融合了第3個pooling層的預測結果。
第三次反卷積步長為8,記為FCN-8s。
這一階段使用單GPU訓練約需1天。
較淺層的預測結果包含了更多細節信息。比較2,3,4階段可以看出,跳級結構利用淺層信息輔助逐步升采樣,有更精細的結果。
7 實驗驗證
相關參數:
minibatch:20張圖片
learning rate:0.001
初始化:
分類網絡之外的卷積層參數初始化為0。
反卷積參數初始化為bilinear插值。最后一層反卷積固定位bilinear插值不做學習。
實驗設計:
1,對比3種性能較好的幾種CNN:AlexNet, VGG16, GoogLeNet進行實驗,選擇VGG16
2,對比FCN-32s-fixed, FCN-32s, FCN-16s, FCN-8s,證明最好的dense prediction組合是8s
3,FCN-8s和state-of-the-art對比是最優的,R-CNN, SDS. FCN-16s
4,FCN-16s和現有的一些工作對比,是最優的
5,FCN-32s和FCN-16s在RGB-D和HHA的圖像數據集上,優於state-of-the-art
8 FCN的優點和不足
FCN 的優勢在於:
- 可以接受任意大小的輸入圖像(沒有全連接層)
- 更加高效,避免了使用鄰域帶來的重復計算和空間浪費的問題。
其不足也很突出:
- 得到的結果還不夠精細 。進行8倍上采樣雖然比32倍的效果好了很多,但是上采樣的結果還是比較模糊和平滑,對圖像中的細節不敏感。
-是對各個像素進行分類,沒有充分考慮像素與像素之間的關系。忽略了在通常的基於像素分類的分割方法中使用的空間規整(spatial regularization)步驟,缺乏空間一致性。
參考:
1.全卷積網絡(FCN)與圖像分割
https://blog.csdn.net/taigw/article/details/51401448
P:包括FCN擴展
2.FCN的理解
https://blog.csdn.net/qq_37274615/article/details/73251503
3.全卷積網絡 FCN 詳解
https://www.cnblogs.com/gujianhan/p/6030639.html
P:主要參考
4.關於FCN 論文中的 Shift-and-stitch 的詳盡解釋
https://www.jianshu.com/p/e534e2be5d7d
P:非常詳細
5.全卷積網絡 FCN 詳解
https://www.cnblogs.com/gujianhan/p/6030639.html
6.【圖像分割】Fully Convolutional Networks for Semantic Segmentation
https://blog.csdn.net/shenxiaolu1984/article/details/51348149
7.圖像語義分割(1)- FCN
https://blog.csdn.net/zizi7/article/details/77093447
8.FCN學習:Semantic Segmentation
https://zhuanlan.zhihu.com/p/22976342?utm_source=tuicool&utm_medium=referral
P:含代碼解析
9.Fully Convolutional Networks for semantic Segmentation(深度學習經典論文翻譯)
https://www.cnblogs.com/xuanxufeng/p/6249834.html
P:論文翻譯
10.FCN簡單梳理
https://blog.csdn.net/a8039974/article/details/78909987
11.【總結】圖像語義分割之FCN和CRF
https://zhuanlan.zhihu.com/p/22308032
P:含SegNet和DeepLab
12.卷積神經網絡CNN(3)—— FCN(Fully Convolutional Networks)要點解釋
https://blog.csdn.net/Fate_fjh/article/details/53446630
13.論文筆記《Fully Convolutional Networks for Semantic Segmentation》
https://blog.csdn.net/happyer88/article/details/47205839
P:dense prediction