淺談Python3實(shí)現(xiàn)兩個(gè)矩形的交并比(IoU)
一、前言
因?yàn)樽罱鼊偤帽粏柕竭@個(gè)問題,但是自己當(dāng)時(shí)特別懵逼,導(dǎo)致沒有做出來。所以下來后自己Google了很多IoU的博客,但是很多博客要么過于簡略,要么是互相轉(zhuǎn)載的,有一些博客圖和代碼還有點(diǎn)問題,也導(dǎo)致自己這個(gè)萌新走了不少彎路。所以自己重新整理了看的博客,力求以更簡單的方式展現(xiàn)這個(gè)問題的解答辦法,方便日后自己回顧。如果朋友們覺得寫的有問題的地方,非常歡迎大家在下面留言交流,避免因?yàn)槲业膯栴}導(dǎo)致讀者走彎路。
二、交并比的概念及應(yīng)用
假設(shè)平面坐標(biāo)中有一個(gè)矩形,并且這個(gè)矩形的長和寬均分別與x軸和y軸平行。
那么矩形在平面坐標(biāo)中的唯一位置可以通過對(duì)角線上的兩個(gè)頂點(diǎn)坐標(biāo)來確定(這里不做證明)。
如下圖所示:這個(gè)矩形的唯一位置可以用左上和右下的頂點(diǎn)坐標(biāo),即:(xmin, ymax, xmax, ymin)來確定,也可以用左下和右上頂點(diǎn)坐標(biāo),即(xmin, ymin, xmax, ymax)來確定。
接下來說一下自己踩的坑:網(wǎng)上的大部分博客,圖是標(biāo)的是左上和右下的頂點(diǎn)坐標(biāo),但是代碼清一色是通過左下和右上頂點(diǎn)坐標(biāo)來確定矩形位置的。所以一開始看著特別暈圈。
理論上兩種確定方式都可以,不過相對(duì)而言,通過左下和右上兩個(gè)頂點(diǎn)坐標(biāo),即(xmin, ymin, xmax, ymax)來確定矩形位置更符合我們的習(xí)慣,我想這也是網(wǎng)上大部分代碼都是這樣的原因吧。

矩形的面積很好求,長X寬就行:
矩形的面積 = (xmax -xmin) X (ymax - ymin)
好了,理清楚怎么確定矩形的位置后,接下來我們就來解決交并比的計(jì)算問題。
交并比(Intersection over Union, IoU)是目標(biāo)檢測(cè)任務(wù)中的一個(gè)非常重要的概念。它是產(chǎn)生的預(yù)測(cè)框(Predicted bounding box)與原標(biāo)記框(Ground-truth bounding box)的交疊率,即它們的交集(相交面積)與并集(總面積)的比值。最理想情況是完全重疊,即比值為1。一般來說,這個(gè)score > 0.5 就可以被認(rèn)為是一個(gè)不錯(cuò)的結(jié)果。這個(gè)標(biāo)準(zhǔn)用于測(cè)量真實(shí)和預(yù)測(cè)之間的相關(guān)度,相關(guān)度越高,該值越高,它可以評(píng)估算法的準(zhǔn)確度。
假設(shè)平面坐標(biāo)中有兩個(gè)矩形:原標(biāo)記框(Ground-truth bounding box, G)和預(yù)測(cè)框(Predicted bounding box, P),其中G為手動(dòng)標(biāo)記的框,P為算法預(yù)測(cè)的框,并且這兩個(gè)矩形的長和寬均分別與x軸和y軸平行。如下圖所示:

IoU計(jì)算公式:

所以有:矩形G(gxmin, gymin, gxmax, gymax)和矩形P(pxmin, pymin, pxmax, pymax)
求交并比的關(guān)鍵是求出相交矩形G∩P的面積。
解決這個(gè)問題,我們只要確定相交矩形的左下(xmin, ymin)和右上(xmax, ymax)頂點(diǎn)坐標(biāo)即可,即確定(xmin, ymin, xmax, ymax)。
通過看圖,我們可以清楚的觀察到:
# 相交矩形的左下頂點(diǎn)坐標(biāo), 就是兩個(gè)矩形左下坐標(biāo)的x和y分別取最大值 xmin = max(gxmin, pxmin) ymin = max(gymin, pymin) # 相交矩形的右上頂點(diǎn)坐標(biāo), 就是兩個(gè)矩形右上坐標(biāo)的x和y分別取最小值 xmax = min(gxmax, pxmax) ymax = min(gymax, pyxmax)
如果一下沒有看明白,可以自己在紙上多畫畫,理解下。
得到了相交矩形的坐標(biāo)(xmin, ymin, xmax, ymax)那么相交矩形的面積就非常簡單了。
area(G∩P) = 長 X 寬
w = xmax - xmin # 計(jì)算相交矩形的長
h = ymax - ymin # 計(jì)算相交矩形的寬
area(G∩P) = w X h # 計(jì)算相交矩形的面積
這里還有最后一個(gè)問題,當(dāng)計(jì)算得到的寬或者長為0或者負(fù)數(shù)時(shí),說明兩個(gè)矩形不相交,相交面積為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 實(shí)現(xiàn)代碼
經(jīng)過以上分析,思路應(yīng)該已經(jīng)非常清晰了,這里我就直接放出完整Python3代碼。
def calculate_IoU(predicted_bound, ground_truth_bound):
"""
computing the IoU of two boxes.
Args:
box: (xmin, ymin, xmax, ymax),通過左下和右上兩個(gè)頂點(diǎn)坐標(biāo)來確定矩形位置
Return:
IoU: IoU of box1 and box2.
"""
pxmin, pymin, pxmax, pymax = predicted_bound
print("預(yù)測(cè)框P的坐標(biāo)是:({}, {}, {}, {})".format(pxmin, pymin, pxmax, pymax))
gxmin, gymin, gxmax, gymax = ground_truth_bound
print("原標(biāo)記框G的坐標(biāo)是:({}, {}, {}, {})".format(gxmin, gymin, gxmax, gymax))
parea = (pxmax - pxmin) * (pymax - pymin) # 計(jì)算P的面積
garea = (gxmax - gxmin) * (gymax - gymin) # 計(jì)算G的面積
print("預(yù)測(cè)框P的面積是:{};原標(biāo)記框G的面積是:{}".format(parea, garea))
# 求相交矩形的左下和右上頂點(diǎn)坐標(biāo)(xmin, ymin, xmax, ymax)
xmin = max(pxmin, gxmin) # 得到左下頂點(diǎn)的橫坐標(biāo)
ymin = max(pymin, gymin) # 得到左下頂點(diǎn)的縱坐標(biāo)
xmax = min(pxmax, gxmax) # 得到右上頂點(diǎn)的橫坐標(biāo)
ymax = min(pymax, gymax) # 得到右上頂點(diǎn)的縱坐標(biāo)
# 計(jì)算相交矩形的面積
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))
# 并集的面積 = 兩個(gè)矩形面積 - 交集面積
IoU = area / (parea + garea - area)
return IoU
if __name__ == '__main__':
IoU = calculate_IoU( (1, -1, 3, 1), (0, 0, 2, 2))
print("IoU是:{}".format(IoU))
這里也放一下通過左上和右下頂點(diǎn)坐標(biāo)來確定矩形的位置的Python3代碼。原理是一樣的,不要弄混就好。

def calculate_IoU(predicted_bound, ground_truth_bound):
"""
computing the IoU of two boxes.
Args:
box: (x1, y1, x2, y2),通過左上和右下兩個(gè)頂點(diǎn)坐標(biāo)來確定矩形
Return:
IoU: IoU of box1 and box2.
"""
px1, py1, px2, py2 = predicted_bound
print("預(yù)測(cè)框P的坐標(biāo)是:({}, {}, {}, {})".format(px1, py1, px2, py2))
gx1, gy1, gx2, gy2 = ground_truth_bound
print("原標(biāo)記框G的坐標(biāo)是:({}, {}, {}, {})".format(gx1, gy1, gx2, gy2))
parea = (px2 - px1) * (py1 - py2) # 計(jì)算P的面積
garea = (gx2 - gx1) * (gy1 - gy2) # 計(jì)算G的面積
print("預(yù)測(cè)框P的面積是:{};原標(biāo)記框G的面積是:{}".format(parea, garea))
# 求相交矩形的左上和右下頂點(diǎn)坐標(biāo)(x1, y1, x2, y2)
x1 = max(px1, gx1) # 得到左上頂點(diǎn)的橫坐標(biāo)
y1 = min(py1, gy1) # 得到左上頂點(diǎn)的縱坐標(biāo)
x2 = min(px2, gx2) # 得到右下頂點(diǎn)的橫坐標(biāo)
y2 = max(py2, gy2) # 得到右下頂點(diǎn)的縱坐標(biāo)
# 利用max()方法處理兩個(gè)矩形沒有交集的情況,當(dāng)沒有交集時(shí),w或者h(yuǎn)取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))
# 并集的面積 = 兩個(gè)矩形面積 - 交集面積
IoU = area / (parea + garea - area)
return IoU
if __name__ == '__main__':
IoU = calculate_IoU( (1, 1, 3, -1), (0, 2, 2, 0))
print("IoU是:{}".format(IoU))
以上這篇淺談Python3實(shí)現(xiàn)兩個(gè)矩形的交并比(IoU)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- 如何通過python實(shí)現(xiàn)IOU計(jì)算代碼實(shí)例
- python實(shí)現(xiàn)交并比IOU教程
- python shapely.geometry.polygon任意兩個(gè)四邊形的IOU計(jì)算實(shí)例
- python實(shí)現(xiàn)IOU計(jì)算案例
- python:目標(biāo)檢測(cè)模型預(yù)測(cè)準(zhǔn)確度計(jì)算方式(基于IoU)
- python實(shí)現(xiàn)的Iou與Giou代碼
- python不使用for計(jì)算兩組、多個(gè)矩形兩兩間的iou方式
- python計(jì)算二維矩形IOU實(shí)例
- Python計(jì)算機(jī)視覺里的IOU計(jì)算實(shí)例
- 解析目標(biāo)檢測(cè)之IoU
相關(guān)文章
Python如何使用__slots__實(shí)現(xiàn)節(jié)省內(nèi)存和性能優(yōu)化
你有想過,一個(gè)小小的 __slots__ 能讓你的 Python 類內(nèi)存消耗直接減半嗎,沒錯(cuò),今天咱們要聊的就是這個(gè)讓人眼前一亮的技巧,感興趣的小伙伴可以了解下2025-03-03
pytorch下大型數(shù)據(jù)集(大型圖片)的導(dǎo)入方式
今天小編就為大家分享一篇pytorch下大型數(shù)據(jù)集(大型圖片)的導(dǎo)入方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-01-01
PyTorch搭建LSTM實(shí)現(xiàn)多變量時(shí)序負(fù)荷預(yù)測(cè)
這篇文章主要為大家介紹了PyTorch搭建LSTM實(shí)現(xiàn)多變量時(shí)間序列預(yù)測(cè)及負(fù)荷預(yù)測(cè),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
Python中pycharm編輯器界面風(fēng)格修改方法
這篇文章主要介紹了Python中pycharm編輯器界面風(fēng)格修改方法,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
Python實(shí)現(xiàn)希爾排序算法的原理與用法實(shí)例分析
這篇文章主要介紹了Python實(shí)現(xiàn)希爾排序算法,簡單講述了希爾排序的原理并結(jié)合具體實(shí)例形式分析了Python希爾排序的具體實(shí)現(xiàn)方法與使用技巧,需要的朋友可以參考下2017-11-11
Python?3.11.0下載安裝并使用help查看模塊信息的方法
本文給大家介紹Python?3.11.0下載安裝并使用help查看模塊信息的相關(guān)知識(shí),首先給大家講解了Python?3.11.0下載及安裝緊接著介紹了在命令行使用help查看模塊信息的方法,感興趣的朋友跟隨小編一起看看吧2022-11-11
Python描述數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)之哈夫曼樹篇
這篇文章主要給大家介紹了關(guān)于Python描述數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)之哈夫曼樹篇的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09

