非極大抑制,是在對象檢測中用的較為頻繁的方法,當在一個對象區域,框出了很多框,那么如下圖:
上圖來自這里
目的就是為了在這些框中找到最適合的那個框.有以下幾種方式:
- 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
參考資料:
- 非極大抑制
- [首次提出nms] Rosenfeld A, Thurston M. Edge and curve detection for visual scene analysis[J]. IEEE Transactions on computers, 1971 (5): 562-569.
- Theodoridis.S.,.Koutroumbas.K..Pattern.Recognition,.4ed,.AP,.2009
- [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】
- [fitness nms] Tychsen-Smith L, Petersson L. Improving Object Localization with Fitness NMS and Bounded IoU Loss[J]. arXiv preprint arXiv:1711.00164, 2017.
- [learning NMS] J. H. Hosang, R. Benenson, and B. Schiele. Learning nonmaximum suppression. In CVPR, pages 6469–6477, 2017
- [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.)