1. 前言
在上一篇中,我们初步认识了**物体检测(Object Detection)**任务。
物体检测和图像分类最大的区别在于:
图像分类只需要判断"图中是什么",而物体检测不仅要判断"是什么",还要回答"在哪里"。
那么,计算机究竟该如何表示一个目标在图像中的位置呢?
最常见、最基础的方法,就是使用边界框(bounding box)。
边界框可以理解为:
用一个矩形框,把图像中的目标圈出来。这样模型不仅知道目标属于哪一类,还能知道它位于图像的哪个区域。
这一节我们就来学习:
-
什么是边界框
-
边界框的表示方法
-
如何在图像上绘制边界框
-
用代码实现边界框可视化
2. 什么是边界框
边界框,英文叫 bounding box ,也叫边界盒 或目标框。
它本质上就是一个矩形框,用来标记目标在图像中的位置。
例如,在一张街道图片中,如果有一辆汽车,那么我们可以画一个矩形把汽车框起来;
如果还有一个行人,就再画一个矩形把行人框起来。
这样一来,每个目标都能通过一个矩形区域表示出来。
所以在物体检测中,一个检测结果通常包含两部分信息:
-
类别信息:这个目标是什么
-
位置信息:这个目标在哪里
而位置信息,最常见的表示方式就是边界框。
3. 边界框的两种常见表示方式
边界框虽然本质上是一个矩形,但在程序中需要用数值来表示。
常见的表示方式主要有两种。
3.1 左上角 + 右下角坐标
这是最常见的一种表示方式。
设边界框左上角坐标为:
(x_min, y_min)
右下角坐标为:
(x_max, y_max)
那么整个边界框就可以写成:
(x_min, y_min, x_max, y_max)
这里:
-
x_min表示左上角的横坐标 -
y_min表示左上角的纵坐标 -
x_max表示右下角的横坐标 -
y_max表示右下角的纵坐标
这种方式非常直观,因为它直接告诉我们矩形框的两个顶点位置。
3.2 左上角坐标 + 宽和高
另一种常见方式是:
-
矩形左上角坐标:
(x, y) -
矩形宽度:
w -
矩形高度:
h
于是边界框表示为:
(x, y, w, h)
这种方式在某些数据集标注格式中经常出现,例如 COCO 中就常见这种表示。
它表示的是:
-
从
(x, y)开始 -
向右延伸
w -
向下延伸
h
4. 两种表示方式之间的转换
这两种边界框表示方式本质上是等价的,可以互相转换。
4.1 从角点坐标转换为宽高形式
已知:
(x_min, y_min, x_max, y_max)
则:
w = x_max - x_min
h = y_max - y_min
所以可以转换成:
(x_min, y_min, w, h)
4.2 从宽高形式转换为角点坐标
已知:
(x, y, w, h)
则:
x_max = x + w
y_max = y + h
所以可以转换成:
(x, y, x + w, y + h)
5. 为什么边界框很重要
边界框是整个物体检测任务的基础。
因为后面很多核心概念,都是围绕边界框展开的,比如:
-
锚框(Anchor Box)
-
交并比(IoU)
-
非极大值抑制(NMS)
-
边界框回归(Bounding Box Regression)
可以说:
如果不理解边界框,后面的检测模型基本就很难真正看懂。
边界框虽然只是一个简单的矩形,但它承担了"目标定位"的核心作用。
6. 在图像中绘制边界框
理解了边界框的概念后,一个自然的问题就是:
如何把边界框画到图像上?
在 Python 中,我们通常可以借助 matplotlib 和 PIL 来实现。
在《动手学深度学习》中,常见做法是先读取图片,再指定边界框坐标,然后将矩形画到图片上。
7. 边界框绘制代码示例
下面给出一个典型的代码示例。
7.1 导入库
import torch
from d2l import torch as d2l
这里我们使用 d2l 提供的一些绘图工具。
7.2 读取图片
img = d2l.plt.imread('catdog.jpg')
d2l.plt.imshow(img)
这段代码的作用是:
-
读取一张名为
catdog.jpg的图片 -
将图片显示出来
如果图片中有一只猫和一只狗,那么接下来我们就可以给它们分别设置边界框。
7.3 定义边界框
dog_bbox = [60.0, 45.0, 378.0, 516.0]
cat_bbox = [400.0, 112.0, 655.0, 493.0]
这里每个边界框都采用:
(x_min, y_min, x_max, y_max)
的形式。
例如:
-
dog_bbox表示狗的边界框 -
cat_bbox表示猫的边界框
7.4 定义绘制边界框函数
def bbox_to_rect(bbox, color):
return d2l.plt.Rectangle(
xy=(bbox[0], bbox[1]),
width=bbox[2] - bbox[0],
height=bbox[3] - bbox[1],
fill=False,
edgecolor=color,
linewidth=2
)
这段函数的作用是把边界框转换成 matplotlib 可绘制的矩形对象。
我们逐行理解一下:
-
xy=(bbox[0], bbox[1])表示矩形左上角坐标
-
width=bbox[2] - bbox[0]表示矩形宽度
-
height=bbox[3] - bbox[1]表示矩形高度
-
fill=False表示矩形内部不填充颜色,只画边框
-
edgecolor=color指定边界框颜色
-
linewidth=2指定边框线宽
7.5 在图像上画出边界框
fig = d2l.plt.imshow(img)
fig.axes.add_patch(bbox_to_rect(dog_bbox, 'blue'))
fig.axes.add_patch(bbox_to_rect(cat_bbox, 'red'))
d2l.plt.show()
运行后,我们就能看到:
-
狗被蓝色框圈出来
-
猫被红色框圈出来
这样,图像中的目标位置就被可视化出来了。
8. 代码完整示例
把上面的代码合在一起,完整如下:
import torch
from d2l import torch as d2l
img = d2l.plt.imread('catdog.jpg')
dog_bbox = [60.0, 45.0, 378.0, 516.0]
cat_bbox = [400.0, 112.0, 655.0, 493.0]
def bbox_to_rect(bbox, color):
return d2l.plt.Rectangle(
xy=(bbox[0], bbox[1]),
width=bbox[2] - bbox[0],
height=bbox[3] - bbox[1],
fill=False,
edgecolor=color,
linewidth=2
)
fig = d2l.plt.imshow(img)
fig.axes.add_patch(bbox_to_rect(dog_bbox, 'blue'))
fig.axes.add_patch(bbox_to_rect(cat_bbox, 'red'))
d2l.plt.show()
9. 代码理解总结
这个例子虽然不复杂,但非常重要,因为它第一次把"检测中的位置表示"真正落到了代码中。
整个流程其实很清晰:
第一步:读取图片
img = d2l.plt.imread('catdog.jpg')
把图片加载进来。
第二步:给出边界框坐标
dog_bbox = [60.0, 45.0, 378.0, 516.0]
cat_bbox = [400.0, 112.0, 655.0, 493.0]
用数值描述目标的位置。
第三步:将坐标转成矩形对象
bbox_to_rect(bbox, color)
这是"数据表示"到"图像显示"的关键一步。
第四步:把矩形加到图片上
fig.axes.add_patch(...)
最终完成边界框绘制。
10. 边界框在后续检测模型中的作用
在真正的检测模型中,边界框并不是人工写死的,而是模型预测出来的。
也就是说,未来我们训练的模型会自动输出类似这样的结果:
[类别, 置信度, x_min, y_min, x_max, y_max]
例如:
['dog', 0.95, 60, 45, 378, 516]
这表示:
-
模型认为这是狗
-
置信度为 95%
-
它的位置由这个边界框确定
所以边界框不仅仅是一个可视化工具,更是检测模型输出结果的核心组成部分。
11. 本节总结
这一节我们学习了物体检测中最基础的内容:边界框。
重点可以总结为以下几点。
11.1 边界框用于表示目标位置
它本质上是一个矩形框,用来把图像中的目标圈出来。
11.2 边界框有两种常见表示方式
第一种:
(x_min, y_min, x_max, y_max)
第二种:
(x, y, w, h)
两种形式可以互相转换。
11.3 可以借助 matplotlib 将边界框画到图片上
通过定义矩形对象,并添加到图像坐标轴中,就能完成目标框绘制。
11.4 边界框是后续检测知识的基础
后面的锚框、IoU、NMS、SSD、YOLO 等内容,都会建立在边界框的基础之上。
12. 学习感悟
边界框这个知识点看起来并不复杂,甚至可以说只是"画矩形框"。
但它其实是物体检测中最基础、最关键的表示方式之一。
很多时候,深度学习里真正重要的并不一定是最复杂的公式,而是这种最基础的任务定义和表示方法。
因为只有先明确:
-
目标怎么表示
-
位置怎么编码
-
结果怎么可视化
后面的模型设计才有意义。
所以,边界框虽然是检测章节中比较靠前的小知识点,但绝对不能轻视。