Python实现目标检测交并比IOU及多分类评估指标详解
本文详细介绍如何使用Python计算目标检测中的交并比(IOU),包括两种常见坐标格式的实现代码。同时补充多分类场景下的混淆矩阵计算方法,并展示如何基于混淆矩阵导出Precision、Recall、F1-score及mIOU等关键评估指标,为模型性能分析提供完整参考。
IoU概念与计算原理
交并比(Intersection-over-Union,简称IoU)是目标检测任务中用于评估预测框与真实框重叠程度的核心指标。它定义为预测候选框与原始标记框交集面积与并集面积的比值。当两个框完全重合时,IoU值为1,表示理想检测结果。

IoU的计算公式基于几何面积运算:首先分别计算两个矩形框的面积,然后确定它们相交部分的边界坐标,计算交集面积,最后用交集面积除以两个框面积之和减去交集面积(即并集面积)。

Python实现IOU计算代码
以下是使用Python实现IoU计算的两种常见方式。第一种方法采用[xmin, ymin, xmax, ymax]格式,第二种方法采用[y0, x0, y1, x1]即(top, left, bottom, right)格式。两种实现均处理了不相交情况,返回0。
def cal_iou(box1, box2):
"""
:param box1: = [xmin1, ymin1, xmax1, ymax1]
:param box2: = [xmin2, ymin2, xmax2, ymax2]
:return:
"""
xmin1, ymin1, xmax1, ymax1 = box1
xmin2, ymin2, xmax2, ymax2 = box2
# 计算每个矩形的面积
s1 = (xmax1 - xmin1) * (ymax1 - ymin1) # C的面积
s2 = (xmax2 - xmin2) * (ymax2 - ymin2) # G的面积
# 计算相交矩形
xmin = max(xmin1, xmin2)
ymin = max(ymin1, ymin2)
xmax = min(xmax1, xmax2)
ymax = min(ymax1, ymax2)
w = max(0, xmax - xmin)
h = max(0, ymax - ymin)
area = w * h # C∩G的面积
iou = area / (s1 + s2 - area)
return iou
# -*-coding: utf-8 -*-
"""
@Project: IOU
@File : IOU.py
@Author : panjq
@E-mail : pan_jinquan@163.com
@Date : 2018-10-14 10:44:06
"""
def calIOU_V1(rec1, rec2):
"""
computing IoU
:param rec1: (y0, x0, y1, x1), which reflects
(top, left, bottom, right)
:param rec2: (y0, x0, y1, x1)
:return: scala value of IoU
"""
# 计算每个矩形的面积
S_rec1 = (rec1[2] - rec1[0]) * (rec1[3] - rec1[1])
S_rec2 = (rec2[2] - rec2[0]) * (rec2[3] - rec2[1])
# computing the sum_area
sum_area = S_rec1 + S_rec2
# find the each edge of intersect rectangle
left_line = max(rec1[1], rec2[1])
right_line = min(rec1[3], rec2[3])
top_line = max(rec1[0], rec2[0])
bottom_line = min(rec1[2], rec2[2])
# judge if there is an intersect
if left_line >= right_line or top_line >= bottom_line:
return 0
else:
intersect = (right_line - left_line) * (bottom_line - top_line)
return intersect/(sum_area - intersect)
def calIOU_V2(rec1, rec2):
"""
computing IoU
:param rec1: (y0, x0, y1, x1), which reflects
(top, left, bottom, right)
:param rec2: (y0, x0, y1, x1)
:return: scala value of IoU
"""
# cx1 = rec1[0]
# cy1 = rec1[1]
# cx2 = rec1[2]
# cy2 = rec1[3]
# gx1 = rec2[0]
# gy1 = rec2[1]
# gx2 = rec2[2]
# gy2 = rec2[3]
cx1,cy1,cx2,cy2=rec1
gx1,gy1,gx2,gy2=rec2
# 计算每个矩形的面积
S_rec1 = (cx2 - cx1) * (cy2 - cy1) # C的面积
S_rec2 = (gx2 - gx1) * (gy2 - gy1) # G的面积
# 计算相交矩形
x1 = max(cx1, gx1)
y1 = max(cy1, gy1)
x2 = min(cx2, gx2)
y2 = min(cy2, gy2)
w = max(0, x2 - x1)
h = max(0, y2 - y1)
area = w * h # C∩G的面积
iou = area / (S_rec1 + S_rec2 - area)
return iou
if __name__=='__main__':
rect1 = (661, 27, 679, 47)
# (top, left, bottom, right)
rect2 = (662, 27, 682, 47)
iou1 = calIOU_V1(rect1, rect2)
iou2 = calIOU_V2(rect1, rect2)
print(iou1)
print(iou2)
更多详细实现细节可参考:https://www.jb51.net/article/184542.htm
多分类评估指标与混淆矩阵计算
补充知识:在多分类任务中,除了IoU,还需关注混淆矩阵、精确率(Precision)、召回率(Recall)、F1-score以及平均IoU(mIOU)等综合评估指标。
以下是计算多分类混淆矩阵及各项评估指标的完整Python代码示例,逻辑清晰,可直接复用。
import os
import numpy as np
from glob import glob
from collections import Counter
def cal_confu_matrix(label, predict, class_num):
confu_list = []
for i in range(class_num):
c = Counter(predict[np.where(label == i)])
single_row = []
for j in range(class_num):
single_row.append(c[j])
confu_list.append(single_row)
return np.array(confu_list).astype(np.int32)
def metrics(confu_mat_total, save_path=None):
'''
:param confu_mat: 总的混淆矩阵
backgound:是否干掉背景
:return: txt写出混淆矩阵, precision,recall,IOU,f-score
'''
class_num = confu_mat_total.shape[0]
confu_mat = confu_mat_total.astype(np.float32) + 0.0001
col_sum = np.sum(confu_mat, axis=1) # 按行求和
raw_sum = np.sum(confu_mat, axis=0) # 每一列的数量
'''计算各类面积比,以求OA值'''
oa = 0
for i in range(class_num):
oa = oa + confu_mat[i, i]
oa = oa / confu_mat.sum()
'''Kappa'''
pe_fz = 0
for i in range(class_num):
pe_fz += col_sum[i] * raw_sum[i]
pe = pe_fz / (np.sum(confu_mat) * np.sum(confu_mat))
kappa = (oa - pe) / (1 - pe)
# 将混淆矩阵写入excel中
TP = [] # 识别中每类分类正确的个数
for i in range(class_num):
TP.append(confu_mat[i, i])
# 计算f1-score
TP = np.array(TP)
FN = col_sum - TP
FP = raw_sum - TP
# 计算并写出precision,recall, f1-score,f1-m以及mIOU
f1_m = []
iou_m = []
for i in range(class_num):
# 写出f1-score
f1 = TP[i] * 2 / (TP[i] * 2 + FP[i] + FN[i])
f1_m.append(f1)
iou = TP[i] / (TP[i] + FP[i] + FN[i])
iou_m.append(iou)
f1_m = np.array(f1_m)
iou_m = np.array(iou_m)
if save_path is not None:
with open(save_path + 'accuracy.txt', 'w') as f:
f.write('OA:\t%.4f\n' % (oa*100))
f.write('kappa:\t%.4f\n' % (kappa*100))
f.write('mf1-score:\t%.4f\n' % (np.mean(f1_m)*100))
f.write('mIou:\t%.4f\n' % (np.mean(iou_m)*100))
# 写出precision
f.write('precision:\n')
for i in range(class_num):
f.write('%.4f\t' % (float(TP[i]/raw_sum[i])*100))
f.write('\n')
# 写出recall
f.write('recall:\n')
for i in range(class_num):
f.write('%.4f\t' % (float(TP[i] / col_sum[i])*100))
f.write('\n')
# 写出f1-score
f.write('f1-score:\n')
for i in range(class_num):
f.write('%.4f\t' % (float(f1_m[i])*100))
f.write('\n')
# 写出 IOU
f.write('Iou:\n')
for i in range(class_num):
f.write('%.4f\t' % (float(iou_m[i])*100))
f.write('\n')
以上即为Python实现交并比IOU及多分类评估指标的完整教程,希望能为相关开发者提供实用参考。欢迎收藏支持,获取更多技术内容。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









