Splash of Color: Instance Segmentation with Mask R-CNN and TensorFlow

噴色:使用Mask R-CNN和TensorFlow進行實例分割

原文:Splash of Color: Instance Segmentation with Mask R-CNN and TensorFlow
原作者:Waleed Abdulla

0 概述

早在11月,我們就將Mask R-CNN的實現開源了,此後,它被forked了1400次,在許多項目中使用,並得到了許多貢獻者的改進。我們也收到了很多問題,因此在這篇文章中,我將解釋該模型的工作原理,並展示如何在實際應用中使用它。

我將介紹兩件事:

  • 首先,Mask RCNN概述。
  • 其次,如何從頭訓練模型並使用它來構建智能的彩色噴塗濾鏡。

1 Mask RCNN概述

1.1 什麼是圖像實例分割(Instance Segmentation)?

圖像識別領域有以下幾個研究方向,如下圖所示:

  • 分類:此圖像中有一個氣球。
  • 語義分割:所有這些都是氣球像素。
  • 物體檢測:此圖像中的這些位置有7個氣球。我們開始考慮重疊的對象。
  • 實例分割:在這些位置有7個氣球,它們是每個像素的像素。

undefined
其中,實例分割是在像素級別識別對象輪廓的任務。與類似的計算機視覺任務相比,它是最難的視覺任務之一。

1.2 Mask R-CNN

Mask R-CNN(區域卷積神經網絡)是一個兩階段的框架:第一階段掃描圖像並生成提案(可能包含對象的區域)。第二階段對候選區域進行分類,並生成邊框和masks。

去年,它是通過Mask R-CNN論文引入的,目的是擴展同一作者的前身Faster R-CNN。Faster R-CNN是流行的對象檢測框架,而Mask R-CNN則通過實例分割對其進行了擴展。

undefined
如上圖所示,Mask R-CNN包含以下模塊:

1.2.1 Backbone

undefined

這是用作特徵提取器的標準卷積神經網絡(通常爲ResNet50或ResNet101)。較早的層檢測低層特徵(邊緣和角落),而較後的層依次檢測高層特徵(汽車,人,天空)。

通過backbone ,圖像從1024x1024px x 3(RGB)轉換爲形狀爲32x32x2048的特徵圖。此功能圖成爲以下階段的輸入。

代碼提示:backbone 內置在函數resnet_graph()中。該代碼支持ResNet50和ResNet101。

1.2.1.1 Feature Pyramid Network

undefined
儘管上面描述的主幹機制很好用,但是可以對其進行改進。Mask R-CNN的同一作者介紹了Feature Pyramid Network (FPN) ,作爲可以更好地表示多個比例對象的擴展。

FPN通過添加第二個金字塔來改進標準特徵提取金字塔,該金字塔從第一個金字塔中獲取高級特徵並將其向下傳遞到較低層。這樣,它允許每個級別的功能都可以訪問較低和較高級別的功能。

我們的Mask RCNN實現使用ResNet101 + FPN backbone

代碼提示:FPN在MaskRCNN.build()中創建。構建ResNet之後的部分。RPN引入了額外的複雜性:而不是標準主幹網(即第一金字塔的頂層)中的單個主幹特徵圖,在FPN中,第二個金字塔的每個級別都有一個特徵圖。我們根據對象的大小選擇動態使用的對象。我將繼續參考主幹要素地圖,就像它是一個要素地圖一樣,但是請記住,在使用FPN時,實際上是在運行時從多個要素中選擇一個。

1.2.2 Region Proposal Network (RPN)

undefined
RPN是一個輕量級的神經網絡,它以滑動窗口的方式掃描圖像並查找包含對象的區域。

RPN掃描的區域稱爲錨點。如左圖所示,它們是分佈在圖像區域上的框。

不過,這是一個簡化的視圖。實際上,大約有20萬個不同大小和縱橫比的錨點,並且它們重疊以覆蓋儘可能多的圖像。

RPN可以掃描這麼多錨點的速度有多快?實際上,速度非常快。滑動窗口由RPN的卷積特性處理,這使其可以並行(在GPU上)掃描所有區域。此外,RPN不會直接掃描圖像(即使我們在圖像上畫了錨點也只是爲了說明)。相反,RPN掃描骨幹特徵圖。這使RPN可以有效地重用提取的特徵,並避免重複計算。通過這些優化,根據引入它的Faster RCNN論文,RPN運行大約10毫秒。在Mask RCNN中,我們通常使用更大的圖像和更多的錨點,因此可能需要更長的時間。

代碼提示:RPN在rpn_graph()中創建。錨定比例和縱橫比由config.py中的RPN_ANCHOR_SCALES和RPN_ANCHOR_RATIOS控制。

