object detection[NMS]


非極大抑制,是在對象檢測中用的較為頻繁的方法,當在一個對象區域,框出了很多框,那么如下圖:

上圖來自這里
目的就是為了在這些框中找到最適合的那個框.有以下幾種方式:

  • 1 nms
  • 2 soft-nms
  • 3 softer-nms

1. nms

主要就是通過迭代的形式,不斷的以最大得分的框去與其他框做iou操作,並過濾那些iou較大(即交集較大)的框
IOU也是一種Tanimoto測量方法[見模式識別,希臘,書609頁]
按照github上R-CNN的matlab代碼,改成py的,具體如下:


def iou(xminNp,yminNp,xmaxNp,ymaxNp,areas,lastInd,beforeInd,threshold):

    # 將lastInd指向的box,與之前的所有存活的box做比較,得到交集區域的坐標。
    # np.maximum([3,1,4,2],3) 等於 array([3,3,4,3])
    xminNpTmp = np.maximum(xminNp[lastInd], xminNp[beforeInd])
    yminNpTmp = np.maximum(yminNp[lastInd], yminNp[beforeInd])
    xmaxNpTmp = np.maximum(xmaxNp[lastInd], xmaxNp[beforeInd])
    ymaxNpTmp = np.maximum(ymaxNp[lastInd], ymaxNp[beforeInd])

    #計算lastInd指向的box,與存活box交集的,所有width,height
    w = np.maximum(0.0,xmaxNpTmp-xminNpTmp)
    h = np.maximum(0.0,ymaxNpTmp-yminNpTmp)
    #計算存活box與last指向box的交集面積
    # array([1,2,3,4]) * array([1,2,3,4]) 等於 array([1,4,9,16])
    inter = w*h
    iouValue = inter/(areas[beforeInd]+areas[lastInd]-inter)
    
    indexOutput = [item[0] for item in zip(beforeInd,iouValue) if item[1] <= threshold ]
    return indexOutput

def nms(boxes,threshold):
    '''
    boxes:n by 5的矩陣,n表示box個數,每一行分別為[xmin,ymin,xmax,ymax,score]
    '''
    assert isinstance(boxes,numpy.ndarray),'boxes must numpy object'
    assert boxes.shape[1] == 5,'the column Dimension should be 5'


    xminNp = boxes[:,0]
    yminNp = boxes[:,1]
    xmaxNp = boxes[:,2]
    ymaxNp = boxes[:,3]
    scores = boxes[:,4]
    #計算每個box的面積
    areas = (xmaxNp-xminNp)*(ymaxNp-yminNp)
    #對每個box的得分按升序排序
    scoresSorted = sorted(list(enumerate(scores)),key = lambda item:item[1])
    #提取排序后數據的原索引
    index = [ item[0] for item in scoresSorted ]
    pick = []
    while index:
        #將當前index中最后一個加入pick
        lastInd = index[-1]
        pick.append(lastInd)
        #計算最后一個box與之前所有box的iou
        index = iou(xminNp,yminNp,xmaxNp,ymaxNp,areas,lastInd,index[:-1],threshold)

    return pick



if __name__ == '__main__':

    nms(boxes,threshold)

2. soft-nms

import copy

