前言
在剛剛過去的一個學期裏,基本水逆了一整個學期,這學期基本沒幹什麼活,就跟RCNN槓上了。首先是看論文,然後是網上找tensorflow寫好的源碼。但是,可惜的是網上給出的源碼基本上是RCNN的主要作者Ross Girshick大神的代碼,不同數據集換了下。因此爲了理解源碼,RCNN的處理過程,費勁去裝了個ubuntu和win10的雙系統並在Ubuntu上安裝caffe,這就花費了近2周的時間。快速研究完RCNN的caffe源碼之後,才轉過來手寫Fast RCNN的tensorflow版本的代碼,RCNN不是很好實現,SVM至今還沒怎麼看懂。接下來將會陸續更新RCNN->Fast RCNN->Faster RCNN系列的文章。在這篇文章中,主要講解RCNN與Fast RCNN中獲取圖片中物體真實目標檢測框的算法——選擇性搜索算法。
一、概述
在R-CNN中架構的第一步是要尋找推薦區域(Region Proposal),也就是找出可能的感興趣區域(Region Of Interest, ROI)。獲取推薦區域的方法有下三種,分爲:滑動窗口、規則塊和選擇性搜索。
第一種就是滑動窗口。滑動窗口本質上就是窮舉法,利用不同的尺度和長寬比把所有可能的大大小小的塊都窮舉出來,然後送去識別,識別出來概率大的就留下來。很明顯,這樣的方法複雜度太高,產生了很多的冗餘候選區域,在現實當中不可行。
第二種是規則塊。在窮舉法的基礎上進行了一些剪枝,只選用固定的大小和長寬比。但是對於普通的目標檢測來說,規則塊依然需要訪問很多的位置,複雜度高。
第三種是選擇性搜索。從機器學習的角度來說,前面的方法召回是不錯了,但是精度差強人意,所以問題的核心在於如何有效地去除冗餘候選區域。其實冗餘候選區域大多是發生了重疊,選擇性搜索利用這一點,自底向上合併相鄰的重疊區域,從而減少冗餘。
二、選擇性搜索
2.1 算法流程
選擇性搜索相關論文早在2012年發表於IJCV會議,論文名爲:Selective Search for Object Recognition。由於這篇論文不單單講解了選擇性搜索,因此,我對論文中選擇性搜索相關內容進行總結。選擇性搜索的算法流程如下:
從圖中可以看出,選擇性搜索輸入的是彩色圖像,輸出爲候選的目標邊界框集合。選擇性搜索主要流程主要分成以下幾個步驟:
- 首先利用論文《Efficient Graph- Based Image Segmentation》提出的felzenszwalb的分割算法獲取初始區域 ,並初始化相似性度量集合 。
- 之後遍歷整個區域集合,得到所有相鄰的區域對集合。
- 接着遍歷所有區域對集合,計算區域和區域的相似性度量,並把這個相似性度量加入中。
- 之後在不爲空的情況下,進行循環處理。在循環中首先找到相似性最大的對應的區域對 。然後將區域和區域進行合成記做 。之後從中刪除與區域相鄰的其他區域的相似性度量、與區域相鄰的區域的相似性度量。接着計算區域 與其相鄰的區域之間的相似性度量並加入中。最後也把區域加入中。
2.2 相似度度量
在論文中,相似性度量主要使用了顏色相似度、紋理相似度、大小相似度和吻合相似度。下面我們一一進行介紹。
2.2.1 顏色相似度
計算每個圖像每個顏色通道的25 bins的直方圖並將其進行L1-norm歸一化,這樣每個區域都可以得到一個75維的向量。兩個區域之間的每個通道的顏色相似度計算如下所示:
由於是歸一化後值,每一個顏色通道的直方圖累加和爲1.0,三個通道的累加和就爲3.0,如果區域和區域直方圖完全一樣,則此時顏色相似度最大爲3.0;如果不一樣,由於累加取兩個區域bin的最小值進行累加,當直方圖差距越大,累加的和就會越小,即顏色相似度越小。
在區域合併過程中使用需要對新區域的顏色直方圖的計算公式如下:
其中,代表區域的內像素大小。
2.2 紋理相似度
紋理相似度採用的是SIFT-Like特徵。具體做法是計算每個顏色通道的8個不同方向的方差的高斯微分(Gaussian Derivative),使用L1-norm歸一化獲取圖像每個顏色通道的每個方向的10 bins的直方圖,這樣就可以獲取到一個維的向量 ,區域之間紋理相似度計算方式和顏色相似度計算方式類似,計算公式如下:
合併之後新區域的紋理直方圖計算公式和顏色直方圖計算公式比較類似,計算公式如下所示:
2.3 大小相似度
加入僅僅是使用顏色和紋理特徵進行合併的話,這就會很容易造成合並後的大區域不斷吞併周圍的小區域。這樣做的後果就是多尺度只應用於局部,而不是全局的多尺度。因此比較合理的思路就是優先進行小區域之間的合併,即賦予小區域更大的權重,這就是大小相似度。大小相似度的計算公式如下:
其中爲原始圖像的像素個數。顯然,可以從上式看出,兩個區域越小,其相似度越大且越接近於1。即該大小相似度保證合併操作的尺度較爲均勻,避免一個大區域陸續“喫掉”其他小區域。
2.4 吻合相似度
相面介紹最後一個相似度——吻合相似度。如果區域 包含在區域內,我們首先應該合併;另一方面,如果區域很難與區域相接,他們之間會形成斷崖,不應該合併在一塊。這裏定義區域的吻合相似度主要是爲了衡量兩個區域是否更加“吻合”,其指標是合併後的區域的邊界框(Bounding Box)越小,其吻合度越高,即相似度越接近1。其計算方式如下:
其中,是圖像未被區域和區域所覆蓋區域的像素大小。那麼選擇性搜索的相似性度量計算公式如下所示:
其中 。在實際計算時我們將都取1。
三、選擇性搜索python實現
上面介紹了選擇性搜索算法流程以及相關細節,由於選擇性搜索算法已經有人利用python實現,並且已經開源。那麼,我們要做的就是利用Anaconda安裝相關源代碼後利用即可。在Anaconda的Prompt中輸入以下命令即可安裝選擇性搜索的python庫文件:
pip install selectivesearch
接下來我們,我們利用安裝好的選擇行搜索(selectivesearch)庫對圖片進行分割目標框。具體代碼如下:
# -*- coding: utf-8 -*-
from __future__ import (
division,
print_function,
)
import skimage.data
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import selectivesearch
def main():
# loading astronaut image
img = skimage.data.astronaut()
# perform selective search
img_lbl, regions = selectivesearch.selective_search(
img, scale=500, sigma=0.9, min_size=10)
candidates = set()
for r in regions:
# excluding same rectangle (with different segments)
if r['rect'] in candidates:
continue
# excluding regions smaller than 2000 pixels
if r['size'] < 2000:
continue
# distorted rects
x, y, w, h = r['rect']
if w / h > 1.2 or h / w > 1.2:
continue
candidates.add(r['rect'])
# draw rectangles on the original image
fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(6, 6))
ax.imshow(img)
for x, y, w, h in candidates:
print(x, y, w, h)
rect = mpatches.Rectangle(
(x, y), w, h, fill=False, edgecolor='red', linewidth=1)
ax.add_patch(rect)
plt.show()
if __name__ == "__main__":
main()
結果如下所示:
接下來對 selectivesearch.selective_search(im_orig, scale=1.0, sigma=0.8, min_size=50)函數進行解析。首先是函數參數說明:
- im_orig代表輸入圖像;
- scale代表輸出區域最大個數,默認值爲1;
- sigma代表felzenszwalb分割算法中高斯分佈的標準差,默認值爲0.8;
- min_size代表felzenszwalb分割算法中區域連通最小個數,默認值爲50;
接下來是selectivesearch.selective_search函數的返回值爲[r,g,b,(region)],實際操作時,我們通常得到的是[r,g,b]即RGB三個通道組成的原始圖像,以及區域字典數組。格式如下:
[
{
‘rect’: (left, top, width, height),
‘labels’: […],
‘size’: component_size
},
…
]
也就是說,"rect"返回的區域在原始圖像中左上頂點的x座標、右下頂點的y座標、和區域的寬度和高度。