RPN爲每個錨點生成兩個輸出:

  1. 錨類(Anchor Class):兩種類之一:前景或背景。FG類表示該框中可能有一個對象。
  2. 邊界框優化(Bounding Box Refinement):前景定位點(也稱爲正定位點)可能未在對象上完美居中。因此,RPN估算出一個增量(x,y,寬度,高度的百分比變化)以細化錨框以更好地適合對象。
    undefined
    使用RPN預測,我們選擇可能包含對象的頂部錨點,並優化其位置和大小。
    如果多個錨點重疊太多,我們保留前景得分最高的錨點,並丟棄其餘的錨點(稱爲非最大抑制)。
    之後,我們將獲得最終建議(感興趣的區域),並將其傳遞到下一階段.

代碼提示:ProposalLayer是自定義的Keras圖層,可讀取RPN的輸出,選擇頂部錨點並應用邊界框優化。

1.2.3 ROI Classifier & Bounding Box Regressor

此階段在RPN建議的感興趣區域(ROI)上運行。就像RPN一樣,它爲每個ROI生成兩個輸出:

undefined

  1. 類(Class):ROI中對象的類。與具有兩個類別(FG / BG)的RPN不同,此網絡更深入,並且具有將區域分類爲特定類別(人,汽車,椅子等)的能力。它還可以生成背景類,從而導致ROI被丟棄。
  2. 邊界框優化(Bounding Box Refinement):與RPN中的操作非常相似,其目的是進一步優化邊界框的位置和大小以封裝對象。

Code Tip:
The classifier and bounding box regressor are created in fpn_classifier_graph().

ROI Pooling

在繼續之前,有一個問題需要解決。分類器無法很好地處理可變輸入大小。它們通常需要固定的輸入大小。但是,由於RPN中的邊界框優化步驟,ROI框可以具有不同的大小。這就是ROI池發揮作用的地方。

undefined
ROI合併是指裁剪要素地圖的一部分並將其大小調整爲固定大小。從原理上講,它類似於裁剪圖像的一部分然後調整其大小(但實現細節有所不同)。

Mask R-CNN的作者提出了一種名爲ROIAlign的方法,在該方法中,他們在不同點採樣特徵圖並應用雙線性插值。

在我們的實施中,爲簡單起見,我們使用TensorFlow的crop_and_resize函數,因爲它對於大多數用途而言都足夠接近。

1.2.4 Segmentation Masks

如果您在上一節的末尾停下來,那麼您將擁有用於對象檢測的Faster R-CNN框架。Mask網絡是Mask R-CNN論文引入的補充。

遮罩分支是一個卷積網絡,它採用ROI分類器選擇的正區域併爲其生成遮罩。生成的蒙版分辨率很低:28x28像素。但是它們是軟掩碼,由浮點數表示,因此與二進制掩碼相比,它們具有更多的細節。較小的面罩尺寸有助於使面罩分支保持明亮。

在訓練過程中,我們將真實的蒙版按比例縮小到28x28以計算損失,而在推理過程中,我們將預測的蒙版按比例縮放到ROI邊界框的大小,這爲我們提供了最終的masks(每個對象一個)。

2 Mask RCNN實戰

與大多數包含此濾鏡的圖像編輯應用程序不同,我們的濾鏡會更聰明:它會自動查找對象。如果您想將其應用於視頻而不是單個圖像,該功能將變得更加有用。
undefined

2.1 Training Dataset

通常,我會先搜索包含所需對象的公共數據集。但是在這種情況下,我想記錄整個週期並展示如何從頭開始構建數據集。

我在flickr上搜索了氣球圖像,將許可證類型限制爲“允許商業使用和改裝”。這樣返回的圖像足以滿足我的需求。我總共選擇了75張圖像,並將它們分爲訓練集和驗證集。查找圖像很容易。註釋它們是困難的部分。

等待!我們是否不需要一百萬張圖像來訓練深度學習模型?有時您會這樣做,但通常卻不會。我主要依靠兩點來大大減少培訓需求:

首先,轉移學習。這只是意味着,我不是從頭開始訓練模型,而是從在COCO數據集上得到訓練的權重文件開始(我們在github存儲庫中提供了該文件)。儘管COCO數據集不包含氣球類,但它包含許多其他圖像(〜120K),因此訓練的權重已經學習了自然圖像中許多常見的功能,這確實有幫助。其次,考慮到這裏的簡單用例,我不要求該模型具有很高的準確性,因此微小的數據集就足夠了。

有很多用於註釋圖像的工具。由於其簡單性,我最終使用了VIA(VGG圖像註釋器)。該文件是您下載並在瀏覽器中打開的一個HTML文件。批註最初的幾幅圖像非常慢,但是一旦習慣了用戶界面,我就在一分鐘左右對一個對象進行批註。

