先理解Mask R-CNN的工作原理,然後構建顏色填充器應用

2020-12-12 機器之心Pro

上年 11 月,matterport 開源了 Mask R-CNN 實現,它在 GitHub 已 fork1400 次,被用於很多項目,同時也獲得了完善。作者將在本文中解釋 Mask R-CNN 的工作原理,並介紹了顏色填充器的應用案例和實現過程。

代碼(包括作者構建的數據集和已訓練的模型):https://github.com/matterport/Mask_RCNN/tree/master/samples/balloon

什麼是實例分割?

實例分割是一種在像素層面識別目標輪廓的任務,相比其他相關任務,實例分割是較難解決的計算機視覺任務之一:

分類:這張圖像中有一個氣球。語義分割:這些全是氣球像素。目標檢測:這張圖像中的這些位置上有 7 個氣球。實例分割:這些位置上有 7 個氣球,並且這些像素分別屬於每個氣球。

Mask R-CNN

Mask R-CNN 是一個兩階段的框架,第一個階段掃描圖像並生成提議(proposals,即有可能包含一個目標的區域),第二階段分類提議並生成邊界框和掩碼。Mask R-CNN 擴展自 Faster R-CNN,由同一作者在去年提出。Faster R-CNN 是一個流行的目標檢測框架,Mask R-CNN 將其擴展為實例分割框架。

Mask R-CNN 的主要構建模塊:

1. 主幹架構

主幹網絡的簡化圖示

這是一個標準的卷積神經網絡(通常來說是 ResNet50 和 ResNet101),作為特徵提取器。底層檢測的是低級特徵(邊緣和角等),較高層檢測的是更高級的特徵(汽車、人、天空等)。

經過主幹網絡的前向傳播,圖像從 1024x1024x3(RGB)的張量被轉換成形狀為 32x32x2048 的特徵圖。該特徵圖將作為下一個階段的輸入。

代碼提示:主幹網絡在 resnet_graph() 函數中。代碼支持 ResNet50 和 ResNet101。

特徵金字塔網絡(FPN)

來源:Feature Pyramid Networks for Object Detection

上述的主幹網絡還可以進一步提升。由 Mask R-CNN 的同一作者引入的特徵金字塔網絡(FPN)是對該主幹網絡的擴展,可以在多個尺度上更好地表徵目標。

FPN 通過添加第二個金字塔提升了標準特徵提取金字塔的性能,第二個金字塔可以從第一個金字塔選擇高級特徵並傳遞到底層上。通過這個過程,它允許每一級的特徵都可以和高級、低級特徵互相結合。

在我們的 Mask R-CNN 實現中使用的是 ResNet101+FPN 主幹網絡。

代碼提示:FPN 在 MaskRCNN.build() 中創建,位於構建 ResNet 的部分之後。FPN 引入了額外的複雜度:在 FPN 中第二個金字塔擁有一個包含每一級特徵的特徵圖,而不是標準主幹中的單個主幹特徵圖(即第一個金字塔中的最高層)。選用哪一級的特徵是由目標的尺寸動態地確定的。

2. 區域建議網絡(RPN)

展示 49 個 anchor box 的簡化圖示

RPN 是一個輕量的神經網絡,它用滑動窗口來掃描圖像,並尋找存在目標的區域。

RPN 掃描的區域被稱為 anchor,這是在圖像區域上分布的矩形,如上圖所示。這只是一個簡化圖。實際上,在不同的尺寸和長寬比下,圖像上會有將近 20 萬個 anchor,並且它們互相重疊以儘可能地覆蓋圖像。

RPN 掃描這些 anchor 的速度有多快呢?非常快。滑動窗口是由 RPN 的卷積過程實現的,可以使用 GPU 並行地掃描所有區域。此外,RPN 並不會直接掃描圖像,而是掃描主幹特徵圖。這使得 RPN 可以有效地復用提取的特徵,並避免重複計算。通過這些優化手段,RPN 可以在 10ms 內完成掃描(根據引入 RPN 的 Faster R-CNN 論文中所述)。在 Mask R-CNN 中,我們通常使用的是更高解析度的圖像以及更多的 anchor,因此掃描過程可能會更久。

