目标检测中的IOU和CIOU原理讲解以及应用(附测试代码)
上期講解了目標(biāo)檢測中的三種數(shù)據(jù)增強的方法,這期我們講講目標(biāo)檢測中用來評估對象檢測算法的IOU和CIOU的原理應(yīng)用以及代碼實現(xiàn)。
交并比IOU(Intersection over union)
在目標(biāo)檢測任務(wù)中,我們用框框來定位對象,如下圖定位圖片中這個汽車,假設(shè)實際框是圖中紅色的框框,你的算法預(yù)測給出的是紫色的框框,怎么判斷你的算法預(yù)測的這個框框的效果好壞呢?
這就用到我們的交并比函數(shù)IOU了,計算公式如下:
將我們圖片汽車的實際紅色框記為A,算法的預(yù)測框記為B,交并比就是數(shù)學(xué)中A和B的交集A∩B跟A和B的并集的A∪B的面積之比,非常容易理解。IOU實際上衡量了兩個邊界框重疊地相對大小,預(yù)測框和真實框重疊越大,說明你的算法預(yù)測效果比較好,IOU是一個評價指標(biāo)。
那么回到剛剛的問題:如何利用IOU進行判斷算法的預(yù)測效果好壞呢?也就是這個預(yù)測框是否可以當(dāng)做正確的定位到我們的目標(biāo)汽車呢?
在計算機檢測任務(wù)中,如果我們算法的預(yù)測框和實際框之間的交并比IOU≧0.5,那么你的算法預(yù)測結(jié)果是可以接受的,就說你預(yù)測的這個框框是正確的,這個閾值0.5,你可以設(shè)置得更高,邊界框越精確,在YOLOv3中正是用到這個IOU來對我們的先驗框進行了一個篩選,以及計算測試集的模型效果mAP時也用到了IOU進行閾值判斷。
效果圖
首先借助Opencv和numpy框畫兩個框,然后計算IOU進行展示,如下圖。
IOU實現(xiàn)代碼
以框的左上角(x1,y1)和右下角(x2,y2)坐標(biāo)形式來計算它們之間的IOU。
import cv2
import numpy as np
def CountIOU(RecA, RecB):
xA = max(RecA[0], RecB[0])
yA = max(RecA[1], RecB[1])
xB = min(RecA[2], RecB[2])
yB = min(RecA[3], RecB[3])
# 計算交集部分面積
interArea = max(0, xB - xA + 1) * max(0, yB - yA + 1)
# 計算預(yù)測值和真實值的面積
RecA_Area = (RecA[2] - RecA[0] + 1) * (RecA[3] - RecA[1] + 1)
RecB_Area = (RecB[2] - RecB[0] + 1) * (RecB[3] - RecB[1] + 1)
# 計算IOU
iou = interArea / float(RecA_Area + RecB_Area - interArea)
return iou
if __name__ == "__main__":
img = np.zeros((512, 512, 3), np.uint8)
img.fill(255)
RecA = [50, 50, 300, 300] # x1,y1,x2,y2
RecB = [60, 60, 320, 320]
cv2.rectangle(img, (RecA[0], RecA[1]), (RecA[2], RecA[3]), (0, 255, 0), 5)
cv2.rectangle(img, (RecB[0], RecB[1]), (RecB[2], RecB[3]), (255, 0, 0), 5)
IOU = CountIOU(RecA, RecB)
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, "IOU = %.2f" % IOU, (130, 190), font, 0.8, (0, 0, 0), 2)
cv2.imshow("image", img)
cv2.waitKey()
cv2.destroyAllWindows()
CIOU(Complete-IOU)
IoU是比值的概念,對目標(biāo)物體的尺寸scale是不敏感的。我們在計算框框BBox的回歸損失函數(shù)進行優(yōu)化有多種優(yōu)化方式,如在CIOU之前有GIOU、DIOU,而CIOU解決了一般IoU無法直接優(yōu)化兩個框框沒有重疊的部分。
IoU經(jīng)過GIOU再到DIOU最終發(fā)展到CIOU,CIOU將目標(biāo)與框框anchor之間的距離,重疊率、尺度以及懲罰項都考慮進去,使得目標(biāo)框回歸變得更加穩(wěn)定,不會像IoU和GIoU一樣出現(xiàn)訓(xùn)練過程中發(fā)散等問題,而懲罰因子把預(yù)測框長寬比擬合目標(biāo)框的長寬比考慮進去,在最新發(fā)布的yolov4中anchor的回歸就是用的CIOU方式。
CIOU計算公式
效果圖
首先借助Opencv和numpy框畫兩個框,然后按照公式計算CIOU進行展示,如下圖。
代碼實現(xiàn):
import torch
import numpy as np
import cv2
import math
def box_ciou(b1, b2):
"""
輸入為: ----------
b1: tensor, shape=(batch, feat_w, feat_h, anchor_num, 4), xywh
b2: tensor, shape=(batch, feat_w, feat_h, anchor_num, 4), xywh
返回為: -------
ciou: tensor, shape=(batch, feat_w, feat_h, anchor_num, 1)
"""
# 求出預(yù)測框左上角右下角
b1_xy = b1[..., :2]
b1_wh = b1[..., 2:4]
b1_wh_half = b1_wh/2.
b1_mins = b1_xy - b1_wh_half
b1_maxes = b1_xy + b1_wh_half
# 求出真實框左上角右下角
b2_xy = b2[..., :2]
b2_wh = b2[..., 2:4]
b2_wh_half = b2_wh/2.
b2_mins = b2_xy - b2_wh_half
b2_maxes = b2_xy + b2_wh_half
# 求真實框和預(yù)測框所有的iou
intersect_mins = torch.max(b1_mins, b2_mins)
intersect_maxes = torch.min(b1_maxes, b2_maxes)
intersect_wh = torch.max(intersect_maxes - intersect_mins, torch.zeros_like(intersect_maxes))
intersect_area = intersect_wh[..., 0] * intersect_wh[..., 1]
b1_area = b1_wh[..., 0] * b1_wh[..., 1]
b2_area = b2_wh[..., 0] * b2_wh[..., 1]
union_area = b1_area + b2_area - intersect_area
iou = intersect_area / (union_area + 1e-6)
# 計算中心的差距
center_distance = torch.sum(torch.pow((b1_xy - b2_xy), 2), axis=-1)
# 找到包裹兩個框的最小框的左上角和右下角
enclose_mins = torch.min(b1_mins, b2_mins)
enclose_maxes = torch.max(b1_maxes, b2_maxes)
enclose_wh = torch.max(enclose_maxes - enclose_mins, torch.zeros_like(intersect_maxes))
# 計算對角線距離
enclose_diagonal = torch.sum(torch.pow(enclose_wh,2), axis=-1)
ciou = iou - 1.0 * (center_distance) / (enclose_diagonal + 1e-7)
v = (4 / (math.pi ** 2)) * torch.pow((torch.atan(b1_wh[..., 0]/b1_wh[..., 1]) - torch.atan(b2_wh[..., 0]/b2_wh[..., 1])), 2)
alpha = v / (1.0 - iou + v)
ciou = ciou - alpha * v
return ciou
if __name__ == "__main__":
img = np.zeros((512, 512, 3), np.uint8)
img.fill(255)
RecA = [1, 90, 90, 150, 150]
RecB = [1, 150, 150, 200, 200]
a = torch.tensor(RecA, dtype=torch.float) # tensor, shape=(batch, feat_w, feat_h, anchor_num, 4), xywh
b = torch.tensor(RecB, dtype=torch.float)
cv2.rectangle(img, (int(RecA[1]-RecA[3]/2), int(RecA[2]-RecA[4]/2)), (int(RecA[1]+RecA[3]/2), int(RecA[2]+RecA[4]/2)), (0, 255, 0), 5)
cv2.rectangle(img,(int(RecB[1]-RecB[3]/2), int(RecB[2]-RecB[4]/2)), (int(RecB[1]+RecB[3]/2), int(RecB[2]+RecB[4]/2)), (255, 0, 0), 5)
CIOU = box_ciou(a,b)
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, "CIOU = %.2f" % CIOU, (130, 190), font, 0.8, (0, 0, 0), 2)
cv2.imshow("image", img)
cv2.waitKey()
cv2.destroyAllWindows()
相關(guān)代碼,還請關(guān)注微信公眾號:碼農(nóng)的后花園,回復(fù)關(guān)鍵字:IOU,下載使用。
更多有關(guān)python、深度學(xué)習(xí)和計算機編程和電腦知識的精彩內(nèi)容,可以關(guān)注微信公眾號:碼農(nóng)的后花園
總結(jié)
以上是生活随笔為你收集整理的目标检测中的IOU和CIOU原理讲解以及应用(附测试代码)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 德龙咖啡机b和sb区别(德字和徳字有什么
- 下一篇: Android——Activity类