【R-CNN目標檢測系列】一、選擇性搜索詳解

前言

在剛剛過去的一個學期裏,基本水逆了一整個學期,這學期基本沒幹什麼活,就跟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。由於這篇論文不單單講解了選擇性搜索,因此,我對論文中選擇性搜索相關內容進行總結。選擇性搜索的算法流程如下:
在這裏插入圖片描述
從圖中可以看出,選擇性搜索輸入的是彩色圖像,輸出爲候選的目標邊界框集合。選擇性搜索主要流程主要分成以下幾個步驟:

  1. 首先利用論文《Efficient Graph- Based Image Segmentation》提出的felzenszwalb的分割算法獲取初始區域RR ,並初始化相似性度量集合SS
  2. 之後遍歷整個區域集合,得到所有相鄰的區域對(ri,rj)\left(r_{i}, r_{j}\right)集合。
  3. 接着遍歷所有區域對(ri,rj)\left(r_{i}, r_{j}\right)集合,計算區域rir_{i}和區域rjr_{j}的相似性度量,並把這個相似性度量加入SS中。
  4. 之後在SS不爲空的情況下,進行循環處理。在循環中首先找到相似性最大的對應的區域對(ri,rj)\left(r_{i},r_{j}\right) 。然後將區域rir_{i}和區域rjr_{j}進行合成記做rtr_{t} 。之後從SS中刪除與區域rir_{i}相鄰的其他區域的相似性度量、與區域rjr_{j}相鄰的區域的相似性度量。接着計算區域 與其相鄰的區域之間的相似性度量並加入SS中。最後也把區域rtr_{t}加入RR中。

2.2 相似度度量

在論文中,相似性度量主要使用了顏色相似度、紋理相似度、大小相似度和吻合相似度。下面我們一一進行介紹。

2.2.1 顏色相似度

計算每個圖像每個顏色通道的25 bins的直方圖並將其進行L1-norm歸一化,這樣每個區域都可以得到一個75維的向量Ci={ci1,,cin}C_{i}=\left\{c_{i}^{1}, \cdots, c_{i}^{n}\right\}。兩個區域之間的每個通道的顏色相似度計算如下所示:
Scolour(ri,rj)=k=1nmin(cik,cjk) S_{\text {colour}}\left(r_{i}, r_{j}\right)=\sum_{k=1}^{n} \min \left(c_{i}^{k}, c_{j}^{k}\right)

由於{ci1,,cin}\left\{c_{i}^{1}, \cdots, c_{i}^{n}\right\}是歸一化後值,每一個顏色通道的直方圖累加和爲1.0,三個通道的累加和就爲3.0,如果區域rir_{i}和區域rjr_{j}直方圖完全一樣,則此時顏色相似度最大爲3.0;如果不一樣,由於累加取兩個區域bin的最小值進行累加,當直方圖差距越大,累加的和就會越小,即顏色相似度越小。

在區域合併過程中使用需要對新區域rtr_{t}的顏色直方圖CtC_{t}的計算公式如下:
Ct=size(ri)×Ci+size(rj)×Cjsize(ri)+size(rj) C_{t}=\frac{\operatorname{size}\left(r_{i}\right) \times C_{i}+\operatorname{size}\left(r_{j}\right) \times C_{j}}{\operatorname{size}\left(r_{i}\right)+\operatorname{size}\left(r_{j}\right)}

其中,size(ri)\operatorname{siz} e\left(r_{i}\right)代表區域rir_{i}的內像素大小。

2.2 紋理相似度

紋理相似度採用的是SIFT-Like特徵。具體做法是計算每個顏色通道的8個不同方向的方差σ=1\sigma=1的高斯微分(Gaussian Derivative),使用L1-norm歸一化獲取圖像每個顏色通道的每個方向的10 bins的直方圖,這樣就可以獲取到一個10×8×3=24010 \times 8 \times 3=240維的向量Ti={ti1,,tin}T_{i}=\left\{t_{i}^{1}, \cdots, t_{i}^{n}\right\} ,區域之間紋理相似度計算方式和顏色相似度計算方式類似,計算公式如下:
Stexture(ri,rj)=k=1nmin(tik,tjk) S_{\text {texture}}\left(r_{i}, r_{j}\right)=\sum_{k=1}^{n} \min \left(t_{i}^{k}, t_{j}^{k}\right)

合併之後新區域rtr_{t}的紋理直方圖TiT_{i}計算公式和顏色直方圖計算公式比較類似,計算公式如下所示:
Tt=size(ri)×Ti+size(rj)×Tjsize(ri)+size(rj) T_{t}=\frac{\operatorname{size}\left(r_{i}\right) \times T_{i}+\operatorname{siz} e\left(r_{j}\right) \times T_{j}}{\operatorname{size}\left(r_{i}\right)+\operatorname{size}\left(r_{j}\right)}

2.3 大小相似度

加入僅僅是使用顏色和紋理特徵進行合併的話,這就會很容易造成合並後的大區域不斷吞併周圍的小區域。這樣做的後果就是多尺度只應用於局部,而不是全局的多尺度。因此比較合理的思路就是優先進行小區域之間的合併,即賦予小區域更大的權重,這就是大小相似度。大小相似度的計算公式如下:
Ssize(ri,rj)=1size(ri)+size(rj)size(im) S_{\text {size}}\left(r_{i}, r_{j}\right)=1-\frac{\operatorname{size}\left(r_{i}\right)+\operatorname{siz} e\left(r_{j}\right)}{\operatorname{size}(i m)}

其中size(im)size(im)爲原始圖像的像素個數。顯然,可以從上式看出,兩個區域越小,其相似度越大且越接近於1。即該大小相似度保證合併操作的尺度較爲均勻,避免一個大區域陸續“喫掉”其他小區域。

2.4 吻合相似度

相面介紹最後一個相似度——吻合相似度。如果區域 rir_{i}包含在區域rjr_{j}內,我們首先應該合併;另一方面,如果區域rir_{i}很難與區域rjr_{j}相接,他們之間會形成斷崖,不應該合併在一塊。這裏定義區域的吻合相似度主要是爲了衡量兩個區域是否更加“吻合”,其指標是合併後的區域的邊界框(Bounding Box)越小,其吻合度越高,即相似度越接近1。其計算方式如下:
Sfill(ri,rj)=1size(BBij)size(ri)size(rj)size(im) S_{f i l l}\left(r_{i}, r_{j}\right)=1-\frac{\operatorname{size}\left(B B_{i j}\right)-\operatorname{size}\left(r_{i}\right)-\operatorname{siz} e\left(r_{j}\right)}{\operatorname{size}(i m)}

其中,size(BBij)\operatorname{size}\left(B B_{i j}\right)是圖像未被區域rir_{i}和區域rjr_{j}所覆蓋區域的像素大小。那麼選擇性搜索的相似性度量計算公式如下所示:
S(ri,rj)=a1Scolour(ri,rj)+a2Stexture(ri,rj)+a3Ssize(ri,rj)+a2Sfill(ri,rj) S\left(r_{i}, r_{j}\right)=a_{1} S_{\text {colour}}\left(r_{i}, r_{j}\right)+a_{2} S_{\text {texture}}\left(r_{i}, r_{j}\right)+a_{3} S_{\text {size}}\left(r_{i}, r_{j}\right)+a_{2} S_{\text {fill}}\left(r_{i}, r_{j}\right)

其中ai{0,1}a_{i} \in\{0,1\} 。在實際計算時我們將aia_{i}都取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)函數進行解析。首先是函數參數說明:

  1. im_orig代表輸入圖像;
  2. scale代表輸出區域最大個數,默認值爲1;
  3. sigma代表felzenszwalb分割算法中高斯分佈的標準差,默認值爲0.8;
  4. 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座標、和區域的寬度和高度。

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