undefined
如果您不喜歡VIA工具,以下是我測試過的其他工具的列表:

  • LabelMe:最知名的工具之一。但是,UI太慢了,特別是在放大大圖像時。
  • RectLabel:簡單易用。僅Mac。
  • LabelBox:非常適合大型標籤項目,並且具有用於不同類型標籤任務的選項。
  • VGG圖像註釋器(VIA):快速,輕巧,設計精良。這是我最終使用的那個。
  • COCO UI:用於註釋COCO數據集的工具。

2.2 Loading the Dataset

沒有通用的格式來存儲細分掩碼。一些數據集將它們保存爲PNG圖像,其他數據集將它們存儲爲多邊形點,依此類推。爲了處理所有這些情況,我們的實現提供了一個Dataset類,您可以從該類繼承該Dataset類,然後重寫一些函數來以可能的任何格式讀取數據。

VIA tool 將註釋保存在JSON文件中,每個mask 是一組多邊形點。我沒有找到該格式的文檔,但是通過查看生成的JSON可以很容易地找到它。我在代碼中添加了註釋,以解釋解析是如何完成的。

代碼提示:爲新數據集編寫代碼的一種簡單方法是複製coco.py並根據需要對其進行修改。這是我做的。我將新文件另存爲Balloons.py

我的BalloonDataset類如下所示:

class BalloonDataset(utils.Dataset):
    def load_balloons(self, dataset_dir, subset):
        ...
    def load_mask(self, image_id):
        ...
    def image_reference(self, image_id):
        ...

load_balloons讀取JSON文件,提取註釋,然後迭代調用內部的add_class和add_image函數來構建數據集。

load_mask通過繪製多邊形爲圖像中的每個對象生成位圖蒙版。

image_reference只是返回一個標識圖像的字符串以進行調試。在這裏,它只是返回圖像文件的路徑。

您可能已經注意到,我的課程不包含用於加載圖像或返回邊界框的函數。基本Dataset類中的默認load_image函數處理加載圖像。並且,邊界框是從masks動態生成的。

2.3 Verify the Dataset

爲了驗證新代碼是否正確實現,我添加了此Jupyter筆記本。它加載數據集,可視化蒙版和邊界框,並可視化錨點,以驗證我的錨點大小是否適合我的對象大小。這是您應該看到的示例:
undefined

代碼提示:爲了創建此筆記本,我複製了我們爲COCO數據集編寫的inspect_data.ipynb,並在頂部修改了一段代碼以加載Balloons數據集。

2.4 Configurations

該項目的配置類似於用於訓練COCO數據集的基本配置,因此我只需要覆蓋3個值。正如我對Dataset類所做的那樣,我繼承自Config類的基礎並添加了覆蓋:

class BalloonConfig(Config):
    # Give the configuration a recognizable name
    NAME = "balloons"
    # Number of classes (including background)
    NUM_CLASSES = 1 + 1  # Background + balloon
    # Number of training steps per epoch
    STEPS_PER_EPOCH = 100

基本配置使用大小爲1024x1024 px的輸入圖像以獲得最佳準確性。我保持這種方式。我的圖像稍小,但是模型會自動調整其大小。

代碼提示:基本的Config類位於config.py中。而且BalloonConfig位於Balloons.py中。

2.5Training

Mask R-CNN是一個相當大的模型。特別是我們的實現使用ResNet101和FPN。因此,您需要具有12GB內存的現代GPU。它的工作量可能更少,但我沒有嘗試過。我使用Amazon的P2實例來訓練該模型,並且由於數據集很小,訓練花費了不到一個小時的時間。

從氣球目錄運行,使用此命令開始訓練。在這裏,我們指定訓練應從預先訓練的COCO權重開始。該代碼將自動從我們的存儲庫下載權重:

python3 balloon.py train --dataset=/path/to/dataset --model=coco

並繼續訓練(如果停止):

python3 balloon.py train --dataset=/path/to/dataset --model=last

代碼提示:除了Balloons.py之外,該存儲庫還有另外三個示例:train_shapes.ipynb(用於訓練玩具模型以檢測幾何形狀),coco.py(用於在COCO數據集上進行訓練)和核(用於在顯微鏡圖像中分割核)。

2.6 Inspecting the Results

inspect_balloon_model筆記本顯示了經過訓練的模型生成的結果。檢查筆記本以獲取更多可視化效果,並逐步完成檢測流程。
undefined

代碼提示:該筆記本是inspect_mode.ipynb的簡化版本,其中包括COCO數據集的可視化和調試代碼。

2.7 Color Splash

最後,既然有了對象遮罩,我們就可以使用它們來應用顏色飛濺效果。該方法非常簡單:創建圖像的灰度版本,然後在對象蒙版標記的區域中,從原始圖像中複製回彩色像素。這是一個例子:

undefined

代碼提示:施加效果的代碼在color_splash()函數中。detect_and_color_splash()處理整個過程,包括加載圖像,運行實例分割以及應用顏色飛濺過濾器。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章