代碼提示:RPN 在 rpn_graph() 中創建。anchor 的尺度和長寬比由 config.py 中的 RPN_ANCHOR_SCALES 和 RPN_ANCHOR_RATIOS 控制。

RPN 為每個 anchor 生成兩個輸出:

anchor 類別:前景或背景(FG/BG)。前景類別意味著可能存在一個目標在 anchor box 中。邊框精調:前景 anchor(或稱正 anchor)可能並沒有完美地位於目標的中心。因此,RPN 評估了 delta 輸出(x、y、寬、高的變化百分數)以精調 anchor box 來更好地擬合目標。

使用 RPN 的預測,我們可以選出最好地包含了目標的 anchor,並對其位置和尺寸進行精調。如果有多個 anchor 互相重疊,我們將保留擁有最高前景分數的 anchor,並捨棄餘下的(非極大值抑制)。然後我們就得到了最終的區域建議,並將其傳遞到下一個階段。

代碼提示:ProposalLayer 是一個自定義的 Keras 層,可以讀取 RPN 的輸出,選取最好的 anchor,並應用邊框精調。

3. ROI 分類器和邊界框回歸器

這個階段是在由 RPN 提出的 ROI 上運行的。正如 RPN 一樣,它為每個 ROI 生成了兩個輸出:

階段 2 的圖示。來源:Fast R-CNN

類別:ROI 中的目標的類別。和 RPN 不同(兩個類別,前景或背景),這個網絡更深並且可以將區域分類為具體的類別(人、車、椅子等)。它還可以生成一個背景類別,然後就可以棄用 ROI 了。邊框精調:和 RPN 的原理類似,它的目標是進一步精調邊框的位置和尺寸以將目標封裝。

代碼提示:分類器和邊框回歸器已在 fpn_classifier_graph() 中創建。

ROI 池化

在我們繼續之前,需要先解決一些問題。分類器並不能很好地處理多種輸入尺寸。它們通常只能處理固定的輸入尺寸。但是,由於 RPN 中的邊框精調步驟,ROI 框可以有不同的尺寸。因此,我們需要用 ROI 池化來解決這個問題。

圖中展示的特徵圖來自較底層。

ROI 池化是指裁剪出特徵圖的一部分,然後將其重新調整為固定的尺寸。這個過程實際上和裁剪圖片並將其縮放是相似的(在實現細節上有所不同)。

Mask R-CNN 的作者提出了一種方法 ROIAlign,在特徵圖的不同點採樣,並應用雙線性插值。在我們的實現中,為簡單起見,我們使用 TensorFlow 的 crop_and_resize 函數來實現這個過程。

代碼提示:ROI 池化在類 PyramidROIAlign 中實現。

4. 分割掩碼

到第 3 節為止,我們得到的正是一個用於目標檢測的 Faster R-CNN。而分割掩碼網絡正是 Mask R-CNN 的論文引入的附加網絡。

掩碼分支是一個卷積網絡,取 ROI 分類器選擇的正區域為輸入,並生成它們的掩碼。其生成的掩碼是低解析度的:28x28 像素。但它們是由浮點數表示的軟掩碼,相對於二進位掩碼有更多的細節。掩碼的小尺寸屬性有助於保持掩碼分支網絡的輕量性。在訓練過程中,我們將真實的掩碼縮小為 28x28 來計算損失函數,在推斷過程中,我們將預測的掩碼放大為 ROI 邊框的尺寸以給出最終的掩碼結果,每個目標有一個掩碼。

代碼提示:掩碼分支網絡在 build_fpn_mask_graph() 中。

建立一個顏色填充過濾器

和大多數圖像編輯 app 中包含的過濾器不同,我們的過濾器更加智能一些:它能自動找到目標。當你希望把它應用到視頻上而不是圖像上時,這種技術更加有用。

訓練數據集

通常我會從尋找包含所需目標的公開數據集開始。但在這個案例中,我想向你展示這個項目的構建循環過程,因此我將介紹如何從零開始構建一個數據集。

我在 flickr 上搜索氣球圖片,並選取了 75 張圖片,將它們分成了訓練集和驗證集。找到圖片很容易,但標註階段才是困難的部分。

等等,我們不是需要數百萬張圖片來訓練深度學習模型嗎?實際上,有時候需要,有時候則不需要。我是考慮到以下兩點而顯著地減小了訓練集的規模:

首先,遷移學習。簡單來說,與其從零開始訓練一個新模型,我從已在 COCO 數據集(在 repo 中已提供下載)上訓練好的權重文件開始。雖然 COCO 數劇集不包含氣球類別,但它包含了大量其它圖像(約 12 萬張),因此訓練好的圖像已經包含了自然圖像中的大量常見特徵,這些特徵很有用。其次,由於這裡展示的應用案例很簡單,我並不需要令這個模型達到很高的準確率,很小的數據集就已足夠。

有很多工具可以用來標註圖像。由於其簡單性,我最終使用了 VIA(VGG 圖像標註器)。這是一個 HTML 文件,你可以下載並在瀏覽器中打開。標註最初幾張圖像時比較慢,不過一旦熟悉了用戶界面,就能達到一分鐘一個目標的速度。

VGG 圖像標註器工具的用戶界面

如果你不喜歡 VIA 工具,可以試試下列工具,我都測試過了:

LabelMe:最著名的標註工具之一,雖然其用戶界面有點慢,特別是縮放高清圖像時。RectLabel:簡單易用,只在 Mac 可用。LabelBox:對於大型標記項目很合適,提供不同類型標記任務的選項。COCO UI:用於標註 COCO 數據集的工具。

加載數據集

分割掩碼的保存格式並沒有統一的標準。有些數據集中以 PNG 圖像保存,其它以多邊形點保存等。為了處理這些案例,在我們的實現中提供了一個 Dataset 類,你可以通過重寫幾個函數來讀取任意格式的圖像。

VIA 工具將標註保存為 JSON 文件,每個掩碼都是一系列多邊形點。

代碼提示:通過複製 coco.py 並按你的需要修改是應用新數據集的簡單方法,我將新的文件保存為 ballons.py。

我的 BalloonDataset 類是這樣定義的:

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

load_mask 通過畫出多邊形為圖像中的每個目標生成位圖掩碼。

image_reference 返回鑑別圖像的字符串結果,以進行調試。這裡返回的是圖像文件的路徑。

你可能已經注意到我的類不包含加載圖像或返回邊框的函數。基礎的 Dataset 類中默認的 load_image 函數可以用於加載圖像,邊框是通過掩碼動態地生成的。

驗證該數據集

為了驗證我的新代碼可以正確地實現,我添加了這個 Jupyter notebook:inspect_balloon_data.ipynb。它加載了數據集,並可視化了掩碼、邊框,還可視化了 anchor 來驗證 anchor 的大小是否擬合了目標大小。以下是一個 good example。

來自 inspect_balloon_data notebook 的樣本

代碼提示:為了創建這個 notebook 我複製了 inspect_data.ipynb(這是為 COCO 數據集寫的),然後修改了代碼的初始部分來加載 Balloons 數據集。

配置

這個項目的配置和訓練 COCO 數據集的基礎配置很相似,因此我只需要修改 3 個值。正如我對 Dataset 類所設置的,我複製了基礎的 Config 類,然後添加了我的覆寫:

基礎的配置使用的是 1024x1024 px 的輸入圖像尺寸以獲得最高的準確率。我保持了相同的配置,雖然圖像相對較小,但模型可以自動地將它們重新縮放。

代碼提示:基礎的 Config 類在 config.py 中,BalloonConfig 在 balloons.py 中。

訓練

Mask R-CNN 是一個規模很大的模型。尤其是在我們的實現中使用了 ResNet101 和 FPN,因此你需要一個 12GB 顯存的 GPU 才能訓練這個模型。我使用的是 Amazon P2 實例來訓練這個模型,在小規模的數據集上,訓練時間不到 1 個小時。

用以下命令開始訓練,以從 balloon 的目錄開始運行。這裡,我們需要指出訓練過程應該從預訓練的 COCO 權重開始。代碼將從我們的 repo 中自動下載權重。

如果訓練停止了,用以下命令讓訓練繼續:

代碼提示:除了 balloon.py 以外,該 repo 還有兩個例子:train_shapes.ipynb,它訓練了一個小規模模型來檢測幾何形狀;coco.py,它是在 COCO 數據集上訓練的。

檢查結果

inspect_balloon_model notebook 展示了由訓練好的模型生成的結果。查看該 notebook 可以獲得更多的可視化選項,並一步一步檢查檢測流程。

代碼提示:這個 notebook 是 inspect_model.ipynb 的簡化版本,包含可視化選項和對 COCO 數據集代碼的調試。

顏色填充

現在我們已經得到了目標掩碼,讓我們將它們應用於顏色填充效果。方法很簡單:創建一個圖像的灰度版本,然後在目標掩碼區域,將原始圖像的顏色像素複製上去。以下是一個 good example:

代碼提示:應用填充效果的代碼在 color_splash() 函數中。detect_and_color_splash() 可以實現加載圖像、運行實例分割和應用顏色填充過濾器的完整流程。

FAQ 環節

Q:我希望了解更多該實現的細節,有什麼可讀的?

A:按這個順序閱讀論文:RCNN、Fast RCNN、Faster RCNN、FPN、Mask RCNN。

Q:我能在哪裡提更多的問題?

A:我們的 repo 的 Issue 頁面:https://github.com/matterport/Mask_RCNN/issues

原文連結:https://engineering.matterport.com/splash-of-color-instance-segmentation-with-mask-r-cnn-and-tensorflow-7c761e238b46

