1. 程式人生 > >非極大值抑制-NMS

非極大值抑制-NMS

圖片來源
原理如下:

非極大值抑制的方法是:在進行目標檢測時會產生很多候選區域,如圖所示產生了1~5號框,而這些候選區域一般會有好多重疊的部分,先對這些框的概率從大到小進行排序,然後按概率從大到小遍歷所有框:

(1)從最大概率1號矩形框開始,分別判斷剩下的框與該框的重疊度IOU(IOU的計算)是否大於某個設定的閾值;

(2)假設2、3與1的IOU超過閾值,那麼就扔掉2、3;並標記第一個矩形框1保留下來。

(3)從剩下的矩形框4、5中,選擇概率最大的4,然後判斷4、5的IOU,IOU大於一定的閾值,那麼就扔掉;並標記4為第二個矩形框。

就這樣一直重複,找到所有被保留下來的矩形框。

程式碼如下:

def non_max_suppression_fast(boxes, probs, overlap_thresh=0.9, max_boxes=300):
    # code used from here: http://www.pyimagesearch.com/2015/02/16/faster-non-maximum-suppression-python/
    # if there are no boxes, return an empty list
    if len(boxes) == 0:
        return []

    # 獲取框的座標
    x1 = boxes[:, 0
] y1 = boxes[:, 1] x2 = boxes[:, 2] y2 = boxes[:, 3] np.testing.assert_array_less(x1, x2) np.testing.assert_array_less(y1, y2) # if the bounding boxes integers, convert them to floats -- # this is important since we'll be doing a bunch of divisions if boxes.dtype.kind == "i"
: boxes = boxes.astype("float") # pick用來存放選取的框的索引 pick = [] # 計算框的面積 area = (x2 - x1) * (y2 - y1) # 排序,返回框的概率從小到大的索引值 idxs = np.argsort(probs) # 按框的概率從大到小迴圈遍歷 while len(idxs) > 0: # 獲取索引列表中的最後一個索引,並將索引值新增到pick列表中 last = len(idxs) - 1 i = idxs[last] pick.append(i) # 計算選取的框與剩下框的交集 xx1_int = np.maximum(x1[i], x1[idxs[:last]]) yy1_int = np.maximum(y1[i], y1[idxs[:last]]) xx2_int = np.minimum(x2[i], x2[idxs[:last]]) yy2_int = np.minimum(y2[i], y2[idxs[:last]]) ww_int = np.maximum(0, xx2_int - xx1_int) hh_int = np.maximum(0, yy2_int - yy1_int) area_int = ww_int * hh_int # 計算選取的框與剩下框的並集 area_union = area[i] + area[idxs[:last]] - area_int # 計算交併比 overlap = area_int/(area_union + 1e-6) # 刪除掉重疊率較高的和最後一個索引(因為最後一個已經加入到pick中) idxs = np.delete(idxs, np.concatenate(([last], np.where(overlap > overlap_thresh)[0]))) #如果選取的框的數量達到上限就停止 if len(pick) >= max_boxes: break # return only the bounding boxes that were picked using the integer data type boxes = boxes[pick].astype("int") probs = probs[pick] return boxes, probs