IoU 作爲目標檢測算法性能 mAP 計算的一個非常重要的函數。
但縱觀 IoU 計算的介紹知識,都是直接給出代碼,給出計算方法,沒有人徹底地分析過其中的邏輯,故本人書寫該篇博客來介紹下其中的邏輯。
1. IoU的簡介及原理解析
IoU 的全稱爲交併比(Intersection over Union),通過這個名稱我們大概可以猜到 IoU 的計算方法。IoU 計算的是 “預測的邊框” 和 “真實的邊框” 的交集和並集的比值。
開始計算之前,我們首先進行分析下交集和並集到底應該怎麼計算:我們首先需要計算交集,然後並集通過兩個邊框的面積的和減去交集部分即爲並集,因此 IoU 的計算的難點在於交集的計算。
爲了計算交集,你腦子裏首先想到的方法應該是:考慮兩個邊框的相對位置,然後按照相對位置(左上,左下,右上,右下,包含,互不相交)分情況討論,來計算交集。
上圖就是你的直覺,這樣想沒有錯。但計算一個交集,就要分多種情況討論,要是程序真的按照這邏輯編寫就太搞笑了。因此對這個問題進行進一步地研究顯得十分有必要。
讓我們重新思考一下兩個框交集的計算。兩個框交集的計算的實質是兩個集合交集的計算,因此我們可以將兩個框的交集的計算簡化爲:
def iou(set_a, set_b):
'''
一維 iou 的計算
'''
x1, x2 = set_a # (left, right)
y1, y2 = set_b # (left, right)
low = max(x1, y1)
high = min(x2, y2)
# intersection
if high-low<0:
inter = 0
else:
inter = high-low
# union
union = (x2 - x1) + (y2 - y1) - inter
# iou
iou = inter / union
return iou
上面,我們計算了兩個一維集合的 iou,將上面的程序進行擴展,即可得到兩個框 IoU 計算的程序。
def iou(box1, box2):
'''
兩個框(二維)的 iou 計算
注意:邊框以左上爲原點
box:[top, left, bottom, right]
'''
in_h = min(box1[2], box2[2]) - max(box1[0], box2[0])
in_w = min(box1[3], box2[3]) - max(box1[1], box2[1])
inter = 0 if in_h<0 or in_w<0 else in_h*in_w
union = (box1[2] - box1[0]) * (box1[3] - box1[1]) + \
(box2[2] - box2[0]) * (box2[3] - box2[1]) - inter
iou = inter / union
return iou
2. 基於TensorFlow的IoU實現
上節介紹了IoU,及其的計算,下面我們給出其在 TensorFlow 上的實現:
import tensorflow as tf
def IoU_calculator(x, y, w, h, l_x, l_y, l_w, l_h):
"""calaulate IoU
Args:
x: net predicted x
y: net predicted y
w: net predicted width
h: net predicted height
l_x: label x
l_y: label y
l_w: label width
l_h: label height
Returns:
IoU
"""
# convert to coner
x_max = x + w/2
y_max = y + h/2
x_min = x - w/2
y_min = y - h/2
l_x_max = l_x + l_w/2
l_y_max = l_y + l_h/2
l_x_min = l_x - l_w/2
l_y_min = l_y - l_h/2
# calculate the inter
inter_x_max = tf.minimum(x_max, l_x_max)
inter_x_min = tf.maximum(x_min, l_x_min)
inter_y_max = tf.minimum(y_max, l_y_max)
inter_y_min = tf.maximum(y_min, l_y_min)
inter_w = inter_x_max - inter_x_min
inter_h = inter_y_max - inter_y_min
inter = tf.cond(tf.logical_or(tf.less_equal(inter_w,0), tf.less_equal(inter_h,0)),
lambda:tf.cast(0,tf.float32),
lambda:tf.multiply(inter_w,inter_h))
# calculate the union
union = w*h + l_w*l_h - inter
IoU = inter / union
return IoU
本文來源:https://blog.csdn.net/u014061630/article/details/82818112