1. 程式人生 > 程式設計 >淺談Python3實現兩個矩形的交併比(IoU)

淺談Python3實現兩個矩形的交併比(IoU)

一、前言

因為最近剛好被問到這個問題,但是自己當時特別懵逼,導致沒有做出來。所以下來後自己Google了很多IoU的部落格,但是很多部落格要麼過於簡略,要麼是互相轉載的,有一些部落格圖和程式碼還有點問題,也導致自己這個萌新走了不少彎路。所以自己重新整理了看的部落格,力求以更簡單的方式展現這個問題的解答辦法,方便日後自己回顧。如果朋友們覺得寫的有問題的地方,非常歡迎大家在下面留言交流,避免因為我的問題導致讀者走彎路。

二、交併比的概念及應用

假設平面座標中有一個矩形,並且這個矩形的長和寬均分別與x軸和y軸平行。

那麼矩形在平面座標中的唯一位置可以通過對角線上的兩個頂點座標來確定(這裡不做證明)。

如下圖所示:這個矩形的唯一位置可以用左上和右下的頂點座標,即:(xmin,ymax,xmax,ymin)來確定,也可以用左下和右上頂點座標,即(xmin,ymin,ymax)來確定。

接下來說一下自己踩的坑:網上的大部分部落格,圖是標的是左上和右下的頂點座標,但是程式碼清一色是通過左下和右上頂點座標來確定矩形位置的。所以一開始看著特別暈圈。

理論上兩種確定方式都可以,不過相對而言,通過左下和右上兩個頂點座標,即(xmin,ymax)來確定矩形位置更符合我們的習慣,我想這也是網上大部分程式碼都是這樣的原因吧。

矩形的面積很好求,長X寬就行:

矩形的面積 = (xmax -xmin) X (ymax - ymin)

好了,理清楚怎麼確定矩形的位置後,接下來我們就來解決交併比的計算問題。

交併比(Intersection over Union,IoU)是目標檢測任務中的一個非常重要的概念。它是產生的預測框(Predicted bounding box)與原標記框(Ground-truth bounding box)的交疊率,即它們的交集(相交面積)與並集(總面積)的比值。最理想情況是完全重疊,即比值為1。一般來說,這個score > 0.5 就可以被認為是一個不錯的結果。這個標準用於測量真實和預測之間的相關度,相關度越高,該值越高,它可以評估演算法的準確度。

假設平面座標中有兩個矩形:原標記框(Ground-truth bounding box,G)和預測框(Predicted bounding box,P),其中G為手動標記的框,P為演算法預測的框,並且這兩個矩形的長和寬均分別與x軸和y軸平行。如下圖所示:

IoU計算公式:

所以有:矩形G(gxmin,gymin,gxmax,gymax)和矩形P(pxmin,pymin,pxmax,pymax)

求交併比的關鍵是求出相交矩形G∩P的面積。

解決這個問題,我們只要確定相交矩形的左下(xmin,ymin)和右上(xmax,ymax)頂點座標即可,即確定(xmin,ymax)。

通過看圖,我們可以清楚的觀察到:

# 相交矩形的左下頂點座標,就是兩個矩形左下座標的x和y分別取最大值
xmin = max(gxmin,pxmin)
ymin = max(gymin,pymin)
# 相交矩形的右上頂點座標,就是兩個矩形右上座標的x和y分別取最小值
xmax = min(gxmax,pxmax)
ymax = min(gymax,pyxmax)

如果一下沒有看明白,可以自己在紙上多畫畫,理解下。

得到了相交矩形的座標(xmin,ymax)那麼相交矩形的面積就非常簡單了。

area(G∩P) = 長 X 寬

w = xmax - xmin # 計算相交矩形的長

h = ymax - ymin # 計算相交矩形的寬

area(G∩P) = w X h # 計算相交矩形的面積

這裡還有最後一個問題,當計算得到的寬或者長為0或者負數時,說明兩個矩形不相交,相交面積為0,那麼最後的IoU就為0。這裡我們有兩種處理方式:

1. 用if語句來分類討論:

if w <=0 or h <= 0:
 return 0

2. 用max()方法來處理:

w = max(0,(x2 - x1))
h = max(0,(y1 - y2))

