1. 程式人生 > >目標檢測中的IOU計算問題

目標檢測中的IOU計算問題

在目標檢測中我們有一個基本的操作,形象表述就是畫框框,我們要通過我們畫的框把我們要標註的目標給框出來,如下面那個狗。我們既可以說這個狗被框出來了,但是也可以說沒有,因為你可以觀察到左邊和上面是存在一些縫隙的。



那問題就出現了。什麼樣的框才算把目標給框住了呢?這個時候就有了IOU這個評價指標。什麼是IOU?



IOU想要描述的時黃框(檢測到的結果)和綠框(標註的結果)重合的程度。用公式表示為

  • IOU=DetectionResultGroundTruthDetectionResultGroundTruth

公式裡面的DetectionResult就表示黃框(也就是通過神經網路得到的結果),GroundResult

表示綠框(也就是標註的結果)。

好的,這看上去很容易,但是在具體實現的時候就會有一些問題了。接下來我先用YOLO2中的做法講解其實現原理。

float overlap(float x1, float w1, float x2, float w2)
{
    float l1 = x1 - w1/2;
    float l2 = x2 - w2/2;
    float left = l1 > l2 ? l1 : l2;
    float r1 = x1 + w1/2;
    float r2 = x2 + w2/2;
    float right = r1 < r2 ? r1 : r2;
    return
right - left; } float box_intersection(box a, box b) { float w = overlap(a.x, a.w, b.x, b.w); float h = overlap(a.y, a.h, b.y, b.h); if(w < 0 || h < 0) return 0; float area = w*h; return area; } float box_union(box a, box b) { float i = box_intersection(a, b); float
u = a.w*a.h + b.w*b.h - i; return u; } float box_iou(box a, box b) { return box_intersection(a, b)/box_union(a, b); }

在這個程式碼中box a表示結果box,而box b表示的是標註box,這兩者都是box類的物件,這個類在這裡我們用到了這樣幾個屬性:

  • x:表示box中心點的x座標
  • y:表示box中心點的y座標
  • w:表示box的寬度
  • h:表示box的高度

我麼先看第一個函式overlap是幹什麼的。假設按照box_intersection中的第一個做法,傳入這樣幾個引數overlap(a.x, a.w, b.x, b.w),結果就是l1表示黃框的左邊,l2表示綠框的左邊,r1表示黃框的右邊,r2表示綠框的右邊。如下圖



接著left=l2right=r1,最後right-left=交集的寬。同理傳入overlap(a.y, a.h, b.y, b.h)

得到交集的高。兩個一乘即為交集的大小。box_iou函式中的做法大家應該可以看得明白了,不再贅述。

當我們訓練好網路後,將待測影象輸入網路得到的輸出結果是一個高維矩陣。在YOLO2中最後得到的矩陣是這樣的[-1, H, W, B, (4 + 1 + C)]

  • H:表示縱向分割的塊的數目
  • W:表示橫向分割的塊的數目

也就是一幅圖片被我們分割為了H*W塊。

  • B:表示anchors的數目
  • C:表示classes的數目

注意這裡的4表示前面講的x,y,w,h,而後面1表示confidence(參看論文中的Pr(object)IOU

以下是對應的python tensorflow版本

coords = tf.reshape(coords, [-1, H*W, B, 4])
wh = tf.exp(coords[:,:,:,2:4]) * np.reshape(anchors, [1, 1, B, 2])
area_pred = wh[:,:,:,0] * wh[:,:,:,1]#得到預測框的面積
centers = coords[:,:,:,0:2]#得到預測框的xy
floor = centers - (wh * .5)
ceil  = centers + (wh * .5)

# calculate the intersection areas
intersect_upleft   = tf.maximum(floor, _upleft)
intersect_botright = tf.minimum(ceil , _botright)
intersect_wh = intersect_botright - intersect_upleft
intersect_wh = tf.maximum(intersect_wh, 0.0)
intersect = tf.multiply(intersect_wh[:,:,:,0], intersect_wh[:,:,:,1])#得到交集

# calculate the best IOU, set 0.0 confidence for worse boxes
iou = tf.truediv(intersect, _areas + area_pred - intersect)#_areas表示真實的面積

這裡的floor對應於上面的l1、黃框的下邊,ceil對應於上面的r1、黃框的上邊。_upleft對應上面的l2和綠框的下邊,_botright對應上面的r2和綠框的上邊。intersect_upleft就是l2和黃框的下邊,intersect_botright就是r1和綠框的上邊,後面的程式碼就順理成章了。

由於本人水平有限,如有問題,懇請指出!^_^