def iou(xminNp,yminNp,xmaxNp,ymaxNp,scores,areas,remainInds,maxGlobalInd,Nt,sigma,threshold, method):

    remainInds = np.array(remainInds)
    # 將maxGlobalInd指向的box,與所有剩下的box做比較,得到交集區域的坐標。
    # np.maximum([3,1,4,2],3) 等於 array([3,3,4,3])
    xminNpTmp = np.maximum(xminNp[maxGlobalInd], xminNp[remainInds])
    yminNpTmp = np.maximum(yminNp[maxGlobalInd], yminNp[remainInds])
    xmaxNpTmp = np.maximum(xmaxNp[maxGlobalInd], xmaxNp[remainInds])
    ymaxNpTmp = np.maximum(ymaxNp[maxGlobalInd], ymaxNp[remainInds])

    # 計算box交集所有width,height
    w = np.maximum(0.0,xmaxNpTmp-xminNpTmp)
    h = np.maximum(0.0,ymaxNpTmp-yminNpTmp)
    
    #計算IOU
    # array([1,2,3,4]) * array([1,2,3,4]) 等於 array([1,4,9,16])
    inter = w*h
    iouValue = inter/(areas[remainInds]+areas[maxGlobalInd]-inter)
    
    # 依據不同的方法進行權值更新
    weight = np.ones_like(iouValue)
    if method == 'linear': # linear
        # 實現1 - iou
        weight = weight - iouValue
        weight[iouValue <= Nt] = 1
        
    elif method == 'gaussian':
        weight = np.exp(-(iouValue*iouValue)/sigma)
        
    else: # original NMS
        weight[iouValue > Nt] = 0
        
    # 更新scores
    scores[remainInds] = weight*scores[remainInds]
    
    # 刪除低於閾值的框
    remainInds = remainInds[scores[remainInds] > threshold]
    
    return remainInds.tolist(),scores

def soft_nms(boxes, threshold, sigma, Nt, method):
    ''' 
    boxes:n by 5的矩陣,n表示box個數,每一行分別為[xmin,ymin,xmax,ymax,score]
    
    # 1 - 先找到最大得分的box,放到結果集中;
    # 2 - 然后將最大得分的box與剩下的做對比,去更新剩下的得分權值
    # 3 - 刪除低於最小值的框;
    # 4 - 再找到剩下中最大的,循環
    # 5 - 返回結果集

    '''
    assert isinstance(boxes,numpy.ndarray),'boxes must numpy object'
    assert boxes.shape[1] == 5,'the column Dimension should be 5'
  
    pick = []
    copyBoxes = copy.deepcopy(boxes)
    xminNp = boxes[:,0]
    yminNp = boxes[:,1]
    xmaxNp = boxes[:,2]
    ymaxNp = boxes[:,3]
    scores = copy.deepcopy(boxes[:,4]) # 會不斷的更新其中的得分數值
    remainInds = list(range(len(scores))) # 會不斷的被分割成結果集,丟棄
    
    #計算每個box的面積
    areas = (xmaxNp-xminNp)*(ymaxNp-yminNp)    
    
    while remainInds:
    
        # 1 - 先找到最大得分的box,放到結果集中;
        maxLocalInd = np.argmax(scores[remainInds])
        maxGlobalInd = remainInds[maxLocalInd]
        pick.append(maxGlobalInd)
        
        # 2 - 丟棄最大值在索引中的位置
        remainInds.pop(maxLocalInd)
        if not remainInds: break

        # 3 - 更新scores,remainInds
        remainInds,scores = iou(xminNp,yminNp,xmaxNp,ymaxNp,scores,areas,remainInds,maxGlobalInd,Nt,sigma,threshold, method)
        
    return pick
    


if __name__ == '__main__':

    soft_nms(boxes, 0.001, 0.5, 0.3, 'linear')

3. softer-nms

參考資料:

  1. 非極大抑制
  2. [首次提出nms] Rosenfeld A, Thurston M. Edge and curve detection for visual scene analysis[J]. IEEE Transactions on computers, 1971 (5): 562-569.
  3. Theodoridis.S.,.Koutroumbas.K..Pattern.Recognition,.4ed,.AP,.2009
  4. [soft-nms] Bodla N, Singh B, Chellappa R, et al. Soft-nms—improving object detection with one line of code[C]//Computer Vision (ICCV), 2017 IEEE International Conference on. IEEE, 2017: 5562-5570. 【code
  5. [fitness nms] Tychsen-Smith L, Petersson L. Improving Object Localization with Fitness NMS and Bounded IoU Loss[J]. arXiv preprint arXiv:1711.00164, 2017.
  6. [learning NMS] J. H. Hosang, R. Benenson, and B. Schiele. Learning nonmaximum suppression. In CVPR, pages 6469–6477, 2017
  7. [softer-nms] He Y, Zhang X, Savvides M, et al. Softer-NMS: Rethinking Bounding Box Regression for Accurate Object Detection[J]. arXiv preprint arXiv:1809.08545, 2018.)


免責聲明!

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



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