三、Python3 實現程式碼

經過以上分析,思路應該已經非常清晰了,這裡我就直接放出完整Python3程式碼。

def calculate_IoU(predicted_bound,ground_truth_bound):
 """
 computing the IoU of two boxes.
 Args:
  box: (xmin,ymax),通過左下和右上兩個頂點座標來確定矩形位置
 Return:
  IoU: IoU of box1 and box2.
 """
 pxmin,pymax = predicted_bound
 print("預測框P的座標是:({},{},{})".format(pxmin,pymax))
 gxmin,gymax = ground_truth_bound
 print("原標記框G的座標是:({},{})".format(gxmin,gymax))

 parea = (pxmax - pxmin) * (pymax - pymin) # 計算P的面積
 garea = (gxmax - gxmin) * (gymax - gymin) # 計算G的面積
 print("預測框P的面積是:{};原標記框G的面積是:{}".format(parea,garea))

 # 求相交矩形的左下和右上頂點座標(xmin,ymax)
 xmin = max(pxmin,gxmin) # 得到左下頂點的橫座標
 ymin = max(pymin,gymin) # 得到左下頂點的縱座標
 xmax = min(pxmax,gxmax) # 得到右上頂點的橫座標
 ymax = min(pymax,gymax) # 得到右上頂點的縱座標

 # 計算相交矩形的面積
 w = xmax - xmin
 h = ymax - ymin
 if w <=0 or h <= 0:
  return 0

 area = w * h # G∩P的面積
 # area = max(0,xmax - xmin) * max(0,ymax - ymin) # 可以用一行程式碼算出來相交矩形的面積
 print("G∩P的面積是:{}".format(area))

 # 並集的面積 = 兩個矩形面積 - 交集面積
 IoU = area / (parea + garea - area)

 return IoU

if __name__ == '__main__':
 IoU = calculate_IoU( (1,-1,3,1),(0,2,2))
 print("IoU是:{}".format(IoU))

這裡也放一下通過左上和右下頂點座標來確定矩形的位置的Python3程式碼。原理是一樣的,不要弄混就好。

def calculate_IoU(predicted_bound,ground_truth_bound):
 """
 computing the IoU of two boxes.
 Args:
  box: (x1,y1,x2,y2),通過左上和右下兩個頂點座標來確定矩形
 Return:
  IoU: IoU of box1 and box2.
 """
 px1,py1,px2,py2 = predicted_bound
 print("預測框P的座標是:({},{})".format(px1,py2))

 gx1,gy1,gx2,gy2 = ground_truth_bound
 print("原標記框G的座標是:({},{})".format(gx1,gy2))

 parea = (px2 - px1) * (py1 - py2) # 計算P的面積
 garea = (gx2 - gx1) * (gy1 - gy2) # 計算G的面積
 print("預測框P的面積是:{};原標記框G的面積是:{}".format(parea,garea))

 # 求相交矩形的左上和右下頂點座標(x1,y2)
 x1 = max(px1,gx1) # 得到左上頂點的橫座標
 y1 = min(py1,gy1) # 得到左上頂點的縱座標
 x2 = min(px2,gx2) # 得到右下頂點的橫座標
 y2 = max(py2,gy2) # 得到右下頂點的縱座標

 # 利用max()方法處理兩個矩形沒有交集的情況,當沒有交集時,w或者h取0,比較巧妙的處理方法
 # w = max(0,(x2 - x1)) # 相交矩形的長,這裡用w來表示
 # h = max(0,(y1 - y2)) # 相交矩形的寬,這裡用h來表示
 # print("相交矩形的長是:{},寬是:{}".format(w,h))
 # 這裡也可以考慮引入if判斷
 w = x2 - x1
 h = y1 - y2
 if w <=0 or h <= 0:
  return 0

 area = w * h # G∩P的面積
 print("G∩P的面積是:{}".format(area))

 # 並集的面積 = 兩個矩形面積 - 交集面積
 IoU = area / (parea + garea - area)

 return IoU

if __name__ == '__main__':
 IoU = calculate_IoU( (1,1,-1),0))
 print("IoU是:{}".format(IoU))

以上這篇淺談Python3實現兩個矩形的交併比(IoU)就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。