爲什麼有nms?
通過滑動窗口得到一堆窗口包含窗口與窗口之間存在包含或大部分交叉的情況,這時需要用nms來選取那些置信度最高的窗口,同時抑制掉置信度低的。
nms例子:
如圖,爲了定位上圖中的一個車輛,通過圖像金字塔或者是滑動窗口,程序找出了一堆可能包含車輛的框,我們需要判斷哪些矩形框是沒用的。nms的方法是:
(1)先假設有6個矩形框,根據置信度進行排序,假設從小到大的順序排序,A,B,C,D,E,F.。
(2)從最大概率的矩形框開始,分別判斷A~E與F的重疊度(交併比iou),若B,D重疊度大於一個閾值,則認爲B,D與F框住的是同一個物體,這時扔掉B,D。
(3)再從剩下的A,C,E中繼續選擇置信度最大的,假設其爲E,然後判斷E與A,C的重合度,根據閾值捨棄相應的矩形框,並且標記E是我們保留下來第二個矩形框。
就這樣一直重複,找到所有被保留下的矩形框,即爲圖中的車輛數。
nms過程:
- 設定置信度閾值,
- 根據置信度,從大到小排列候選框列表
- 選取置信度最高的框A,添加到輸出列表,並將其從候選框列表中刪除。
- 計算A與候選框列表中所有框的iou,若大於一定的閾值,將框刪除。
- 從未處理的框集繼續尋找一個得分最高的框,重複2,3操作嗎,直到候選列表框爲空,返回輸出列表。
代碼如下:
import numpy as np
def iou(box,boxes,isMin = False):
## box = [x1,y1,x2,y2,c]
box_area = (box[2] - box[0]) * (box[3] -box[1])
boxes_area = (boxes[:,2] - boxes[:,0]) * (boxes[:,3] - boxes[:,1])
xx1 = np.maximum(box[0],boxes[:,0])
yy1 = np.maximum(box[1], boxes[:, 1])
xx2 = np.minimum(box[2], boxes[:, 2])
yy2 = np.minimum(box[3], boxes[:, 3])
w = np.maximum(0,xx2-xx1)
h = np.maximum(0,yy2-yy1)
inter = w*h
if isMin : ##最小面積
over = np.true_divide(inter,np.minimum(box_area,boxes_area))
else: ##交併比
over = np.true_divide(inter,(box_area+boxes_area-inter))
return over
def nms(boxes,thresh=0.3,isMin=False):
if boxes.shape[0] == 0:
return np.array([])
_boxes = boxes[(-boxes[:,4]).argsort()] ##按照置信度排序
keep = []
while _boxes.shape[0] > 1:
a_box = _boxes[0]
b_box = _boxes[1:]
keep.append(a_box)
index = np.where(iou(a_box , b_box, isMin) < thresh) ##函數的用法,
_boxes = b_box[index]
if _boxes.shape[0] > 0:
keep.append(_boxes[0]) ##返回的還是list
return np.stack(keep) ##把arry 和 list 組裝到一起
np.stack()函數
作用是把arry和list組裝到一起
import numpy as np
a = np.array([1,2,3])
b = np.array([4,5,6])
c = []
c.append(a)
c.append(b)
print(c)
print(np.stack(c))
##輸出結果
[array([1, 2, 3]), array([4, 5, 6])]
[[1 2 3]
[4 5 6]]
np.where() 函數:
- 當數組是一維數組時,返回的值是一維的索引
import numpy as np
a = np.arange(10)
print(a)
print(np.where(a>5))
##輸出結果:
[0 1 2 3 4 5 6 7 8 9]
(array([6, 7, 8, 9], dtype=int64),)
- 當數組是二維數組時,滿足條件的數組值返回的是值的位置索引,因此會有兩組索引數組來表示值的位置。
import numpy as np
a = np.arange(10).reshape(2,5)
print(a)
print(np.where(a>5))
##輸出結果
[[0 1 2 3 4]
[5 6 7 8 9]]
(array([1, 1, 1, 1], dtype=int64), array([1, 2, 3, 4], dtype=int64))
如上,返回的是滿足條件的值的行和列的索引。