目標(biāo)檢測(cè)中的非最大值抑制算法
計(jì)算機(jī)視覺是人工智能的一個(gè)重要領(lǐng)域,它可以識(shí)別和理解圖像和場(chǎng)景。
它包括圖像識(shí)別、目標(biāo)檢測(cè)、圖像分割、圖像生成、圖像超分辨率等多個(gè)子領(lǐng)域。由于大量的實(shí)際用例,目標(biāo)檢測(cè)可能應(yīng)用地最廣。
目標(biāo)檢測(cè)
目標(biāo)檢測(cè)是指計(jì)算機(jī)系統(tǒng)定位圖像中的目標(biāo)并識(shí)別每個(gè)目標(biāo)的能力。目標(biāo)檢測(cè)已廣泛應(yīng)用于人臉檢測(cè)、車輛檢測(cè)、行人計(jì)數(shù)、安全系統(tǒng)和自動(dòng)駕駛汽車。
目標(biāo)檢測(cè)模型從端到端學(xué)習(xí)范式的發(fā)展中受益匪淺:建議、特征和分類器成為一個(gè)神經(jīng)網(wǎng)絡(luò),使一般目標(biāo)檢測(cè)的結(jié)果提高了兩倍[1]通常,所有現(xiàn)代目標(biāo)檢測(cè)模型都遵循三個(gè)步驟:
1. 建議窗口的搜索空間(通過滑動(dòng)窗口或使用建議的稀疏窗口)。
2. 使用分類器/回歸器對(duì)窗口評(píng)分。
3. 組合可能屬于同一對(duì)象的窗口。
最后一步稱為“非最大抑制”
邊界框
在目標(biāo)檢測(cè)中,我們通常使用邊界框來描述目標(biāo)在圖像中的空間位置。
邊界框是一個(gè)矩形,使用左上角和右下角坐標(biāo)繪制。另一種常用的邊界框表示法包含矩形的中心以及矩形的高度和寬度。
非最大值算法(NMS)
可以使用以下步驟解釋該算法:
輸入:邊界框列表以及類名稱和檢測(cè)到的每個(gè)對(duì)象的輸出概率。
1. 刪除輸出概率得分小于指定閾值的邊界框。
2. 按輸出概率的降序排列剩余邊界框的列表。
3. 遍歷已排序的邊界框列表,直到至少剩下一個(gè)元素。
4. 從列表中刪除第一個(gè)邊界框,并將其標(biāo)記為“當(dāng)前元素”。此外,檢查交并比(IOU)。如果IOU高于指定的閾值,則從列表中刪除該元素,并將當(dāng)前元素附加到“最終列表”中
5. 重復(fù)步驟3和4。
6. 返回“最終列表”
NMS算法試運(yùn)行
假設(shè)下面的圖像(圖1)包含兩條狗(左一條:Maya,右一條:Zoro),我們有一個(gè)對(duì)象檢測(cè)模型,可以區(qū)分圖像中的Maya和Zoro。
在使用上圖對(duì)我們的目標(biāo)檢測(cè)模型(無NMS)進(jìn)行推斷時(shí),我們將得到如圖2所示的輸出。在這里,我們可以看到,我們?cè)趩蝹(gè)對(duì)象上得到了多個(gè)具有各自概率分?jǐn)?shù)的邊界框。
我們的目標(biāo)是為對(duì)象選擇最合適的邊界框。換句話說,我們必須從概率為0.94、0.68和0.47的三個(gè)框中選擇一個(gè)Maya邊界框。同樣,我們也必須從概率為0.9和0.58的兩個(gè)邊界框中找到Zoro的最佳邊界框。
根據(jù)算法,我們將首先丟棄所有概率分?jǐn)?shù)低于指定閾值的邊界框。例如,如果我們將閾值設(shè)置為0.5,我們將丟棄Maya概率為0.47的邊界框。
此外,我們將找到概率得分最高的邊界框,并將其IOU與同類的所有其他邊界框進(jìn)行檢查。如果IOU高于閾值(表示相同的對(duì)象),則丟棄概率分?jǐn)?shù)較低的邊界框。
同樣,我們將對(duì)圖像中所有檢測(cè)到的對(duì)象執(zhí)行以下步驟。最終輸出如圖3所示。
代碼
首先,我們將初始化概率置信閾值和IOU閾值。例如,如果一個(gè)邊界框的概率低于概率置信閾值,那么我們將丟棄該邊界框。同樣,如果IOU分?jǐn)?shù)高于定義的閾值,我們不會(huì)考慮輸出概率低的邊界框。
import cv2
class NMS:
def __init__(self) -> None:
self.conf = 0.5
self.iou_threshsold = 0.4
下面截取的代碼中的IOU函數(shù)計(jì)算兩個(gè)區(qū)域的IOU。IOU是兩個(gè)區(qū)域的相交面積與兩個(gè)區(qū)域的并集的比率。在IOU函數(shù)中,bboxes1和bboxes2是一個(gè)包含以下四個(gè)元素的列表:
[ X(top-left), Y(top-left), X(bottom-right), Y(bottom-right) ]
def IOU(self, bboxes1, bboxes2):
bboxes1 = [int(i) for i in bboxes1]
bboxes2= [int(i) for i in bboxes2]
xA = max(bboxes1[0], bboxes2[0])
yA = max(bboxes1[1], bboxes2[1])
xB = min(bboxes1[2], bboxes2[2])
yB = min(bboxes1[3], bboxes2[3])
intersection_area = max(0, xB - xA + 1) * max(0, yB - yA + 1)
box1_area = (bboxes1[2] - bboxes1[0] + 1) * (bboxes1[3] - bboxes1[1] + 1)
box2_area = (bboxes2[2] - bboxes2[0] + 1) * (bboxes2[3] - bboxes2[1] + 1)
iou = intersection_area / float(box1_area + box2_area - intersection_area)
return iou
下面的代碼在圖像上繪制邊界框,并將概率分?jǐn)?shù)放在框的頂部。參數(shù)“images”是圖像對(duì)象,“bboxes_list”包含檢測(cè)到的對(duì)象的坐標(biāo)、類和概率輸出。
bboxes_list = [class, X(top-left), Y(top-left), X(bottom-right), Y(bottom-right), output_probability]
Sample values:
0 187 90 586 607 0.94
0 120 116 600 370 0.68
1 511 185 961 418 0.58
0 340 145 568 478 0.47
1 524 70 920 565 0.92
def draw_overlay(self, image, bboxes_list):
overlay_color = {
'0' : (0, 255, 0),
'1' : (255, 0, 0)
}
overlay_thickness = 3
font = cv2.FONT_HERSHEY_SIMPLEX
for coord in bboxes_list:
class_name = coord[0]
start_point = (int(coord[1]), int(coord[2]))
end_point = (int(coord[3]), int(coord[4]))
prob = float(coord[5])
text_start_point = (int(coord[1]), int(coord[2]) - 10)
image = cv2.rectangle(image, start_point, end_point,
overlay_color[class_name], overlay_thickness)
image = cv2.putText(image, str(prob), text_start_point,
font, 0.8, overlay_color[class_name], overlay_thickness - 1, cv2.LINE_AA)
cv2.imshow("im", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
以下函數(shù)是上述NMS算法的實(shí)現(xiàn)。此函數(shù)用于在應(yīng)用非最大值抑制算法后返回所需的邊界框。
def nms(self, image, bboxes_list):
req_bboxes, final_boxes = [], []
for coord in bboxes_list:
prob = float(coord[5])
if prob > self.conf:
req_bboxes.a(chǎn)ppend(coord)
# sorting the bounding boxes based on probability score
bboxes_sorted = sorted(req_bboxes, reverse=True, key=lambda x: x[5])
while len(bboxes_sorted) > 0:
# removing the best probability bounding box
box = bboxes_sorted.pop(0)
for b in bboxes_sorted:
# comparing with the same class
if box[0] == b[0]:
iou = self.IOU(box[1:-1], b[1:-1])
if iou >= self.iou_threshsold:
# if IOU is large then discard the box with lowest probability
bboxes_sorted.remove(b)
print(len(bboxes_sorted))
final_boxes.a(chǎn)ppend(box)
return final_boxes
以下是NMS類的驅(qū)動(dòng)程序代碼。我們首先讀取coordinates.txt獲取邊界框的坐標(biāo)和其他詳細(xì)信息;然后,我們應(yīng)用NMS算法來獲得所需的邊界框。
if __name__ == "__main__":
image = cv2.imread("zoraya.jpg")
with open("coordinates.txt", 'r') as f:
data = f.readlines()
data = [i[:-1].split(' ') for i in data]
obj = NMS()
obj.draw_overlay(image, data)
final_boxes = obj.nms(image, data)
obj.draw_overlay(image, final_boxes)
coordinates.txt
0 187 90 586 607 0.94
0 120 116 600 370 0.68
1 511 185 961 418 0.58
0 340 145 568 478 0.47
1 524 70 920 565 0.92
結(jié)論
本文概述了對(duì)非最大值抑制算法的需求以及python實(shí)現(xiàn)。此外,我們還使用一個(gè)圖像示例解釋了該算法。
原文標(biāo)題 : 目標(biāo)檢測(cè)中的非最大值抑制算法

發(fā)表評(píng)論
請(qǐng)輸入評(píng)論內(nèi)容...
請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字
您提交的評(píng)論過于頻繁,請(qǐng)輸入驗(yàn)證碼繼續(xù)
最新活動(dòng)更多
-
3月27日立即報(bào)名>> 【工程師系列】汽車電子技術(shù)在線大會(huì)
-
4月30日立即下載>> 【村田汽車】汽車E/E架構(gòu)革新中,新智能座艙挑戰(zhàn)的解決方案
-
5月15-17日立即預(yù)約>> 【線下巡回】2025年STM32峰會(huì)
-
即日-5.15立即報(bào)名>>> 【在線會(huì)議】安森美Hyperlux™ ID系列引領(lǐng)iToF技術(shù)革新
-
5月15日立即下載>> 【白皮書】精確和高效地表征3000V/20A功率器件應(yīng)用指南
-
5月16日立即參評(píng) >> 【評(píng)選啟動(dòng)】維科杯·OFweek 2025(第十屆)人工智能行業(yè)年度評(píng)選
推薦專題
- 1 UALink規(guī)范發(fā)布:挑戰(zhàn)英偉達(dá)AI統(tǒng)治的開始
- 2 北電數(shù)智主辦酒仙橋論壇,探索AI產(chǎn)業(yè)發(fā)展新路徑
- 3 “AI寒武紀(jì)”爆發(fā)至今,五類新物種登上歷史舞臺(tái)
- 4 降薪、加班、裁員三重暴擊,“AI四小龍”已折戟兩家
- 5 國(guó)產(chǎn)智駕迎戰(zhàn)特斯拉FSD,AI含量差幾何?
- 6 光計(jì)算迎來商業(yè)化突破,但落地仍需時(shí)間
- 7 東陽光:2024年扭虧、一季度凈利大增,液冷疊加具身智能打開成長(zhǎng)空間
- 8 地平線自動(dòng)駕駛方案解讀
- 9 封殺AI“照騙”,“淘寶們”終于不忍了?
- 10 優(yōu)必選:營(yíng)收大增主靠小件,虧損繼續(xù)又逢關(guān)稅,能否乘機(jī)器人東風(fēng)翻身?