Python MTCNN(人臉檢測)項目附代碼講解(2)-NMS/IOU工具介紹

對於MTCNN中使用的原理工具,這一節分為代碼的三部分(NMS,IOU,框的改變),對於圖像金字塔、三個網絡(R、P、ONET)和數據集的處理部分放在模型搭建中來講,要不突然講起來感覺太虛空,沒辦法很好的理解,當然也可以先去讀下論文,瞭解下,那個也是不錯的。

做MTCNN前。先看看我們會使用到什麼工具~

IOU(交併比)

本來想先寫NMS的,寫著寫著突然發現還是需要先講解下IOU會好一點,這樣理解起來也比較順,那就先說IOU這個概念。

Python MTCNN(人臉檢測)項目附代碼講解(2)-NMS/IOU工具介紹

交併比這個概念就是我們經過網絡訓練生成了一個框,如下圖中的紅色框,而我們在數據集中早就標記好了一個真實框,這個就是我之前說的處理數據集時必不可少的一步:標記。因為只有這樣我們才能更好的訓練,然後驗證。

Python MTCNN(人臉檢測)項目附代碼講解(2)-NMS/IOU工具介紹

好,我們得到了預測框,那麼這個怎麼衡量框的準不準呢?

也就是如何給網絡得到的這一個框一個分數呢?我們可以使用交併比來估計,就是說使用兩個框的交集的面積除以並集的面積(這個是最常用的),當然交併比有三種計算方法了(如下圖)。

Python MTCNN(人臉檢測)項目附代碼講解(2)-NMS/IOU工具介紹

下面就是如何計算交併比的公式,

Python MTCNN(人臉檢測)項目附代碼講解(2)-NMS/IOU工具介紹

對於這一個分數計算,其實你可以試著算算,如何兩個框是一樣的,那比值就是1,也就是說分數為1,其實也可以理解成置信度(也就是概率),如果兩個框沒有在一起,也就是0,那麼這個框就不是訓練中框到人臉的那個框。

如果你理解了這個概念其實就差不多了,這個基本上就是IOU的概念,那麼對於我在圖中說的O_Net使用交集面積除以最小面積的計算方法,這個到後面使用到的時候再指明。

代碼如下(其實這一塊,沒有辦法很詳細的講解,有問題可以在下面留言,看到了我會回覆):

import numpy as np
# 定義IOU(交併比)計算公式, 傳入真實框和其他移動後的框
def iou(box, boxes, isMin=False):
# 計算原始真實框的面積
box_area = (box[2] - box[0]) * (box[3] - box[1])
# 計算移動後的框的面積,這裡計算的是矩陣
boxes_area = (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1])
# 找到兩個框的內部點計算交集
x1 = np.maximum(box[0], boxes[:, 0])
y1 = np.maximum(box[1], boxes[:, 1])
x2 = np.minimum(box[2], boxes[:, 2])
y2 = np.minimum(box[3], boxes[:, 3])
# 然後找到交集區域的長和寬,有的框沒有交集那麼相差可能為負,所以需要使用0來規整數據
w = np.maximum(0, x2 - x1)
h = np.maximum(0, y2 - y1)
# 計算交集的面積
inter_area = w * h
# 兩種計算方法:1是交併比等於交集除以並集,2是交集除以最小的面積
if isMin:
ovr_area = np.true_divide(inter_area, np.minimum(boxes_area, box_area))
else:
ovr_area = np.true_divide(inter_area, (boxes_area + box_area - inter_area))
# 返回交併比,也就是IOU
return ovr_area

非極大值抑制(NMS)的實現

Python MTCNN(人臉檢測)項目附代碼講解(2)-NMS/IOU工具介紹

非極大值抑制(NMS)顧名思義就是抑制不是極大值的元素,搜索局部的極大值

檢測中,滑動窗口經提取特徵,經分類器分類識別後,每個窗口都會得到一個分數

但是滑動窗口會導致很多窗口與其他窗口存在包含或者大部分交叉的情況。

這時就需要用到NMS來選取那些鄰域裡分數最高(是人臉的概率最大),並且抑制那些分數低的窗口。

這個就是我們通過網絡進行人臉座標點回歸(如何實現人臉座標點的迴歸,這個在數據集時會說明)時,在進行人臉檢測時出現的框很多,但是我們不可能每個都保留,那麼這個非極大值抑制就是來幫我們確認留下哪個框。

看上面的圖(當然不知道能不能看清),以女主的臉上的框而言,當我們經過網絡訓練後,可能出現一個帶有分數(也就是置信度,你可以理解為人臉概率)的框,我們會設定一個閾值來得到這些框,比如大於0.7,那麼經過網絡大於0.7的框的都會被留在人臉附近(這個就是IOU的分數值),這就回到了如何保留最大的分數框的問題,因為我們最後的目的就是能保留唯一的一個框,不太可能給一個人臉上框好幾個框,那個不符合我們的預期。

Python MTCNN(人臉檢測)項目附代碼講解(2)-NMS/IOU工具介紹

這裡我們就使用到可NMS,意思就如上面講的那樣,先選擇這一堆框中最大的,然後去除和這個框交併比大於一定比例的,然後保留下來小於一定比例的,意思就是,比如女主臉上的框,因為都是框到人臉了,那麼這每個框的IOU其實都是蠻大的,所以我們只取裡面最大的,就得到了下面女主臉上的框

Python MTCNN(人臉檢測)項目附代碼講解(2)-NMS/IOU工具介紹

但是因為有兩個人臉,又不能取圖中最大分數的框,那樣就只剩一個框了,所以我們設定如果其他框和這個最大值分數的框的IOU小於0.3(這個值是自己定義的),那麼先留下,然後再取出剩下框最大值,再求IOU,然後留下男主的框

Python MTCNN(人臉檢測)項目附代碼講解(2)-NMS/IOU工具介紹

這個流程就是:

網絡迴歸生成人臉框 --取出分數最大的框保存在一個列表中--拿剩下其他的框和這個最大的框求IOU,留下IOU小於設定閾值的框--然後再對保留的框取出最大分數的框保存在剛才的列表中--再拿剩下其他的框和這個最大的框求IOU,留下IOU小於設定閾值的框(依次循環,直至結束)

NMS代碼:

# 定義NMS,篩選符合標準的線框 

def nms(boxes, thresh=0.3, isMin=False):
# 如果照片裡面沒有框數據了,就返回空列表
if boxes.shape[0] == 0:
return np.array([])
# 以計算出的iou從大到小排列
_boxes = boxes[(-boxes[:, 4]).argsort()]
r_boxes = []
# 如果框的有1個以上就進行對比
while _boxes.shape[0] > 1:
# 取出最大的框
a_box = _boxes[0]
# 剩下的框分別和之前的進行比對
b_boxes = _boxes[1:]
# 先將最大iou的框添加到保留框的列表中
r_boxes.append(a_box)
# 保留iou 小於0.3的,說明這個框和目前比對的不是同一個框,去除交集較多的框
index = np.where(iou(a_box, b_boxes, isMin) < thresh)
_boxes = b_boxes[index]
# _boxes = b_boxes[iou(a_box, b_boxes, isMin) < thresh]
# 如果保留的框數量大於0,則添加iou最大的那個框
if _boxes.shape[0] > 0:
r_boxes.append(_boxes[0])
# 將這些框堆疊在一起
return np.stack(r_boxes)

轉換框為正方形convert_to_square

# 定義將圖片框變為正方形的工具
def convert_to_square(bbox):
# 先將數據copy
square_bbox = bbox.copy()
# 如果數據框內沒有框,則返回空列表

if bbox.shape[0] == 0:
return np.array([])
# 計算出框的長寬
h = bbox[:, 3] - bbox[:, 1]
w = bbox[:, 2] - bbox[:, 0]
# 找出最大的那個邊
max_side = np.maximum(h, w)
# 計算正方形的左上角的點
square_bbox[:, 0] = bbox[:, 0] + w * 0.4 - max_side * 0.4
square_bbox[:, 1] = bbox[:, 1] + h * 0.4 - max_side * 0.4
square_bbox[:, 2] = square_bbox[:, 0] + max_side
square_bbox[:, 3] = square_bbox[:, 1] + max_side
# 返回到正方形的列表
return square_bbox

這個的意思就是網絡輸入size限定的,工具的作用就是在每個網絡輸入的時候就是圖片糾正,將圖片改變成一個正方形的size,便於網絡訓練,作用其實很簡單,因為在網絡訓練時一般輸入的是12*12/24*24/48*48這種類型的,但是進行我們訓練難免會變形為矩形什麼的,所以我們就要進行矩形糾正。

好了今天的工具暫且講到這裡,有疑問可以在下面留言,這樣大家可以一起交流解答~

有什麼寫的有問題的地方也歡迎大家指正~

喜歡就關注我,持續日更中~歡迎轉發留言評論~

(發現一天寫這麼多的確很累吶,等我把恩達老師的筆記寫完,就按照項目一個一個來寫,那樣大家就可以跟著實踐了,謝謝大家的支持,歡迎轉發留言~)


分享到:


相關文章: