ROIPooling和ROIAlign的區別(通俗易懂)


本文詳細講解了 RoIPooling 、RoIAlign 和 RoIWarp ,用非常的圖來幫助理解,相信通過本文閱讀能讓你對這三者有更加深刻的理解

如果對你有所幫助請點個在看、點或分享,鼓勵一下小編

理解Region of Interest — (RoI Pooling)

快速而簡單地解釋什么是RoI Pooling 以及它是如何工作的?為什么我們在Fast R-CNNs中使用它?

Fast R-CNNs 架構。來源https://arxiv.org/pdf/1504.08083.pdf

我們將討論在Fast R-CNN文件中描述的原始RoI池化(上圖中的淺藍色矩形)。這個過程還有第二種和第三種版本分別叫做 RoIAlign 和 RoIWarp 。

什么是RoI?

RoI(Region of Interest)是從原始圖像中提取的區域。我們不打算講解如何提取這些區域,因為有很多方法可以做到。我們現在唯一應該知道的是,有多個類似的區域,最后都應該接受測試。

Fast R-CNN 的原理

特征提取

Fast R-CNN 不同於基本的 R-CNN網絡。它只有一個卷積特征提取(在我們的示例中,我們將使用VGG16)。

VGG16 特征提取輸出尺寸

我們的模型取一個尺寸為 512x512x3 (寬度x高度x RGB) 的圖像輸入,VGG16將其映射為一個 16x16x512 的feature map。你可以使用不同的輸入大小(通常較小,Keras中VGG16的默認輸入大小為224x224)。

如果你看輸出矩陣,你應該注意到它的 寬度和高度 正好比輸入圖像小32倍(512/32 = 16)。這很重要,因為所有 RoIs 都要按這個因子減小。

Sample RoIs

這里只畫出了 4 個不同的 RoI 。在實際的Fast R-CNN你可能有成千上萬個,但打印所有使圖像難於觀察。

Regions of Interest, 圖片來源:https://www.flickr.com/photos/bunny/

重要!需要記住的是 RoI 不是一個邊界框。它可能看起來像一個,但它只是一個進一步處理的proposal。很多人都這么認為,因為大多數論文和博客文章都是在提出proposals,而不是實際的對象。這樣更方便,上面的圖像上也這樣做了。這里有一個不同的 proposal area ,也將被Fast R-CNN(綠框)選中。

Region of Interest which doesn’t make sense

有一些方法可以限制 RoI 的數量,也許我將來會寫一些關於它的東西。

如何從feature map 上獲取 RoI ?

現在,當我們知道RoI是什么時,我們必須能夠將它們映射到VGG16的輸出 feature map上。

將RoI映射到VGG16的輸出

每個RoI都有它的原始坐標和大小。從現在開始,我們將只關注其中之一:

我們的RoI 對象

其原始大小為 145x200 ,左上角設置為 (192x296) 。正如你可能知道的,我們無法將這些數字的大部分整除以 32(比例因子)。

- width: 200/32 = 6.25

- height: 145/32 = ~4.53

- x: 296/32 = 9.25

- y: 192/32 = 6

只有最后一個數字(左上角的Y坐標)是有意義的。這是因為我們現在使用的是 16x16 網格,我們關心的數字只有整數(更精確地說:自然數)。

feature map上坐標的量化

量化是將輸入從一大組值(如實數)約束為一組離散的值(如整數)的過程。

如果我們feature map 上原始的 RoI 如下所示:

feature map 上的 原始 RoI

我們不能真正地在它上面應用池化層,因為一些“cells”被分割了。量化所做的就是每一個結果在放到矩陣上之前都進行約減。 9.25變成9, 4.53變成4,等等。

量化后的RoI

你可以注意到我們剛剛丟失了一堆數據(深藍色)和獲得了新的數據(綠色):

Quantization losses

我們不需要處理它因為它仍然可以工作但是這個過程有一個不同的版本叫做RoIAlign它可以修復這個問題

RoI Pooling

現在,當我們把RoI映射到feature map上時,我們可以在上面應用pooling。為了方便起見,我們將再次選擇 RoI池化層 的大小,但請記住,大小可能是不同的。你可能會問:“我們為什么要應用RoI Pooling呢?”這是個好問題。如果你看原始設計的Fast R-CNN:

