目标检测(三)——IoU总结与代码实现(可完整实现)

IoU基本含义

IoU: 简单来说,就是锚框与真实框的交集与锚框与真实框的并集之比。
I o U = A ∩ B A ∪ B IoU = \frac{A∩B}{A∪B} IoU=ABAB
其中:

  • A 是真实框
  • B 是预测框——也就是锚框

形象的表示为:
在这里插入图片描述
如何确定A,B之间的交集呢?

首先,假设A,B的bbox数据:
A = [ x a 1 , y a 1 , x a 2 , y a 2 ] B = [ x b 1 , y b 1 , x b 2 , y b 2 ] A = [x_{a1}, y_{a1}, x_{a2}, y_{a2}] \\ B = [x_{b1}, y_{b1}, x_{b2}, y_{b2}] \\ A=[xa1,ya1,xa2,ya2]B=[xb1,yb1,xb2,yb2]
而此时的交集情况:
在这里插入图片描述
因此,交集的左上角坐标就是A,B的左上角x,y的最大值:【以x向右为正,y向下为正,均从0开始】
i n t e r x 1 = m a x ( x a 1 , x b 1 ) i n t e r y 1 = m a x ( y a 1 , y b 1 ) inter_{x1} = max(x_{a1}, x_{b1}) \\ inter_{y1} = max(y_{a1}, y_{b1}) \\ interx1=max(xa1,xb1)intery1=max(ya1,yb1)
而右下角的顶点则是A,B的右下角最小值:
i n t e r x 2 = m i n ( x a 2 , x b 2 ) i n t e r y 2 = m i n ( y a 2 , y a 2 ) inter_{x2} = min(x_{a2}, x_{b2}) \\ inter_{y2} = min(y_{a2}, y_{a2}) \\ interx2=min(xa2,xb2)intery2=min(ya2,ya2)
此时,交集的长宽就可以得到了:【长度由具体的像素个数决定,因此需要加1】
i n t e r w = m a x ( i n t e r x 2 − i n t e r x 1 + 1.0 , 0. ) i n t e r h = m a x ( i n t e r y 2 − i n t e r y 1 + 1.0 , 0. ) inter_{w} = max(inter_{x2} - inter_{x1} + 1.0, 0.)\\ inter_{h} = max(inter_{y2} - inter_{y1} + 1.0, 0.)\\ interw=max(interx2interx1+1.0,0.)interh=max(intery2intery1+1.0,0.)
因此,交集面积:
S i n t e r = i n t e r w ∗ i n t e r h S_{inter} = inter_{w} * inter_{h} \\ Sinter=interwinterh
最后我们计算一下并集的面积:

A, B框的面积:
S A = ( x a 2 − x a 1 + 1.0 ) ∗ ( y a 2 − y a 1 + 1.0 ) S B = ( x b 2 − x b 1 + 1.0 ) ∗ ( y b 2 − y b 1 + 1.0 ) S_{A} = (x_{a2} - x_{a1} + 1.0) * (y_{a2} - y_{a1} + 1.0) \\ S_{B} = (x_{b2} - x_{b1} + 1.0) * (y_{b2} - y_{b1} + 1.0) \\ SA=(xa2xa1+1.0)(ya2ya1+1.0)SB=(xb2xb1+1.0)(yb2yb1+1.0)
并集面积:
u n i o n a r e a = S A + S B − S i n t e r union_area = S_{A} + S_{B} - S_{inter} unionarea=SA+SBSinter
此时的交并集IoU:
I o U = S i n t e r u n i o n a r e a = S i n t e r S A + S B − S i n t e r IoU = \frac{S_{inter}}{union_area} = \frac{S_{inter}}{S_{A} + S_{B} - S_{inter}} IoU=unionareaSinter=SA+SBSinterSinter

示例:【黄色区域就是交集面积】

在这里插入图片描述
下面,我们通过代码来进行IoU计算和交集可视化绘制!

代码实践

0. 导入的基本库

import numpy as np  # 可能用到的数据值计算库
import os           # 可能用到的文件操作
import matplotlib.pyplot as plt   		# 图形绘制 
import matplotlib.patches as patches 	# 添加矩形框
import matplotlib.image as image  		# 读取图像数据

1. Bounding box 表示

这里涉及使用bounding box的绘制来可视化交集,所以构建一个bounding box的数据格式函数——因为bounding box具有两种不同的数据表示,两种表示在最终计算上,步骤有所不同。

def BoundingBox_Denote(bbox=[], mode=True):
    '''边界框的表示形式的转换
        bbox: 包含(x1, y1, x2, y2)四个位置信息的数据格式
        mode: 边界框数据表示的模式
             True:  to (x1,y1,x2,y2)
             False: to (x,y,w,h)
        
        return: 返回形式转换后的边界框数据
    '''
    denote_bbox = [] # 转换表示的边界框

    if mode is True:  # 保持原形式
        denote_bbox = bbox
    else:  # 转换为(center_x, center_y, w, h)
        center_x = (bbox[0]+bbox[2]) / 2.0
        center_y = (bbox[1]+bbox[3]) / 2.0
        w = bbox[2] - bbox[0]
        h = bbox[3] - bbox[1]
        denote_bbox = [center_x, center_y, w, h]
    
    # 返回表示转换的边界框表示
    denote_bbox = np.asarray(denote_bbox,  dtype='float32')
    return denote_bbox

2. 边界框矩形的绘制

这个部分用于边界框的绘制,展示交集的可视化

def draw_rectangle(bbox=[], mode=True, color='k', fill=False):
    '''绘制矩形框
        bbox:边界框数据(默认框数据不超过图片边界)
        mode: 边界框数据表示的模式
             True:  to (x1,y1,x2,y2)
             False: to (x,y,w,h)
        color: 边框颜色
        fill: 是否填充
    '''
    if mode is True: # to (x1,y1,x2,y2)
        x = bbox[0]
        y = bbox[1]
        w = bbox[2] - bbox[0] + 1  # 考虑到实际长度由像素个数决定,因此加1(可按坐标轴上两点间的点数推导)
        h = bbox[3] - bbox[1] + 1
    else: # to (x,y,w,h)
    	# 默认绘制的框不超出边界
        x = bbox[0] - bbox[2] / 2.0
        y = bbox[1] - bbox[3] / 2.0
        w = bbox[2]
        h = bbox[3]
    
    # 绘制边界框
    # patches.Rectangle需要传入左上角坐标、矩形区域的宽度、高度等参数
    # 获取绘制好的图形的返回句柄——用于添加到当前的图像窗口中
    rect = patches.Rectangle((x, y), w, h, 
                             linewidth=1,        # 线条宽度
                             edgecolor=color,    # 线条颜色
                             facecolor='y',      # 
                             fill=fill, linestyle='-')
    
    return rect

3. 为xywh格式的bbox数据提供坐标变换

def bbox_2leftup_2rightdown(bbox):
    '''计算bbox的左上右下顶点
        bbox:框数据——xywh
    '''
    x1 = bbox[0] - bbox[2] / 2.0
    y1 = bbox[1] - bbox[3] / 2.0
    x2 = bbox[0] + bbox[2] / 2.0
    y2 = bbox[1] + bbox[3] / 2.0
    
    return x1, y1, x2, y2

4. IoU计算

这里完成IoU的计算,同时返回IoU计算过程中转换好数据格式的原始边界框与实际的交集区域bbox。

