選擇性搜索(Selective Search)


1 概述

  本文牽涉的概念是候選區域(Region Proposal ),用於物體檢測算法的輸入。無論是機器學習算法還是深度學習算法,候選區域都有用武之地。

2 物體檢測和物體識別

  物體識別是要分辨出圖片中有什么物體,輸入是圖片,輸出是類別標簽和概率。物體檢測算法不僅要檢測圖片中有什么物體,還要輸出物體的外框(x, y, width, height)來定位物體的位置。

物體檢測的核心就是物體識別。

  為了定位物體,我們需要選擇一些子區域並在子區域上運行物體識別算法。物體的位置就是物體識別算法返回最高概率的子區域內。 

  產生候選子區域的最直接的方法就是滑窗法,但是這種辦法效率比較低,一般使用‘候選區域’算法,而擇性搜索(Selective Search)就是最流行的候選區域產生算法之一(個人理解:這個最流行可能是針對論文那兩年說的,現在深度學習都是使用網絡產生候選區域,不用算法生成了)。

2.1 滑窗法

  在滑窗方案中,我們要使用一個小窗口遍歷搜索整張圖片,在每個位置上對滑窗內的圖片做物體識別算法。不僅要搜索不同的位置,還要遍歷不同的大小,工作量可想而知。問題還沒完,對於人臉和人體這種長寬比基本固定的物體還好,對於長寬不固定的物體,搜索起來簡直就是噩夢,計算量直接飆升。

2.2 候選區域(Region Proposal)算法

  滑窗法的問題可以使用候選區域產生算法解決。這些算法輸入整張圖片,然后輸出可能有物體的候選區域位置,這些候選區域可以有噪聲或者重疊,或者和物體的重合度不是很好,這都不要緊,只要這些區域里有一個和實際物體的位置足夠接近就行。因為不好的候選區域會被物體識別算法過濾掉。

  候選區域算法用分割不同區域的辦法來識別潛在的物體。在分割的時候,我們要合並那些在某些方面(如顏色、紋理)類似的小區域。相比滑窗法在不同位置和大小的窮舉,候選區域算法將像素分配到少數的分割區域中。所以最終候選區域算法產生的數量比滑窗法少的多,從而大大減少運行物體識別算法的次數。同時候選區域算法所選定的范圍天然兼顧了不同的大小和長寬比。

  候選區域算法比較重要的特征就是要有較高的召回率。我們要通過這種方法保證擁有物體的區域就在候選區域列表里。所以我們不介意有很多區域什么都有,這都沒關系,物體檢測算法會過濾掉他們,雖然會浪費一點時間。

目前已有不少成熟的后續區域產生算法:

  • Objectness
  • Constrained Parametric Min-Cuts for Automatic Object Segmentation
  • Category Independent Object Proposals
  • Randomized Prim
  • Selective Search

由於Selective Search又快召回率又高,這個方法是最常用的。說了這么多,終於牽出本文的主角了。

2.3 物體檢測之選擇性搜索(Selective Search)

  選擇性搜索算法用於為物體檢測算法提供候選區域,它速度快,召回率高。選擇性搜索算法需要先使用《Efficient Graph-Based Image Segmentation》論文里的方法產生初始的分割區域,然后使用相似度計算方法合並一些小的區域。 下列兩張圖分別是原圖和原始分割圖: 

  我們不能使用原始分割圖的區域作為候選區域,原因如下: 

  1. 大部分物體在原始分割圖里都被分為多個區域 
  2. 原始分割圖無法體現物體之間的遮擋和包含。

  如果我們試圖通過進一步合並相鄰的區域來解決第一個問題,我們最終會得到一個包含兩個對象的分段區域。我們不要需要完美的的分割區域,我們只想要和實際物體高度重合的區域就行了。選擇性搜索算法使用《Efficient Graph-Based Image Segmentation》論文里的方法產生初始的分割區域作為輸入,通過下面的步驟進行合並: 

  1. 首先將所有分割區域的外框加到候選區域列表中 
  2. 基於相似度合並一些區域 
  3. 將合並后的分割區域作為一個整體,跳到步驟1

  通過不停的迭代,候選區域列表中的區域越來越大。可以說,我們通過自底向下的方法創建了越來越大的候選區域。表示效果如下: 

相似度

  選擇性搜索算法如何計算兩個區域的像素度的呢? 主要是通過以下四個方面:顏色、紋理、大小和形狀交疊 ,最終的相似度是這四個值取不同的權重相加

效果

  opencv實現了選擇性搜索算法,可以給出上千個根據有物體的可能性降序排列的候選區域。下圖是畫出了前面200~250個候選區域的效果。一般來說。1000~1200個候選區域基本能勝任物體檢測的任務了。 
python代碼實現

#!/usr/bin/env python

import cv2

if __name__ == '__main__':

    # speed-up using multithreads
    cv2.setUseOptimized( True );
    cv2.setNumThreads( 4 );

    # read image
    im = cv2.imread( 'test.jpg' )
    # resize image
    newHeight = 200
    newWidth = int( im.shape[1] * 200 / im.shape[0] )
    im = cv2.resize( im, (newWidth, newHeight) )

    # create Selective Search Segmentation Object using default parameters
    ss = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()

    # set input image on which we will run segmentation
    ss.setBaseImage( im )

    if 1:
        # Switch to fast but low recall Selective Search method
        ss.switchToSelectiveSearchFast()
    else:
        # Switch to high recall but slow Selective Search method
        ss.switchToSelectiveSearchQuality()


    # run selective search segmentation on input image
    rects = ss.process()
    print( 'Total Number of Region Proposals: {}'.format( len( rects ) ) )

    # number of region proposals to show
    numShowRects = 100
    # increment to increase/decrease total number
    # of reason proposals to be shown
    increment = 50

    while True:
        # create a copy of original image
        imOut = im.copy()

        # itereate over all the region proposals
        for i, rect in enumerate( rects ):
            # draw rectangle for region proposal till numShowRects
            if (i < numShowRects):
                x, y, w, h = rect
                cv2.rectangle( imOut, (x, y), (x + w, y + h), (0, 255, 0), 1, cv2.LINE_AA )
            else:
                break

        # show output
        cv2.imshow( "Output", imOut )

        # record key press
        k = cv2.waitKey( 0 ) & 0xFF

        # m is pressed
        if k == 109:
            # increase total number of rectangles to show by increment
            numShowRects += increment
        # l is pressed
        elif k == 108 and numShowRects > increment:
            # decrease total number of rectangles to show by increment
            numShowRects -= increment
        # q is pressed
        elif k == 113:
            break
    # close image show window
    cv2.destroyAllWindows()
selective search

結果如下所示:

效果不是很好,現在都是用深度!!!

參考:yuanlulu

 


免責聲明!

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



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