訂閱
糾錯
加入自媒體

目標檢測中的非最大值抑制算法

計算機視覺人工智能的一個重要領域,它可以識別和理解圖像和場景。

它包括圖像識別、目標檢測、圖像分割、圖像生成、圖像超分辨率等多個子領域。由于大量的實際用例,目標檢測可能應用地最廣。

目標檢測

目標檢測是指計算機系統(tǒng)定位圖像中的目標并識別每個目標的能力。目標檢測已廣泛應用于人臉檢測、車輛檢測、行人計數(shù)、安全系統(tǒng)和自動駕駛汽車。

目標檢測模型從端到端學習范式的發(fā)展中受益匪淺:建議、特征和分類器成為一個神經(jīng)網(wǎng)絡,使一般目標檢測的結果提高了兩倍[1]通常,所有現(xiàn)代目標檢測模型都遵循三個步驟:

1. 建議窗口的搜索空間(通過滑動窗口或使用建議的稀疏窗口)。

2. 使用分類器/回歸器對窗口評分。

3. 組合可能屬于同一對象的窗口。

最后一步稱為“非最大抑制”

邊界框

在目標檢測中,我們通常使用邊界框來描述目標在圖像中的空間位置。

邊界框是一個矩形,使用左上角和右下角坐標繪制。另一種常用的邊界框表示法包含矩形的中心以及矩形的高度和寬度。

非最大值算法(NMS)

可以使用以下步驟解釋該算法:

輸入:邊界框列表以及類名稱和檢測到的每個對象的輸出概率。

1. 刪除輸出概率得分小于指定閾值的邊界框。

2. 按輸出概率的降序排列剩余邊界框的列表。

3. 遍歷已排序的邊界框列表,直到至少剩下一個元素。

4. 從列表中刪除第一個邊界框,并將其標記為“當前元素”。此外,檢查交并比(IOU)。如果IOU高于指定的閾值,則從列表中刪除該元素,并將當前元素附加到“最終列表”中

5. 重復步驟3和4。

6. 返回“最終列表”

NMS算法試運行

假設下面的圖像(圖1)包含兩條狗(左一條:Maya,右一條:Zoro),我們有一個對象檢測模型,可以區(qū)分圖像中的Maya和Zoro。

在使用上圖對我們的目標檢測模型(無NMS)進行推斷時,我們將得到如圖2所示的輸出。在這里,我們可以看到,我們在單個對象上得到了多個具有各自概率分數(shù)的邊界框。

我們的目標是為對象選擇最合適的邊界框。換句話說,我們必須從概率為0.94、0.68和0.47的三個框中選擇一個Maya邊界框。同樣,我們也必須從概率為0.9和0.58的兩個邊界框中找到Zoro的最佳邊界框。

根據(jù)算法,我們將首先丟棄所有概率分數(shù)低于指定閾值的邊界框。例如,如果我們將閾值設置為0.5,我們將丟棄Maya概率為0.47的邊界框。

此外,我們將找到概率得分最高的邊界框,并將其IOU與同類的所有其他邊界框進行檢查。如果IOU高于閾值(表示相同的對象),則丟棄概率分數(shù)較低的邊界框。

同樣,我們將對圖像中所有檢測到的對象執(zhí)行以下步驟。最終輸出如圖3所示。

代碼

首先,我們將初始化概率置信閾值和IOU閾值。例如,如果一個邊界框的概率低于概率置信閾值,那么我們將丟棄該邊界框。同樣,如果IOU分數(shù)高于定義的閾值,我們不會考慮輸出概率低的邊界框。

import cv2
     class NMS:
            def __init__(self) -> None:
            self.conf = 0.5
            self.iou_threshsold = 0.4

下面截取的代碼中的IOU函數(shù)計算兩個區(qū)域的IOU。IOU是兩個區(qū)域的相交面積與兩個區(qū)域的并集的比率。在IOU函數(shù)中,bboxes1和bboxes2是一個包含以下四個元素的列表:

[ 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

下面的代碼在圖像上繪制邊界框,并將概率分數(shù)放在框的頂部。參數(shù)“images”是圖像對象,“bboxes_list”包含檢測到的對象的坐標、類和概率輸出。

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算法的實現(xiàn)。此函數(shù)用于在應用非最大值抑制算法后返回所需的邊界框。

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類的驅動程序代碼。我們首先讀取coordinates.txt獲取邊界框的坐標和其他詳細信息;然后,我們應用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

結論

本文概述了對非最大值抑制算法的需求以及python實現(xiàn)。此外,我們還使用一個圖像示例解釋了該算法。

       原文標題 : 目標檢測中的非最大值抑制算法

聲明: 本文由入駐維科號的作者撰寫,觀點僅代表作者本人,不代表OFweek立場。如有侵權或其他問題,請聯(lián)系舉報。

發(fā)表評論

0條評論,0人參與

請輸入評論內(nèi)容...

請輸入評論/評論長度6~500個字

您提交的評論過于頻繁,請輸入驗證碼繼續(xù)

暫無評論

暫無評論

    掃碼關注公眾號
    OFweek人工智能網(wǎng)
    獲取更多精彩內(nèi)容
    文章糾錯
    x
    *文字標題:
    *糾錯內(nèi)容:
    聯(lián)系郵箱:
    *驗 證 碼:

    粵公網(wǎng)安備 44030502002758號