系列文章目录
文章目录
- 系列文章目录
- 前言
- [1 功能分块](#1 功能分块)
-
- [1.1 骨干网络 Backbone](#1.1 骨干网络 Backbone)
- [1.2 颈部网络 Neck](#1.2 颈部网络 Neck)
- [1.3 头部网络 Head](#1.3 头部网络 Head)
-
- [1.3.1 边界框回归头](#1.3.1 边界框回归头)
- [1.3.2 分类头](#1.3.2 分类头)
- [2 关键概念](#2 关键概念)
- [3 典型算法](#3 典型算法)
-
- [3.1 NMS](#3.1 NMS)
- [3.2 IoU](#3.2 IoU)
- 总结
前言
1 功能分块
1.1 骨干网络 Backbone
- 它的任务是把一张图片的关键信息浓缩出来,比如形状、纹理、颜色等特征,就像把水果榨成汁一样,保留精华,去掉多余水分(无关背景)。
1.2 颈部网络 Neck
1.3 头部网络 Head
1.3.1 边界框回归头
1.3.2 分类头
2 关键概念
3 典型算法
3.1 NMS
3.2 IoU
IoU(Intersection over Union):衡量两个边界框(Bounding Box)之间重叠程度和匹配度,常用于目标检测任务中评估预测框 Predicted Box 与真实框 Ground Truth Box的匹配度。相比于 Jaccard Index
-
其值范围在 [ 0 , 1 ] [0,1] [0,1],
1
表示完全重叠,0
表示无重叠。 -
数学定义:
I o U = 交集面积 并集面积 \mathrm{IoU} = \frac{交集面积}{并集面积} IoU=并集面积交集面积
- 即:
IoU = A inter A union = A inter A box1 + A box2 − A inter \text{IoU} = \frac{A_{\text{inter}}}{A_{\text{union}}} = \frac{A_{\text{inter}}}{A_{\text{box1}} + A_{\text{box2}} - A_{\text{inter}}} IoU=AunionAinter=Abox1+Abox2−AinterAinter
- 计算步骤:
- 交集坐标
- 左上角:取两框左上坐标的较大值
- 右下角:取两框右下坐标的较小值
- 若右下坐标 < 左上坐标,则交集面积为
0
x LeftTop = max ( x 1 a , x 1 b ) , y LeftTop = min ( y 1 a , y 1 b ) x_{\text{LeftTop}} = \max(x_1^a, x_1^b), \quad y_{\text{LeftTop}} = \min(y_1^a, y_1^b) xLeftTop=max(x1a,x1b),yLeftTop=min(y1a,y1b)
x RightBottom = min ( x 2 a , x 2 b ) , y RightBottom = max ( y 2 a , y 2 b ) x_{\text{RightBottom}} = \min(x_2^a, x_2^b), \quad y_{\text{RightBottom}} = \max(y_2^a, y_2^b) xRightBottom=min(x2a,x2b),yRightBottom=max(y2a,y2b)
-
面积计算
- 交集面积 = max ( 0 , x RightBottom − x LeftTop ) × max ( 0 , y RightBottom − y LeftTop ) \max(0, x_{\text{RightBottom}} - x_{\text{LeftTop}}) \times \max(0, y_{\text{RightBottom}} - y_{\text{LeftTop}}) max(0,xRightBottom−xLeftTop)×max(0,yRightBottom−yLeftTop)
- 并集面积 = 框1面积 + 框2面积 - 交集面积
- 代码实践
python
import matplotlib.pyplot as plt
import matplotlib.patches as pts
# 现在定义一个函数,接收两个参数,都是两个点坐标,以数组的形式
def calculate_iou(box1, box2):
"""
计算两个边界框之间的 IoU (Intersection over Union)
参数:
box1: 第一个边界框,格式为 [x1, y1, x2, y2]
box2: 第二个边界框,格式为 [x1, y1, x2, y2]
返回:
iou: 两个边界框之间的 IoU 值
"""
# 解析边界框坐标
x1_box1, y1_box1, x2_box1, y2_box1 = box1
x1_box2, y1_box2, x2_box2, y2_box2 = box2
# 确保坐标的有效性
assert x1_box1 < x2_box1, f"无效的 box1 x坐标: {x1_box1} >= {x2_box1}"
assert y1_box1 < y2_box1, f"无效的 box1 y坐标: {y1_box1} >= {y2_box1}"
assert x1_box2 < x2_box2, f"无效的 box2 x坐标: {x1_box2} >= {x2_box2}"
assert y1_box2 < y2_box2, f"无效的 box2 y坐标: {y1_box2} >= {y2_box2}"
# 计算交集区域的坐标
x_left = max(x1_box1, x1_box2)
y_top = max(y1_box1, y1_box2)
x_right = min(x2_box1, x2_box2)
y_bottom = min(y2_box1, y2_box2)
# 检查是否有交集
if x_right < x_left or y_bottom < y_top:
return 0.0
# 计算交集区域面积
intersection_area = (x_right - x_left) * (y_bottom - y_top)
# 计算两个边界框各自的面积
area_box1 = (x2_box1 - x1_box1) * (y2_box1 - y1_box1)
area_box2 = (x2_box2 - x1_box2) * (y2_box2 - y1_box2)
# 计算并集区域面积
union_area = area_box1 + area_box2 - intersection_area
# 计算IOU,并避免除零错误
if union_area == 0:
iou = 0
else:
iou = intersection_area / union_area
return iou
# 定义一个函数,根据坐标画出两个框
def plot_boxes(box1, box2):
fig, ax = plt.subplots()
# 绘制第一个框
rect1 = pts.Rectangle((box1[0], box1[1]), box1[2]-box1[0], box1[3]-box1[1], linewidth=1, edgecolor='r', facecolor='none')
ax.add_patch(rect1)
# 绘制第二个框
rect2 = pts.Rectangle((box2[0], box2[1]), box2[2]-box2[0], box2[3]-box2[1], linewidth=1, edgecolor='b', facecolor='none')
ax.add_patch(rect2)
# 设置坐标轴范围
ax.set_xlim(0, 100)
ax.set_ylim(0, 100)
# 显示图像
plt.show()
# 测试用例
if __name__ == "__main__":
# # 测试1: 完全重叠
box_a = [10, 10, 50, 50]
# box_b = [10, 10, 50, 50]
# iou = calculate_iou(box_a, box_b)
# print(f"测试1 (完全重叠): IoU = {iou:.2f} (预期: 1.00)")
# 测试2: 部分重叠
box_c = [20, 20, 60, 60]
iou = calculate_iou(box_a, box_c)
print(f"测试2 (部分重叠): IoU = {iou:.2f} (预期: 0.47)")
# 绘制框
plot_boxes(box_a, box_c)
- 效果图
总结
- 分段介绍YOLO的框架和基本原理。