原始的 Fast R-CNN 架構 ,來源:(https://arxiv.org/pdf/1504.08083.pdf)

在 RoI池化層 之后是一個固定大小的 全連接層。因為RoIs的大小不同,所以我們必須將它們池化為相同的大小(在我們的示例中為 3x3x512)。此時我們映射的RoI大小為 4x6x512,你可以想象我們 不能將4除以3:(這就是量化再次使用的地方。)

映射后的 RoI 和 池化層

這次我們不需要處理坐標,只需要處理大小。我們很幸運(或者只是適用於池化層的大小) 6 可以整除以 3 得到2,但當你用 4 除以 3 時,剩下1.33。在應用相同的方法( 約簡 round down )后,我們有一個 1x2的向量。我們的映射是這樣的:

數據池化映射

由於量化,我們又一次失去了最底下的那行

數據的池化映射

現在我們能將數據池化成 3x3x512的矩陣

數據池化處理過程

在本例中,我們應用了 最大池化,但在你的模型中可能會有所不同。當然,這個過程是在整個RoI矩陣上完成的,而不僅僅是在最頂層。所以最終的結果是這樣的:

同樣的過程應用到原始圖像的每一個RoI上,因此最終,我們可能會得到數百甚至數千個3x3x512矩陣。每一個矩陣都必須通過網絡的其余部分(從FC層開始)發送。對於它們,模型分別生成bbox和類。

接下來呢?

在池化完成之后,我們確定輸入的大小為**3x3x512**,這樣我們就可以將其輸入到FC層進行進一步處理。還有一件事要討論。由於量化過程,我們丟失了很多數據。確切地說,就是:

量化數據丟失(深藍色和淺藍色),數據獲得(綠色)

這可能是一個問題,因為每個“單元格”都包含大量數據(feature map上的1x1x512,在原始圖像上大致相當於32x32x3,但請不要使用這個引用,因為卷積層不是這樣工作的)。有一種方法可以解決這個問題(RoIAlign)

Understanding Region of Interest — (RoI Align and RoI Warp)

為什么我們想去修改 RoI 池化

正如我們上面所說的,RoI 池化 有一個主要的問題。它在處理過程中丟失了大量的數據。

量化數據丟失(深藍色和淺藍色),數據獲得(綠色)

每次進行 RoI 池化操作的時候,就會丟失關於該對象的部分信息。這降低了整個模型的精確度,很多真正聰明的人都考慮過這個問題。

設置

在我們開始之前,我需要快速解釋一下我們的模型。

原始的 Mask R-CNN 架構。來源:(https://arxiv.org/pdf/1703.06870.pdf)

Mask R-CNN 的輸出

我們將使用 Mask R-CNN 網絡進行測試。我們使用它的唯一原因是,這種網絡從一個精確的池化層中獲益更多,因此更容易顯示 RoI Align和RoI池化之間的差異。我們使用哪個網絡並不重要,重要的是它實現了RoI 池化。因此我們的設置不變,看起來是這樣的:

模型特征映射過程。圖片來源:https://www.flickr.com/photos/bunny/

我們的模型取一個大小為 512x512x3 (寬度x高度x RGB)的圖像輸入,VGG16將其映射為一個 16x16x512的feature map。比例因子是 32 。

接下來,我們將使用其中一個proposed RoIs ( 145x200box),並嘗試將其映射到feature map上。因為不是所有的對象維度都可以整除以32,所以我們沒有將RoI與網格對齊。

RoI 位置

- (9.25,6)— top left corner

- 6.25— width

- 4.53 — height

再一次,我們選擇池化層的大小為 3x3,所以最終的形狀是 3x3x512(這只是一個任意的例子,以便更容易在圖像上顯示。你的池化層可能有不同的大小)。

池化層

在這里,所有看上去和 RoI 池化一樣

引入RoI Align

RoI池化和RoI Align之間的主要區別是量化。**RoI Align沒有將量化**用於數據池化。你知道Fast R-CNN應用了兩次量化。第一次在映射過程中,第二次在池化過程中。

我們可以跳過這些操作,將原始RoI分成9個等大小的小格子,並在每個盒子內應用雙線性插值。讓我們定義框:

每個框的大小由映射的RoI的大小和池化層的大小決定。我們使用了一個 3x3 的池化層,所以我們必須將映射的RoI ( 6.25x4.53)除以3。這樣我們就得到了一個高為 1.51 ,寬為 2.08 的方框(我在這里約簡以使它更容易)。現在我們可以把我們的方框放入映射的RoI中:

RoI分割成多個框

如果查看第一個框(左上角),可以注意到它覆蓋了6個不同的網格單元格。為了提取池化層的值,我們必須從池化層中采樣一些數據。為了對數據進行采樣,我們必須在盒子里創建 四個采樣點。

采樣點分布

你可以 通過方框的高度和寬度除以3 來計算每個點的位置。

在我們的例子中,我們計算第一個點(左上角)的坐標如下:

- X = X_box + (width/3) * 1 = 9.94

- Y = Y_box + (height/3) * 1 = 6.50

為了計算第二點(左下角),我們只需要改變Y:

- X = X_box + (width/3) * 1 = 9.94

- Y = Y_box + (height/3) * 2 = 7.01

現在,當我們有了所有的點我們可以應用雙線性插值對這個方框進行數據采樣。圖像處理中常用雙線性插值對顏色進行采樣,其方程如下:

雙線性差值方程

不要試圖理解這個方程,請看看它是如何工作的圖形解釋:

雙線性插值第一個點

當您從我們的方框中取出第一個點時,除非它已經被取走了,您將它與最鄰近的單元格連接(正好在中間)。在本例中,我們的點的坐標是**(9.44,6.50)**。單元格左上角最接近的中間位置是**(9.50,6.50)**(如果我們的點只比網格高0.01,那么它應該是(9.50,5.50))。然后我們必須選擇一個左下角的點,最近的是**(9.50,7.50)**遵循同樣的規則,我們選擇**(10.50,6.50)**和**(10.50,7.50)**作為右上角和右下角的點。在RoI上面,您可以看到整個計算過程,從而得到第一個點(0.14)的值。

雙線性插值的第二個點

這一次我們從:

- top-left: (10.50, 6.50)

- bottom-left: (10.50, 7.50)

- top-right: (11.50, 6.50)

- bottom-right: (11.50, 7.50)

你應該開始在這里看到一個模式:)。以下是其他要點:

雙線性插值的第三個點

- top-left: (9.50, 6.50)

- bottom-left: (9.50, 7.50)

- top-right: (10.50, 6.50)

- bottom-right: (10.50, 7.50)

雙線性插值的第四個點

- top-left: (10.50, 6.50)

- bottom-left: (10.50, 7.50)

- top-right: (11.50, 6.50)

- bottom-right: (11.50, 7.50)

現在我們已經計算了所有的點,並可以應用**Max Pooling**對他們(它可以是Avg池,如果你想):

第一個 Box Pooling

我不會給你們講所有的插值,因為這會花很長時間而且你們可能已經知道怎么做了。我將向你們展示整個過程是如何使用RoIAlign,對RoI進行池化的:

當然,這一過程適用於每一層,因此最終結果包含512個層(與feature map輸入相同)

請注意,即使我們沒有把采樣點放在feature map的所有單元格中,我們也通過雙線性插值從它們中提取數據。

在這種情況下,單元11x6, 11x7, 11x8, 11x9, 11x10, 13x6, 13x7, 13x8, 13x9, 13x10, 15x6, 15x7, 15x8, 15x9, 15x10將不會有任何點。如果你觀察第二個點的計算(第一個框),它仍然使用單元格11x6和11x7來進行雙線性插值,即使點在單元格10x6中。

如果您比較從RoIAlign和RoIPooling的數據丟失/數據獲取,您應該看到RoIAlign使用來自整個區域來池化數據:

比較RoIAlign(左)和RoIPooling(右)數據源。

- 綠色意味着用於池化的額外數據。

- 藍色(兩種陰影)表示池化是丟失數據。

RoIWarp — meet me in the middle

第三種池化數據的方法是通過 [*Instance-aware semantic segmentation via multi-task network cascades*](https://arxiv.org/pdf/1512.04412.pdf) 中引入的,它被稱為 RoIWarp。RoIWarp的想法和RoIAlign差不多,唯一的區別是 RoIWarp是將RoI量化到feature map上。

https://arxiv.org/pdf/1512.04412.pdf

RoI Warp

如果你看數據丟失/額外數據:

RoI Warp data lost/data gain

由於雙線性插值,我們只損失了一小部分。

RoIAlign 和 RoIWarp 是如何影響准確率的

如果我們看一下Mask R-CNN的文件,有一些重要的數字需要討論。第一個是使用stride 16在ResNet-50-C4上應用不同RoI層時的 平均精度 變化:

當使用RoIWarp的時候只有一個小的提升,但是使用RoIAlign在精度上給了我們一個顯著的提高。這種提升隨着步長(stride)的增加而增加:

其中 APbb 是檢測邊界看的平均精度。該測試是在ResNet-50-C5上使用stride 32完成的。

總結

當我們想要提高類似 R-CNN 的模型的准確性時,理解RoI池化是很重要的。2014年論文中提出的Fast R-CNN的標准方法和2018年論文中提出的Mask R-CNN的新方法有很大區別。這並不意味着這些方法只適用於特定的網絡,我們可以很容易地使用RoIAlign在Fast R-CNN和RoIPooling在Mask R-CNN,但你必須記住,RoIAlign給我們更好的平均精度。

我真的希望我的解釋能容易理解,因為我看過很多關於RoI 池化而不涉及計算的文章。在我看來,更直觀的方法總是更好的,特別是如果你不想花一整天的時間閱讀原始的論文來最終理解它的作用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM