7.13. 非極大值抑制¶
偵測網路通常會在同一個真實物體周圍產生數個彼此重疊的候選框:物體附近的每個錨點都會以相近的分數觸發,而後處理器會同時看到這些框。非極大值抑制(NMS)就是把這一群框收斂成單一框的步驟。
這個演算法很簡短:依分數對候選框排序,取分數最高的那一個,抑制所有與它重疊程度超過所選閾值的其他框,接著從剩下的框中取下一個最高分者,如此反覆。重疊度的衡量指標是交集比聯集(IoU)── 兩個框的共用面積除以兩者合併後的面積,數值介於 0(毫無重疊)與 1(完全相同的框)之間。每個隨附的後處理器上的 nms_threshold 建構子引數,就是超過這個門檻便將框視為某個已保留框之重複品的截斷值。
NMS 將一群重疊的偵測結果收斂為分數最高的那一個。¶
7.13.1. Soft-NMS¶
隨附的 ml.utils.NMS 類別實作了 Soft-NMS,這是一種改良做法,它會依照重疊程度的多寡,將重疊框的分數予以衰減,而不是直接捨棄該框。若衰減後的分數降到閾值以下,該框便被捨棄;否則它會以降低後的分數存活下來,並參與下一輪競爭。
nms_sigma 參數控制衰減的積極程度。當 nms_sigma 較小時(隨附的預設值為 0.1),衰減十分陡峭:重疊嚴重的框其分數會被壓到趨近於零,此時 Soft-NMS 退化為經典 NMS。當 nms_sigma 較大時,衰減較為平緩,不同物體的重疊框便較常存活下來;當同一類別的真實物體確實彼此重疊時(一群人臉、一叢手掌),這一點便很重要。
將 nms_sigma 設為 <= 0 會完全停用衰減:重疊的框會帶著原始分數通過,僅由分數閾值對其進行過濾。
7.13.2. 直接建構一個¶
每個隨附的後處理器都會在每次推論時建立一個全新的 NMS,將每個候選框加入其中,並在最後呼叫 get_bounding_boxes()。自訂後處理器也遵循相同的模式:
from ml.utils import NMS
iw = model.input_shape[0][2]
ih = model.input_shape[0][1]
nms = NMS(iw, ih, inputs[0].roi)
for box, score, class_idx in candidates:
nms.add_bounding_box(box.xmin, box.ymin,
box.xmax, box.ymax,
score, class_idx)
result = nms.get_bounding_boxes(threshold=nms_threshold,
sigma=nms_sigma)
建構子接收網路輸入的寬度與高度(以像素為單位),以及模型所執行對應的原始影像 ROI;add_bounding_box() 接收以該網路輸入像素空間表示的框座標,而 get_bounding_boxes() 則使用 ROI 將存活的框重新映射回影像座標。此重映射會自動處理 正規化拉伸 ── 用來把框投影回去的,正是預測器所看到的同一個 ROI ── 因此回傳的框已可直接繪製到擷取的影格上。
回傳結構是一個由各類別清單組成的清單,以傳遞給 add_bounding_box 的 label_index 作為索引。空的類別清單會被保留,使索引與模型的類別索引相符;enumerate(result) 可同時走訪各類別及其偵測結果。