非極大值抑制演算法(non-maximum suppression,nms),首次在** efficient non-maximum suppression 被提出,多年之後被廣泛用於目標檢測領域,用於消除多餘的檢測框。
目標檢測演算法(主流的有 rcnn 系、yolo 系、ssd 等)在進行目標檢測任務時,可能對同一目標有多次**得到不同的檢測框,nms 演算法則可以確保對每個物件只得到乙個檢測,簡單來說就是「消除冗餘檢測」。
交並比(intersection over union,iou)是目標檢測領域常用的乙個指標,用於衡量兩個邊界框的重疊程度,顧名思義利用兩個邊界框的交集面積除以兩個邊界框的並集面積即可。當 iou 為 0 的時候表示無重疊,為 1 的時候表示完全重疊,在 0 到 1 之間的數值表示重疊程度。
nms 的工作流程如下,其實非常簡單粗暴:
按照一定的置信度閾值,刪除置信度過低的檢測框,對檢測框進行初步篩選,如設定為0.5,上圖中沒有檢測框會被初步過濾掉;
從當前邊界框列表中選取置信度最大的邊界框,加入結果列表,同時計算其他邊界框與它的iou,若iou超過設定的iou閾值,則刪除該檢測框;
重複上面的第二步,直到邊界框列表為空,得到結果列表。
上圖中,顯然,左側目標只保留0.95的置信度的檢測結果,右側目標只保留0.9的檢測結果。
此外,還有乙個問題就是當目標為很多類別時(上圖只有乙個行人類別),按照吳恩達的思路這裡應該不引入其他變數,簡單來說就是乙個類別乙個類別地進行nms。
利用python實現nms是非常簡單的,有興趣可以檢視fast r-cnn的實現原始碼,下文**參考其完成(**中沒有進行第一步的按置信度過濾)。
import numpy as np
import cv2
from draw_bbox import draw_box
defnms
(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]
# 將置信度最高的加入結果列表
# 計算其他邊界框與該邊界框的iou
x11 = 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 * h
ious = 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, scores
if __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。
非極大值抑制
nms non maximum suppression 中文名非極大值抑制,在很多計算機視覺任務中都有廣泛應用,如 邊緣檢測 目標檢測等。這裡主要以人臉檢測中的應用為例,來說明nms,並給出matlab和c 示例程式。人臉檢測的一些概念 1 絕大部分人臉檢測器的核心是分類器,即給定乙個尺寸固定,分類...
非極大值抑制
參考 思想 1.將每乙個檢測框的得分值排序,得到得分值最大的檢測框,將該檢測框記錄下來 2.然後其他計算所有的檢測框與該框的iou,將iou大於閾值的檢測框去除,iou小於閾值的認為是不同的目標,則保留 3.對剩下的檢測框繼續做上述的處理 import numpy as np def py cpu ...
非極大值抑制
在進行目標檢測的時候,當多個方框都 到同乙個目標的時候,我們需要去除iou小的方框,原始碼如下 def nms boxes,threshold,method union param boxes n,9 x1,y1,x2,y2,score,offset x1,offset y1,offset x2,o...