相關焦點

  • Mask R-CNN
    Mask R-CNN是一種在有效檢測目標的同時輸出高質量的實例分割mask。是對faster r-cnn的擴展,與bbox識別並行的增加一個預測分割mask的分支。Mask R-CNN 可以應用到人體姿勢識別。並且在實例分割、目標檢測、人體關鍵點檢測三個任務都取得了現在最好的效果。效果圖
  • 愷明大神 Mask R-CNN 超實用教程
    ROI池化的工作原理是從特徵map中提取一個固定大小的窗口,並使用這些特徵獲得最終的類別標籤和邊界框。或者用你的手機拍一些視頻,然後回到你的電腦前使用它們!output/ :另一個空目錄,將保存處理過的視頻(假設您將命令行參數設置為輸出到此目錄)。 今天我們將回顧兩個腳本: 現在,我們已經回顧了Mask R-CNNs的工作原理,讓我們動手寫一些Python代碼。
  • 【從零開始學Mask RCNN】一,原理回顧&&項目文檔翻譯
    對上個步驟中獲得的ROI區域執行論文提出的ROIAlign操作,即先將原圖和feature map的pixel對應起來,然後將feature map和固定的feature對應起來。最後對這些ROI區域進行多類別分類,候選框回歸和引入FCN生成Mask,完成分割任務。
  • 愷明大神 Mask R-CNN 超實用教程
    直接跳到下載(https://www.pyimagesearch.com/2018/11/19/mask-r-cnn-with-opencv/#)。在本教程的第一部分中,我們將討論圖像分類、對象檢測、實例分割和語義分割之間的區別。 這裡,我們將簡要回顧Mask R-CNN架構及其與Faster R-CNN的關係。然後,我將向您展示如何在圖像和視頻流上應用Mask R-CNN與OpenCV。
  • 經典目標檢測方法Faster R-CNN和Mask R-CNN|基於PaddlePaddle深度...
    Mask R-CNN 可以應用到人體姿勢識別,並且在實例分割、目標檢測、人體關鍵點檢測三個任務都取得了很好的效果。因此,百度深度學習框架 PaddlePaddle 開源了用於目標檢測的 RCNN 模型,從而可以快速構建強大的應用,滿足各種場景的應用,包括但不僅限於安防監控、醫學圖像識別、交通車輛檢測、信號燈識別、食品檢測等等。
  • 用於圖像分割的卷積神經網絡:從R-CNN到Mask R-CNN
    通過多個尺度的窗口選擇性搜索,並搜尋共享紋理、顏色或強度的相鄰像素。然後,每個區域的特徵簡單地池化(通常使用最大池化(Max Pooling))。所以我們所需要的是原始圖像的一次傳遞,而非大約 2000 次!Fast R-CNN 見解 2:將所有模型併入一個網絡Fast R-CNN 將卷積神經網絡(CNN),分類器和邊界框回歸器組合為一個簡單的網絡。
  • 一文看懂近年火到不行的CNN圖像識別:從R-CNN到Mask R-CNN
    選擇性搜索(Selective Search)方法通過不同尺寸的窗口的滑動尋找相近紋理、顏色或亮度的相鄰像素。他的想法非常簡單——為什麼不讓每張圖像只計算一次CNN,然後在2000個區域建議中找到一種方法來分享計算結果呢?
  • 潮科技行業入門指南 | 深度學習理論與實戰:提高篇(14)——Mask R...
    = results[0] visualize.display_instances(image, r['rois'], r['masks'], r['class_ids'], class_names, r['scores'])檢測結果r包括rois(RoI)、masks(
  • 輕鬆掌握 MMDetection 中常用算法(二):Faster R-CNN|Mask R-CNN
    其詳細流程是:將c2 c3 c4 c5 4 個特徵圖全部經過各自 1x1 卷積進行通道變換變成 m2~m5,輸出通道統一為 256從 m5 開始,先進行 2 倍最近鄰上採樣,然後和 m4 進行 add 操作,得到新的 m4將新 m4 進行 2 倍最近鄰上採樣,然後和 m3 進行 add 操作,得到新的 m3將新 m3 進行 2 倍最近鄰上採樣,然後和 m2 進行 add 操作,得到新的 m2
  • 【源頭活水】Sparse R-CNN:簡化版fast rcnn
    算法,是faster rcnn算法的前身,由於其巨大計算量以及無法端到端訓練,故而提出區域提取網絡RPN加上fast rcnn的faster rcnn算法。其包括兩個主要組件:無序集合輸出的loss計算第一步是先採用匈牙利算法進行雙邊匹配,得到無序輸出和無序gt bbox的有序索引對,然後對有序的一對一預測和gt計算相應loss即可。由於其訓練時候每個gt bbox只有一個匹配,故detr測試階段不需要nms。
  • FAIR最新視覺論文集錦:FPN,RetinaNet,Mask 和 Mask-X RCNN(含代碼...
    能構建出一個簡單易行的基本模型,在各種不同的任務都好使,並不是一件容易的事。深究細節之前先強調一點,FPN 是基於一個特徵提取網絡的,它可以是常見的 ResNet 或者 DenseNet 之類的網絡。在你最常用的深度學習框架下取一個預訓練模型,就可以用來實現 FPN 了。
  • 何愷明團隊:從特徵金字塔網絡、Mask R-CNN到學習分割一切
    構建一個每個人都可以在各種任務、子主題和應用領域中建立的基準模型並不容易。在詳細討論之前,我們需要了解的一點是:FPN是ResNet或DenseNet等通用特徵提取網絡的附加組件。你可以從你喜歡的DL庫中得到想要的預訓練FPN模型,然後像其他預訓練模型一樣使用它們。物體是以不同的的scale和size出現的。
  • 何愷明團隊計算機視覺最新進展:從特徵金字塔網絡、Mask R-CNN到...
    構建一個每個人都可以在各種任務、子主題和應用領域中建立的基準模型並不容易。在詳細討論之前,我們需要了解的一點是:FPN是ResNet或DenseNet等通用特徵提取網絡的附加組件。你可以從你喜歡的DL庫中得到想要的預訓練FPN模型,然後像其他預訓練模型一樣使用它們。  物體是以不同的的scale和size出現的。
  • 接地氣介紹一下Mask RCNN
    根據 Faster RCNN 計算出來的每個候選框的分數,篩選出一大堆更加準確的 RoI 「對應圖中 selected RoI」,然後用一個 RoI Align 層提取這些 RoI 的特徵,計算出一個 mask,根據 RoI 和原圖的比例,將這個 mask 擴大回原圖,就可以得到一個分割的 mask 了。
  • Mask R-CNN官方實現「又」來了!訓練速度是原來2倍
    cocoapi yacs matplotlib OpenCV(可選) R-CNN發展歷史 R-CNN是卷積神經網絡(CNN)在圖像識別領域的應用
  • CondInst:性能和速度均超越Mask RCNN的實例分割模型
    對於實例分割來說,主流的做法還是基於先檢測後分割的流程,比如最流行的Mask RCNN模型就是構建在Faster RCNN基礎上。目前這方面的工作主要集中在三個方向:Mask encoding:對2D mask編碼為1D representation,比如PolarMask基於輪廓構建了polar representation,而MEInst則將mask壓縮成一個1D vector,這樣預測mask就類似於box regress那樣直接加在one-stage檢測模型上;
  • (附代碼)| 從特徵金字塔網絡、Mask R-CNN到學習分割一切
    FPN的論文真的很棒。構建一個每個人都可以在各種任務、子主題和應用領域中建立的基準模型並不容易。在詳細討論之前,我們需要了解的一點是:FPN是ResNet或DenseNet等通用特徵提取網絡的附加組件。你可以從你喜歡的DL庫中得到想要的預訓練FPN模型,然後像其他預訓練模型一樣使用它們。物體是以不同的的scale和size出現的。
  • CNN 原理與實踐指南
    本文對CNN的基礎原理及常見的CNN網絡進行了詳細解讀,並介紹了Pytorch構建深度網絡的流程。最後,以阿里天池零基礎入門CV賽事為學習實踐,對Pytorch構建CNN模型進行實現。卷積神經網絡理解因此卷積、ReLu、pooling,不斷重複其實也就基本上構成了卷積神經網絡的框架,如圖8。然後將最終得到的feaure map 排成一列(圖8),接到全連接層,這樣就形成了我們的卷積神經網絡。值得注意的是,排成一列的數值,是有權重,而這些權重是通過訓練、反向傳播得到的,通過權重的計算,可以知道不同分類的概率是怎麼樣的。
  • CNN原理與實踐指南
    本文對CNN的基礎原理及常見的CNN網絡進行了詳細解讀,並介紹了Pytorch構建深度網絡的流程。最後,以阿里天池零基礎入門CV賽事為學習實踐,對Pytorch構建CNN模型進行實現。卷積神經網絡理解因此卷積、ReLu、pooling,不斷重複其實也就基本上構成了卷積神經網絡的框架,如圖8。然後將最終得到的feaure map 排成一列(圖8),接到全連接層,這樣就形成了我們的卷積神經網絡。值得注意的是,排成一列的數值,是有權重,而這些權重是通過訓練、反向傳播得到的,通過權重的計算,可以知道不同分類的概率是怎麼樣的。
  • 經典論文速讀-Mask R-CNN
    另一方面,本文將mask預測和類別預測解耦,mask類別由RoI分類來完成,對比FCNs同時預測類別和mask,實例分割表現則很差。2 相關工作R-CNN,基於區域的方法來檢測目標,各個目標基於RoI使用RoIPool獨立預測和驗證,詳細內容可以閱讀經典論文速讀-Faster R-CNN 上,經典論文速讀-Faster R-CNN 下