def box_iou_solve(bbox1, bbox2, mode=True):
    '''计算两个框之间的IoU值
        bbox1: 框数据
        bbox2: 框数据
        mode: 框数据表示形式
              True: xyxy
              False: xywh

        IoU的intersection的左上右下顶点: 左上点为

        return IoU, (r_bbox1, r_bbox2, inter_bbox)
             PS:
                IoU: 交并比值
                r_bbox1:转换为xyxy形式的bbox1
                r_bbox2:转换为xyxy形式的r_bbox2
                inter_bbox: 形式为xyxy的交集位置
    '''
    if mode is True:  # bbox数据格式: xyxy
        # 左上右下顶点坐标
        b1_x1, b1_y1, b1_x2, b1_y2 = bbox1[0], bbox1[1], bbox1[2], bbox1[3]
        b2_x1, b2_y1, b2_x2, b2_y2 = bbox2[0], bbox2[1], bbox2[2], bbox2[3]
        # 框的长宽:长度由具体的像素个数决定,因此需要加1
        b1_w, b1_h = bbox1[2] - bbox1[0] + 1.0, bbox1[3] - bbox1[1] + 1.0
        b2_w, b2_h = bbox2[2] - bbox2[0] + 1.0, bbox1[3] - bbox1[1] + 1.0
    else:  # bbox数据格式: xywh
        # 左上右下顶点坐标
        b1_x1, b1_y1, b1_x2, b1_y2 = bbox_2leftup_2rightdown(bbox1)
        b2_x1, b2_y1, b2_x2, b2_y2 = bbox_2leftup_2rightdown(bbox2)
        # 框的长宽
        b1_w, b1_h = bbox1[2], bbox1[3]
        b2_w, b2_h = bbox2[2], bbox2[3]

    # 各自的面积
    s1 = b1_w * b1_h
    s2 = b2_w * b2_h

    # 交集面积
    # 如果考虑多个框进行计算交集——那么应该使用np.maximum——进行逐位比较
    inter_x1 = max(b1_x1, b2_x1)  # 交集区域的左上角
    inter_y1 = max(b1_y1, b2_y1)
    inter_x2 = min(b1_x2, b2_x2)  # 交集区域的右下角
    inter_y2 = min(b1_y2, b2_y2)

    # 长度由具体的像素个数决定,因此需要加1
    inter_w = max(inter_x2 - inter_x1 + 1.0, 0)
    inter_h = max(inter_y2 - inter_y1 + 1.0, 0)
    intersection = inter_w * inter_h

    # 并集面积
    union_area = s1 + s2 - intersection

    # 计算IoU交并集
    IoU = intersection / union_area

    # 整合坐标信息——用于展示交集可视化
    # 返回数据均以xyxy表示
    r_bbox1 = b1_x1, b1_y1, b1_x2, b1_y2
    r_bbox2 = b2_x1, b2_y1, b2_x2, b2_y2
    inter_bbox = inter_x1, inter_y1, inter_x2, inter_y2

    return IoU, (r_bbox1, r_bbox2, inter_bbox)

5. 演示代码

fig = plt.figure(figsize=(12, 8))
ax = plt.gca()

# 图片路径
img_path = os.path.join(os.getcwd(), 'img', '1.jpg')
img = image.imread(img_path) # 读取图片数据
plt.imshow(img)  # 展示图片

bbox1 = [240, 70, 380, 240] 
bbox2 = [300, 100, 440, 300]
denote_mode = True  # 数据格式模式
denote_bbox1 = BoundingBox_Denote(bbox=bbox1, mode=denote_mode)  # 形式转换
denote_bbox2 = BoundingBox_Denote(bbox=bbox2, mode=denote_mode)
iou, bboxs = box_iou_solve(bbox1, bbox2, mode=denote_mode)  # 计算IoU交并比

# 取出IoU转换解析后的bbox数据
r_bbox1 = bboxs[0]   
r_bbox2 = bboxs[1]
inter_bbox = bboxs[2]

# 利用数据进行绘制矩形框
# mode=True: bbox数据应该输入_xyxy
rect1 = draw_rectangle(r_bbox1, mode=True, color='b')
rect2 = draw_rectangle(r_bbox2, mode=True, color='b')
rect3 = draw_rectangle(inter_bbox, mode=True, color='y', fill=True)

ax.add_patch(rect1)  # 将绘制的矩形添加到图片上
ax.add_patch(rect2)
ax.add_patch(rect3)

plt.show()

结果图片

在这里插入图片描述

