深度学习-计算机视觉-物体检测与边缘框实现
在图像分类任务中,我们通常基于一个关键假设:图像中仅包含一个主要物体对象,我们的目标是精准地识别出这个物体的类别。这种任务设定简洁明了,主要聚焦于物体类别的判断,适合对单一主体进行分类的场景。
然而,在现实世界的许多应用场景中,图像往往包含多个我们感兴趣的物体或目标。此时,我们的需求不再局限于了解这些目标“是什么”,还希望明确它们“在哪里”。
为应对这一挑战,计算机视觉领域提出了目标检测(Object Detection)和目标识别(Object Recognition)任务。这两种任务相辅相成,目标检测侧重于定位图像中目标物体的具体位置(通常以边界框形式表示),而目标识别则侧重于对检测到的目标物体进行类别判断。通过结合两者,我们可以在复杂的图像场景中,既准确识别出多个目标物体的类别,又明确它们的空间位置,从而为后续的分析和决策提供更全面的信息支持。
在目标检测中,我们通常使用边界框(bounding box)来描述对象的空间位置。
- 边界框是矩形的,由矩形左上角的x和y坐以及右下角的x和y坐标决定。 (左上x,左上y,右下x,右下y)
- 另一种常用的边界框表示方法是边界框中心的(x, y)轴坐标以及框的宽度和高度。(中心x,中心y,宽,高)
下面加载本节将使用的示例图像。【代码来自《动手学深度学习》】
可以看到图像左边是一只狗,右边是一只猫。 它们是这张图像里的两个主要目标。
import torch
from d2l import torch as d2ld2l.set_figsize()
img = d2l.plt.imread('../img/catdog.jpg')
d2l.plt.imshow(img);
定义在这两种表示法之间进行转换的函数:
box_corner_to_center
从两角表示法转换为中心宽度表示法,box_center_to_corner
从中心宽度表示法转换为两角表示法。
#@save
def box_corner_to_center(boxes):"""从(左上,右下)转换到(中间,宽度,高度)"""x1, y1, x2, y2 = boxes[:, 0], boxes[:, 1], boxes[:, 2], boxes[:, 3]cx = (x1 + x2) / 2cy = (y1 + y2) / 2w = x2 - x1h = y2 - y1boxes = torch.stack((cx, cy, w, h), axis=-1)return boxes#@save
def box_center_to_corner(boxes):"""从(中间,宽度,高度)转换到(左上,右下)"""cx, cy, w, h = boxes[:, 0], boxes[:, 1], boxes[:, 2], boxes[:, 3]x1 = cx - 0.5 * wy1 = cy - 0.5 * hx2 = cx + 0.5 * wy2 = cy + 0.5 * hboxes = torch.stack((x1, y1, x2, y2), axis=-1)return boxes
备注:torch.stack
是 PyTorch 中一个用于连接多个张量(tensors)的函数。它在指定的维度上将多个张量堆叠在一起,形成一个新的张量。新张量的维度比原张量多一个维度。其中,axis=-1表示沿着最后一个维度进行堆叠。axis=0表示沿着第一个维度进行堆叠。
import torch# 创建两个一维张量
tensor1 = torch.tensor([1, 2, 3])
tensor2 = torch.tensor([4, 5, 6])# 沿着最后一个维度(axis=-1)和第一个维度(axis=0)进行堆叠
stacked_tensor = torch.stack([tensor1, tensor2], axis=-1)
stacked_tensor_dim0 = torch.stack([tensor1, tensor2], axis=0)输出:
tensor([[1, 4],[2, 5],[3, 6]])tensor([[1, 2, 3],[4, 5, 6]])
根据坐标信息定义图像中狗和猫的边界框:
# bbox是边界框的英文缩写
dog_bbox, cat_bbox = [60.0, 45.0, 378.0, 516.0], [400.0, 112.0, 655.0, 493.0]boxes = torch.tensor((dog_bbox, cat_bbox))
box_center_to_corner(box_corner_to_center(boxes)) == boxes输出:
tensor([[True, True, True, True],[True, True, True, True]])
我们可以将边界框在图中画出,以检查其是否准确。
画之前,我们定义一个辅助函数bbox_to_rect
。 它将边界框表示成matplotlib
的边界框格式。
#@save
def bbox_to_rect(bbox, color):# 将边界框(左上x,左上y,右下x,右下y)格式转换成matplotlib格式:# ((左上x,左上y),宽,高)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'));