【R-CNN目標檢測系列】三、IoU與非極大抑制

寫在前面

在上一篇博客:【計算機視覺——RCNN目標檢測系列】二、邊界框迴歸(Bounding-Box Regression)中我們主要講解了R-CNN中邊界框迴歸,接下來我們在這篇博客我們講解R-CNN中另外一個比較種重要的模塊——IoU與非極大抑制

在這篇博客中,我們將重點RCNN論文中另一個比較重要模塊——IoU與非極大抑制。IoU是描述兩個矩形框之間重合程度的指標,在RCNN中常用於衡量邊界框迴歸算法得到的預測目標框與真實目標框之間的重合程度。非極大抑制算法(Non-Maximum Suppression,NMS)則是用於去除大量重複的候選目標框。


一、IoU

首先來看下交併比(Intersection over Union,IoU)。假定兩個目標框分別爲 和 ,兩個矩形框的示意圖如下圖所示。那麼兩個目標框的交併比計算公式爲: IoU=ABABIoU=\frac{A \cap B}{A \cup B}。也就是IoU是兩個目標框交際與並集的比值。一般來說,在目標檢測中, 可視爲檢測結果良好正確,如果預測器和實際邊界框完美重疊,則 ,因爲交集就等於並集。但一般來說只要 ,那麼結果是可以接受。

python中實現IoU的代碼如下:

import numpy as np

def IoU(vertice1, vertice2):
     """
     這是計算兩個矩形區域的交併比函數,verticle格式爲:[xin,ymin,xmax,ymax]
     :param vertice1: 目標框1
     :param vertice2: 目標框1
     :return: 兩個矩形區域的交併比
     """
     # 計算區域交集的左上與右下座標
     lu = np.maximum(vertice1[0:2], vertice2[0:2])
     rd = np.minimum(vertice1[2:], vertice2[2:])
     # 計算區域交集的面積
     intersection = np.maximum(0.0, rd - lu)
     inter_square = intersection[0] * intersection[1]
     # 計算區域並集的面積
     square1 = (vertice1[2] - vertice1[0]) * (vertice1[3] - vertice1[1])
     square2 = (vertice2[2] - vertice2[0]) * (vertice2[3] - vertice2[1])
     union_square = np.maximum(square1 + square2 - inter_square, 1e-10)
     return np.clip(inter_square / union_square, 0.0, 1.0)

二、非極大抑制

接下來,我們重點介紹非極大抑制(Non-Maximum Suppression,NMS)。顧名思義,非極大抑制就是要抑制非極大值。也可以將非極大抑制理解成搜索局部最大值。
在此我們討論的非極大抑制主要特指用於目標檢測領域中搜索木分類概率最大的目標框的非極大抑制算法,而通用的非極大抑制請閱讀論文《Efficient Non-Maximum Suppression》。下面我們來看下非極大抑制的示意圖。

我們常會採用分類概率與IoU作爲指標來實現目標框的非極大抑制。具體算法流程如下:

  1. 首先我們按照目標框對應的分類概率進行排序,選取分類概率最大的目標框,記作current_box。
  2. 計算current_box與剩餘目標框之間的IoU
  3. 將IoU大於閾值的目標框捨棄
  4. 接下來在剩餘的目標框中再選出最大分類概率的目標框。按照上述流程一直循環直至條件結束。
    顯然從算法流程可以看出,非極大抑制是一種貪心算法。它的主要目的就是消除多餘重疊比例較高的目標框。在RCNN與Fast RCNN中,候選框主要是由選擇性搜索算法獲取的,爲了涵蓋每張圖片中對各個目標,選擇行搜索算法會返回將近2000個候選框,因此帶來大量重疊率叫高的目標框,因此在分類和定位任務借宿後,利用非極大抑制算法進行淘汰多餘重複候選框時一項十分重要的工作。

非極大抑制(NMS)算法的python實現如下:

import numpy as np  
  
def py_cpu_nms(dets, thresh):
    """
    這是NMS去除重複目標框的函數
    :param dets: 目標框數組,目標框的格式爲:[xin,ymin,xmax,ymax,score]
    :param thresh: 閾值
    :return: 不重複的目標框數組在元目標框數組中的下標數組
    """

    vertices = dets[:, 0:4]  # 目標框
    scores = dets[:, 4]  # bbox打分

    #areas = (x2 - x1 + 1) * (y2 - y1 + 1)
    # 打分從大到小排列,取index
    order = scores.argsort()[::-1]
    # keep爲最後保留的邊框
    keep = []
    while order.size > 0:
        # order[0]是當前分數最大的窗口,肯定保留
        i = order[0]
        keep.append(i)
        # 計算窗口i與其他所有窗口的交疊部分的面積
        ious = np.array([IoU(vertices[i], vertices[j]) for j in order[1:]])
        # inds爲所有與窗口i的iou值小於threshold值的窗口的index,其他窗口此次都被窗口i吸收
        inds = np.where(ious <= thresh)[0]
        # order裏面只保留與窗口i交疊面積小於threshold的那些窗口,由於ovr長度比order長度少1(不包		含i),所以inds+1對應到保留的窗口
        order = order[inds + 1]
    return keep
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章