在這里,先介紹幾個概念,也是圖像處理當中的最常見任務.
語義分割(semantic segmentation)
目標檢測(object detection)
目標識別(object recognition)
實例分割(instance segmentation)
首先需要了解一下什么是語義分割(semantic segmentation).
語義分割,簡單來說就是給定一張圖片,對圖片中的每一個像素點進行分類
比如說下圖,原始圖片是一張街景圖片,經過語義分割之后的圖片就是一個包含若干種顏色的圖片,其中每一種顏色都代表一類.
圖像語義分割是AI領域中一個重要的分支,是機器視覺技術中關于圖像理解的重要一環.
有幾個比較容易混淆的概念,分別是目標檢測(object detection),目標識別(object recognition),實例分割(instance segmentation),下面來一一介紹.
目標檢測,就是在一張圖片中找到并用box標注出所有的目標.
注意,目標檢測和目標識別不同之處在于,目標檢測只有兩類,目標和非目標.
如下圖所示:
目標識別,就是檢測和用box標注出所有的物體,并標注類別.
如下圖所示:
實例分割,對圖像中的每一個像素點進行分類,同種物體的不同實例也用不同的類標進行標注.
下圖展示了語義分割和實例分割之間的區別:
中間是實例分割,右圖是語義分割.
PASCAL VOC是一個正在進行的,目標檢測,目標識別,語義分割的挑戰.
這里是它的主頁,這里是leader board,很多公司和團隊都參與了這個挑戰,很多經典論文都是采用這個挑戰的數據集和結果發表論文,包括RCNN,FCN等.
關于這個挑戰,有興趣的同學可以讀一下這篇論文
FCN,全卷積神經網絡,是目前做語義分割的最常用的網絡.
Fully convolutional networks for semantic segmentation 是2015年發表在CVPR上的一片論文,提出了全卷積神經網絡的概念,差點得了當前的最佳論文,沒有評上的原因好像是有人質疑,全卷積并不是一個新的概念,因為全連接層也可以看作是卷積層,只不過卷積核是原圖大小而已.
在一般的卷積神經網絡中,一般結構都是前幾層是卷積層加池化,最后跟2-3層的全連接層,輸出分類結果,如下圖所示:
這個結構就是AlexNet的結構,用來進行ImageNet中的圖片分類,最后一層是一個輸出為1000*1向量的全連接層,因為一共有1000個類,向量中的每一維都代表了當前類的概率,其中tabby cat的概率是最大的.
而在全卷積神經網絡中,沒有了全連接層,取而代之的是卷積層,如下圖所示:
最后一層輸出的是1000個二維數組,其中每一個數組可以可視化成為一張圖像,圖中的每一個像素點的灰度值都是代表當前像素點屬于該類的概率,比如在這1000張圖像中,取出其中代表tabby cat的概率圖,顏色從藍到紅,代表當前點屬于該類的概率就越大.
可以看出FCN與CNN之間的區別就是把最后幾層的全連接層換成了卷積層,這樣做的好處就是能夠進行dense prediction.
從而可是實現FCN對圖像進行像素級的分類,從而解決了語義級別的圖像分割(semantic segmentation)問題。與經典的CNN在卷積層之后使用全連接層得到固定長度的特征向量進行分類(全聯接層+softmax輸出)不同,FCN可以接受任意尺寸的輸入圖像,采用反卷積層對最后一個卷積層的feature map進行上采樣, 使它恢復到輸入圖像相同的尺寸,從而可以對每個像素都產生了一個預測, 同時保留了原始輸入圖像中的空間信息, 最后在上采樣的特征圖上進行逐像素分類。
在進行語義分割的時候,需要解決的一個重要問題就是,如何把定位和分類這兩個問題結合起來,畢竟語義分割就是進行逐個像素點的分類,就是把where和what兩個問題結合在了一起進行解決.
在前面幾層卷積層,分辨率比較高,像素點的定位比較準確,后面幾層卷積層,分辨率比較低,像素點的分類比較準確,所以為了更加準確的分割,需要把前面高分辨率的特征和后面的低分辨率特征結合起來.
如上圖所示,對原圖像進行卷積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,此時進行32倍的上采樣可以得到原圖大小,這個時候得到的結果就是叫做FCN-32s.
這個時候可以看出,FCN-32s結果明顯非常平滑,不精細. 針對這個問題,作者采用了combining what and where的方法,具體來說,就是在FCN-32s的基礎上進行fine tuning,把pool4層和conv7的2倍上采樣結果相加之后進行一個16倍的上采樣,得到的結果是FCN-16s.
之后在FCN-16s的基礎上進行fine tuning,把pool3層和2倍上采樣的pool4層和4倍上采樣的conv7層加起來,進行一個8倍的上采樣,得到的結果就是FCN-8s.
可以看出結果明顯是FCN-8s好于16s,好于32s的.
上圖從左至右分別是原圖,FCN-32s,FCN-16s,FCN-8s.
FCN的優點,能夠end-to-end, pixels-to-pixels,而且相比于傳統的基于cnn做分割的網絡更加高效,因為避免了由于使用像素塊而帶來的重復存儲和計算卷積的問題。
FCN的缺點也很明顯,首先是訓練比較麻煩,需要訓練三次才能夠得到FCN-8s,而且得到的結果還是不精細,對圖像的細節不夠敏感,這是因為在進行decode,也就是恢復原圖像大小的過程時,輸入上采樣層的label map太稀疏,而且上采樣過程就是一個簡單的deconvolution.
其次是對各個像素進行分類,沒有考慮到像素之間的關系.忽略了在通常的基于像素分類的分割方法中使用的空間規整步驟,缺乏空間一致性.
U-net 是基于FCN的一個語義分割網絡,適合用來做醫學圖像的分割.
下面是U-net 的結構圖:
結構比較清晰,也很優雅,成一個U狀.
和FCN相比,結構上比較大的改動在上采樣階段,上采樣層也包括了很多層的特征.
還有一個比FCN好的地方在于,Unet只需要一次訓練,FCN需要三次訓練.
我實現了unet的網絡結構,代碼在: https://github.com/zhixuhao/unet,
是用keras實現的,關于數據集和訓練測試,可以參考我這一篇博文: http://blog.csdn.net/u012931582/article/details/70215756
SegNet 是一個encoder-decoder結構的卷積神經網絡.
這里是官方網站:http://mi.eng.cam.ac.uk/projects/segnet/
SegNet 的結構如下所示:
可以看出,整個結構就是一個encoder和一個decoder.前面的encoder就是采用的vgg-16的網絡結構,而decoder和encoder基本上就是對稱的結構.
SegNet和FCN最大的不同就在于decoder的upsampling方法,上圖結構中,注意,前面encoder每一個pooling層都把pooling indices保存,并且傳遞到后面對稱的upsampling層. 進行upsampling的過程具體如下:
左邊是SegNet的upsampling過程,就是把feature map的值 abcd, 通過之前保存的max-pooling的坐標映射到新的feature map中,其他的位置置零.
右邊是FCN的upsampling過程,就是把feature map, abcd進行一個反卷積,得到的新的feature map和之前對應的encoder feature map 相加.
文章中說,他們用了CamVid 這個數據集進行了一下,這個數據集主要是街景圖片,總共有11個類,367張訓練圖片,233張測試圖片,是一個比較小的數據集.
下圖是分割結果的對比:
DeconvNet 是一個convolution-deconvolution結構的神經網絡,和SegNet非常相似
是一篇2015年ICCV上的文章: Learning Deconvolution Network for Semantic Segmentation
下面是它的結構圖:
前面的convolution network 和SegNet的encoder部分是一樣的,都是采用了VGG16的結構,只不過DeconvNet后面添加了兩個全連接層.
在進行upsampling的時候,SegNet和DeconvNet基本上是一致的,都是進行了unpooling,就是需要根據之前pooling時的位置把feature map的值映射到新的feature map上,unpooling 之后需要接一個反卷積層.
可以看出,這些網絡的結構都是非常相似的,都是基于encoder-decoder結構的,只不過說法不同,前面是一些卷積層,加上池化層,后面的decoder其實就是進行upsampling,這些網絡的最主要區別就是upsampling的不同.
FCN進行upsampling的方法就是對feature map進行反卷積,然后和高分辨率層的feature map相加.
Unet進行upsampling的方法和FCN一樣.
DeconvNet進行upsampling的方法就是進行unpooling,就是需要根據之前pooling時的位置把feature map的值映射到新的feature map上,unpooling 之后需要接一個反卷積層.
SegNet進行upsampling的方法和DeconvNet一樣.