非极大值抑制算法
非極大值抑制算法
簡介
非極大值抑制算法(Non-Maximum Suppression,NMS),首次在論文 Efficient non-maximum suppression 被提出,多年之后被廣泛用于目標檢測領域,用于消除多余的檢測框。
NMS 介紹
目標檢測算法(主流的有 RCNN 系、YOLO 系、SSD 等)在進行目標檢測任務時,可能對同一目標有多次預測得到不同的檢測框,NMS 算法則可以確保對每個對象只得到一個檢測,簡單來說就是“消除冗余檢測”。
IOU
交并比(Intersection over Union,IOU)是目標檢測領域常用的一個指標,用于衡量兩個邊界框的重疊程度,顧名思義利用兩個邊界框的交集面積除以兩個邊界框的并集面積即可。當 IOU 為 0 的時候表示無重疊,為 1 的時候表示完全重疊,在 0 到 1 之間的數值表示重疊程度。
NMS 算法流程
NMS 的工作流程如下,其實非常簡單粗暴:
上圖中,顯然,左側目標只保留0.95的置信度的檢測結果,右側目標只保留0.9的檢測結果。
此外,還有一個問題就是當目標為很多類別時(上圖只有一個行人類別),按照吳恩達的思路這里應該不引入其他變量,簡單來說就是一個類別一個類別地進行NMS。
代碼實現
利用Python實現NMS是非常簡單的,有興趣可以查看Fast R-CNN的實現源碼,下文代碼參考其完成(代碼中沒有進行第一步的按置信度過濾)。
import numpy as np import cv2from draw_bbox import draw_boxdef nms(bboxes, scores, iou_thresh):""":param bboxes: 檢測框列表:param scores: 置信度列表:param iou_thresh: IOU閾值:return:"""x1 = bboxes[:, 0]y1 = bboxes[:, 1]x2 = bboxes[:, 2]y2 = bboxes[:, 3]areas = (y2 - y1) * (x2 - x1)# 結果列表result = []index = scores.argsort()[::-1] # 對檢測框按照置信度進行從高到低的排序,并獲取索引# 下面的操作為了安全,都是對索引處理while index.size > 0:# 當檢測框不為空一直循環i = index[0]result.append(i) # 將置信度最高的加入結果列表# 計算其他邊界框與該邊界框的IOUx11 = np.maximum(x1[i], x1[index[1:]])y11 = np.maximum(y1[i], y1[index[1:]])x22 = np.minimum(x2[i], x2[index[1:]])y22 = np.minimum(y2[i], y2[index[1:]])w = np.maximum(0, x22 - x11 + 1)h = np.maximum(0, y22 - y11 + 1)overlaps = w * hious = overlaps / (areas[i] + areas[index[1:]] - overlaps)# 只保留滿足IOU閾值的索引idx = np.where(ious <= iou_thresh)[0]index = index[idx + 1] # 處理剩余的邊框bboxes, scores = bboxes[result], scores[result]return bboxes, scoresif __name__ == '__main__':raw_img = cv2.imread('test.png')# 這里為了編碼方便,將檢測的結果直接作為變量bboxes = [[183, 625, 269, 865], [197, 603, 296, 853], [190, 579, 295, 864], [537, 507, 618, 713], [535, 523, 606, 687]]confidences = [0.7, 0.9, 0.95, 0.9, 0.6]# 未經過nms的原始檢測結果img = raw_img.copy()for x, y in zip(bboxes, confidences):img = draw_box(img, x, y)cv2.imwrite("../assets/raw_img.png", img)# 進行nms處理bboxes, scores = nms(np.array(bboxes), np.array(confidences), 0.5)img = raw_img.copy()for x, y in zip(list(bboxes), list(scores)):img = draw_box(img, x, y)cv2.imwrite("../assets/img_nms.png", img)在上一節的檢測結果基礎上進行NMS后的檢測結果如下圖,可以看到,成功過濾掉很多冗余的檢測。
補充說明
本文主要講解并實現了目標檢測算法中常用的NMS算法,該算法對檢測結果進行篩選上有著姣好的效果,本文理論部分參考吳恩達的深度學習課程,設計的源碼可以在我的Github找到,歡迎star或者fork。
總結
- 上一篇: WRN详述
- 下一篇: Zotero参考文献管理