相关链接(持续更新)
目标检测(一)——边界框总结与代码实现(可完整实现)
目标检测(二)——锚框总结与代码实现(可完整实现)

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
### 回答1: IOU(交并比)是用于目标检测评估的常用度量。它表示两个区域的重叠部分占比。具体来说,它是两个区域的交集(重叠部分)除以两个区域的并集(总共的部分)。 IOU的计算公式如下: IOU = Area of Intersection / Area of Union IOU值越大,两个区域重叠度越大。通常来说,当IOU值大于0.5时,我们才认为两个区域是“相似”的。 下面是一个示例代码,用来计算两个矩形的IOU值: ``` def calculate_iou(box1, box2): # Calculate the x-y co-ordinates of the rectangles x1_left, y1_top, x1_right, y1_bottom = box1 x2_left, y2_top, x2_right, y2_bottom = box2 # Calculate the area of the rectangles rect1_area = (x1_right - x1_left) * (y1_bottom - y1_top) rect2_area = (x2_right - x2_left) * (y2_bottom - y2_top) # Find the overlapping area overlap_x1 = max(x1_left, x2_left) overlap_y1 = max(y1_top, y2_top) overlap_x2 = min(x1_right, x2_right) overlap_y2 = min(y1_bottom, y2_bottom) overlap_area = max(0, overlap_x2 - overlap_x1) * max(0, overlap_y2 - overlap_y1) # Calculate the IOU iou = overlap_area / (rect1_area + rect2_area - overlap_area) return iou ``` 在上面的代码中,输入参数`box1`和`box2`是两个矩形的坐标。每个矩形都是由左上角和右下角的坐标表示的。坐标用4元组表示,分别是左上 ### 回答2: 目标检测中的IoU(Intersection over Union)是一种衡量目标检测算法性能的指标,它用于计算预测框与真实标注框之间的重叠程度,通常取值范围在0到1之间。 以下是一个IoU计算的示例代码: ```python def calculate_iou(box1, box2): x1, y1, w1, h1 = box1 x2, y2, w2, h2 = box2 # 计算两个框的相交部分的坐标 xmin = max(x1, x2) ymin = max(y1, y2) xmax = min(x1 + w1, x2 + w2) ymax = min(y1 + h1, y2 + h2) # 计算相交部分的面积 inter_area = max(0, xmax - xmin + 1) * max(0, ymax - ymin + 1) # 计算并集面积 box1_area = (w1 + 1) * (h1 + 1) box2_area = (w2 + 1) * (h2 + 1) union_area = box1_area + box2_area - inter_area # 计算IoU iou = inter_area / union_area return iou ``` 以上代码中,`box1`和`box2`分别代表预测框和真实标注框的坐标以及宽高信息。通过计算交集的面积与并集的面积之比,可以得到IoU的值。 使用该代码示例,我们可以计算出两个框之间的IoU,从而评估目标检测算法的准确性和性能。 ### 回答3: 目标检测iou(Intersection over Union)表示交并比,是用于衡量两个目标框之间重叠程度的度量指标。下面是用Python编写的一个目标检测iou代码示例: ```python def compute_iou(box1, box2): # 计算两个目标框的重叠区域面积 x1 = max(box1[0], box2[0]) y1 = max(box1[1], box2[1]) x2 = min(box1[2], box2[2]) y2 = min(box1[3], box2[3]) intersection = max(0, x2 - x1) * max(0, y2 - y1) # 计算两个目标框的并集面积 area_box1 = (box1[2] - box1[0]) * (box1[3] - box1[1]) area_box2 = (box2[2] - box2[0]) * (box2[3] - box2[1]) union = area_box1 + area_box2 - intersection # 计算IOU iou = intersection / union return iou # 示例用法 box1 = [10, 10, 50, 50] box2 = [30, 30, 80, 80] iou = compute_iou(box1, box2) print("IOU:", iou) ``` 以上代码中,compute_iou函数接受两个目标框的坐标信息作为输入,使用相交矩形的面积除以两个目标框的并集面积来计算iou值。运行示例之后,输出的IOU值即为两个目标框的交并比。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NULL not error

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值