从代码学习深度学习 - 目标检测前置知识(一) PyTorch 版


前言

目标检测是计算机视觉领域中的一个核心问题,它的任务是识别图像中物体的类别并定位它们的位置。近年来,基于深度学习的目标检测算法取得了显著的进展。PyTorch 作为主流的深度学习框架之一,为目标检测的研究和应用提供了强大的支持。

本篇博客旨在通过代码实例,介绍目标检测任务中一些重要的前置知识,特别是与边界框 (Bounding Box) 和锚框 (Anchor Box) 相关的概念和常用工具函数。理解这些基础知识对于后续学习和实现更复杂的目标检测模型至关重要。我们将使用 PyTorch 来实现这些工具函数,并结合代码注释进行详细讲解。

完整的代码:下载链接


一、边界框 (Bounding Box)

在目标检测任务中,我们通常使用边界框来表示物体的位置。边界框是一个矩形框,能够框出图像中的目标物体。

1.1 边界框表示法转换

边界框有两种常见的表示方式:

  1. (左上角x, 左上角y, 右下角x, 右下角y):直接给出矩形框左上角和右下角顶点的坐标。
  2. (中心点x, 中心点y, 宽度, 高度):给出矩形框中心点的坐标以及矩形的宽度和高度。

在不同的算法或应用场景中,可能需要在这两种表示法之间进行转换。下面我们提供两个 PyTorch 函数来实现这两种表示法之间的相互转换。

import torch  # 导入 PyTorch 库,用于张量操作

def box_corner_to_center(boxes):
    """将边界框从(左上角,右下角)表示法转换为(中心点,宽度,高度)表示法

    该函数接收以(x1, y1, x2, y2)格式表示的边界框张量,其中:
        - (x1, y1):表示边界框左上角的坐标
        - (x2, y2):表示边界框右下角的坐标

    然后将其转换为(cx, cy, w, h)格式,其中:
        - (cx, cy):表示边界框中心点的坐标
        - w:表示边界框的宽度
        - h:表示边界框的高度

    参数:
        boxes (torch.Tensor): 形状为(N, 4)的张量,包含N个边界框的左上角和右下角坐标

    返回:
        torch.Tensor: 形状为(N, 4)的张量,包含N个边界框的中心点坐标、宽度和高度
    """
    # 分别提取所有边界框的左上角和右下角坐标
    x1, y1, x2, y2 = boxes[:, 0], boxes[:, 1], boxes[:, 2], boxes[:, 3]

    # 计算中心点坐标
    cx = (x1 + x2) / 2  # 中心点x坐标 = (左边界x + 右边界x) / 2
    cy = (y1 + y2) / 2  # 中心点y坐标 = (上边界y + 下边界y) / 2

    # 计算宽度和高度
    w = x2 - x1  # 宽度 = 右边界x - 左边界x
    h = y2 - y1  # 高度 = 下边界y - 上边界y

    # 将计算得到的中心点坐标、宽度和高度堆叠成新的张量
    boxes = torch.stack((cx, cy, w, h), axis=-1)

    return boxes


def box_center_to_corner(boxes):
    """将边界框从(中心点,宽度,高度)表示法转换为(左上角,右下角)表示法

    该函数接收以(cx, cy, w, h)格式表示的边界框张量,其中:
        - (cx, cy):表示边界框中心点的坐标
        - w:表示边界框的宽度
        - h:表示边界框的高度

    然后将其转换为(x1, y1, x2, y2)格式,其中:
        - (x1, y1):表示边界框左上角的坐标
        - (x2, y2):表示边界框右下角的坐标

    参数:
        boxes (torch.Tensor): 形状为(N, 4)的张量,包含N个边界框的中心点坐标、宽度和高度

    返回:
        torch.Tensor: 形状为(N, 4)的张量,包含N个边界框的左上角和右下角坐标
    """
    # 分别提取所有边界框的中心点坐标、宽度和高度
    cx, cy, w, h = boxes[:, 0], boxes[:, 1], boxes[:, 2], boxes[:, 3]

    # 计算左上角坐标
    x1 = cx - 0.5 * w  # 左边界x = 中心点x - 宽度/2
    y1 = cy - 0.5 * h  # 上边界y = 中心点y - 高度/2

    # 计算右下角坐标
    x2 = cx + 0.5 * w  # 右边界x = 中心点x + 宽度/2
    y2 = cy + 0.5 * h  # 下边界y = 中心点y + 高度/2

    # 将计算得到的左上角和右下角坐标堆叠成新的张量
    boxes = torch.stack((x1, y1, x2, y2), axis=-1)

    return boxes

1.2 绘制边界框

为了直观地展示边界框,我们可以使用 Matplotlib 库来绘制它们。下面的代码展示了如何将常用的边界框表示法转换为 Matplotlib 能够识别的矩形格式,并在图像上绘制出来。

import matplotlib.pyplot as plt  # 用于创建和操作 Matplotlib 图表
# 假设 utils_for_huitu.py 文件存在并已正确导入
import utils_for_huitu

utils_for_huitu.set_figsize() # 如果使用了自定义的绘图工具
img = plt.imread('img/03_catdog.jpg') # 示例图片路径
plt.imshow(img); # 显示示例图片

# 猫狗图像边界框坐标(左上角x,左上角y,右下角x,右下角y)
dog_bbox, cat_bbox = [60.0, 45.0, 378.0, 516.0], [400.0, 112.0, 655.0, 493.0]

def bbox_to_rect(bbox, color):
    """将边界框从(左上x, 左上y, 右下x, 右下y)格式转换为matplotlib的Rectangle格式

    在目标检测中,边界框通常使用左上角和右下角坐标表示,但matplotlib的Rectangle
    需要使用左上角坐标、宽度和高度来绘制矩形。此函数实现这一转换。

    参数:
        bbox (list): 包含4个元素的列表 [左上x, 左上y, 右下x, 右下y]
        color (str): 边界框的颜色,例如'red'、'blue'等

    返回:
        matplotlib.patches.Rectangle: 可添加到matplotlib图像上的矩形对象
    """
    # 使用左上角坐标作为矩形起点
    # 宽度 = 右下角x - 左上角x
    # 高度 = 右下角y - 左上角y
    return plt.Rectangle(
        xy=(bbox[0], bbox[1]),  # 矩形的左上角坐标
        width=bbox[2] - bbox[0],  # 矩形的宽度
        height=bbox[3] - bbox[1],  # 矩形的高度
        fill=False,  # 设置为不填充矩形内部
        edgecolor=color,  # 设置边界线颜色
        linewidth=2  # 设置边界线宽度为2
    )

# 下面的代码假设已有一个图像对象 img 和 matplotlib axes 对象 fig.axes
fig = plt.imshow(img)  # 示例:显示图像

# 添加狗的边界框,使用蓝色
fig.axes.add_patch(bbox_to_rect(dog_bbox, 'blue')) # 示例:绘制狗的边界框

# 添加猫的边界框,使用红色
fig.axes.add_patch(bbox_to_rect(cat_bbox, 'red')) # 示例:绘制猫的边界框
plt.show() # 示例:显示带有边界框的图像

在这里插入图片描述

在这里插入图片描述

二、锚框 (Anchor Box)

目标检测算法通常会在输入图像中采样大量的区域,然后判断这些区域中是否包含我们感兴趣的目标,并调整区域边界从而更准确地预测目标的 真实边界框 (ground-truth bounding box)。不同的模型使用的区域采样方法可能不同。其中一种方法是以每个像素为中心,生成多个具有不同缩放比 (scale) 和宽高比 (aspect ratio) 的边界框。这些边界框被称为 锚框 (anchor box)。

假设输入图像的高度为 h h h,宽度为 w w w。我们以图像的每个像素为中心生成不同形状的锚框:缩放比为 s ∈ ( 0 , 1 ] s \in (0, 1] s(0,1],宽高比为 r > 0 r > 0 r>0。那么锚框的宽度和高度分别是 w s r ws\sqrt{r} wsr h s / r hs/\sqrt{r} hs/r 。请注意,当中心位置给定时,已知宽和高的锚框是确定的。

为了生成多个不同形状的锚框,可以设置多个缩放比 s 1 , … , s n s_1, \dots, s_n s1,,sn 和多个宽高比 r 1 , … , r m r_1, \dots, r_m r1,,rm。当使用这些缩放比和宽高比的所有组合以每个像素为中心时,输入图像将总共有 w h n m whnm whnm 个锚框。但这样计算复杂度会很高。实践中,通常只考虑包含 s 1 s_1 s1 r 1 r_1 r1 的组合:

( s 1 , r 1 ) , ( s 1 , r 2 ) , … , ( s 1 , r m ) , ( s 2 , r 1 ) , … , ( s n , r 1 ) (s_1, r_1), (s_1, r_2), \dots, (s_1, r_m), (s_2, r_1), \dots, (s_n, r_1) (s1,r1),(s1,r2),,(s1,rm),(s2,r1),,(sn,r1)

也就是说,以同一像素为中心的锚框数量是 n + m − 1 n + m - 1 n+m1。对于整个输入图像,将共生成 w h ( n + m − 1 ) wh(n + m - 1) wh(n+m1) 个锚框。

下面是生成锚框的 PyTorch 函数实现:

import torch
torch.set_printoptions(2)  # 精简输出精度

def multibox_prior(data, sizes, ratios):
    """生成以每个像素为中心具有不同形状的锚框

    参数:
    data:输入图像张量,维度为(批量大小, 通道数, 高度, 宽度)
    sizes:锚框缩放比列表,元素个数为num_sizes,每个元素∈(0,1]
    ratios:锚框宽高比列表,元素个数为num_ratios,每个元素>0

    返回:
    输出张量,维度为(1, 像素总数*每像素锚框数, 4),表示所有锚框的坐标
    """
    # 获取输入数据的高度和宽度
    # in_height, in_width: 标量
    in_height, in_width = data.shape[-2:]

    # 获取设备信息以及尺寸和比例的数量
    # device: 字符串; num_sizes, num_ratios: 标量
    device, num_sizes, num_ratios = data.device, len(sizes), len(ratios)

    # 计算每个像素点产生的锚框数量 = 尺寸数 + 宽高比数 - 1
    # boxes_per_pixel: 标量
    boxes_per_pixel = (num_sizes + num_ratios - 1)

    # 将尺寸和比例转换为张量
    # size_tensor: 维度为(num_sizes,)
    # ratio_tensor: 维度为(num_ratios,)
    size_tensor = torch.tensor(sizes, device=device
<think>嗯,用户想从零开始学习深度学习中的目标检测,需要入门教程和实践指南。首先,我需要回忆目标检测的基础知识目标检测和图像分类不同,不仅要识别物体,还要定位位置,通常用边界框表示。常见的方法有R-CNN系列、YOLO、SSD等。用户是零基础,所以得从基础概念讲起,再逐步深入。 用户可能已经了解深度学习的基础,比如神经网络、卷积操作,但不确定,所以需要先巩固基础。比如,卷积层、池化层的作用,反向传播和梯度下降的原理。然后,目标检测特有的概念,比如锚框、非极大值抑制、IoU等,这些都需要解释清楚。 接下来是实践部分。用户可能需要具体的步骤,比如数据准备、模型选择、训练和评估。数据方面,常用PASCAL VOC、COCO数据集,可能需要数据增强。模型方面,YOLOv5或Faster R-CNN比较适合入门,尤其是YOLOv5的PyTorch实现,社区支持好,代码容易找到。 还要考虑用户的实际操作,比如代码示例。可能需要展示如何用PyTorch加载数据、定义模型、训练循环。但用户是零基础,所以代码不能太复杂,最好有详细的注释。另外,评估指标如mAP需要解释清楚,帮助用户理解模型性能。 用户可能遇到的问题包括环境配置、数据预处理、调参等。应该提醒他们先掌握Python和深度学习框架的基础,比如引用中的内容提到需要Python和数据结构基础,以及框架学习。实践项目部分建议从简单任务开始,逐步过渡到目标检测,符合用户的学习路径。 进阶部分可以提到模型压缩和部署,但用户目前可能更关注入门,所以放在后面。同时,生成的相关问题要围绕目标检测的基础、数据准备、模型选择、评估指标和优化方法,这样用户能进步探索。 需要确保回答结构清晰,分步骤讲解,每个步骤都有具体的内容和参考,比如引用中的基础知识储备和实践项目。还要注意LaTeX格式的正确使用,比如数学公式用$...$,独立公式用$$...$$,但用户的问题中没有涉及太多数学,可能主要集中在算法和模型结构上。 最后,检查引用是否相关,比如引用[1]提到基础知识储备和框架学习,引用[2]和[4]涉及神经网络实现,这些都能支持回答中的建议。确保所有引用标识正确,没有遗漏。</think>### 从零开始的深度学习目标检测实践指南 #### 1. **基础概念与前置知识** - **目标检测定义**:在图像中识别物体类别并定位其位置(边界框)[^4]。 - **与图像分类的区别**:目标检测需同时处理分类和定位任务,如$IoU$(交并比)用于评估定位精度: $$IoU = \frac{\text{预测框} \cap \text{真实框}}{\text{预测框} \cup \text{真实框}}$$ - **前置技能**:Python编程、PyTorch/TensorFlow基础、卷积神经网络(CNN)原理[^1]。 #### 2. **关键算法与技术** - **经典模型**: - **两阶段检测**:Faster R-CNN(通过区域提议网络生成候选框)[^2]。 - **单阶段检测**:YOLO系列(端到端直接预测边界框和类别)。 - **核心技术**: - **锚框(Anchor)**:预定义不同尺寸的参考框,用于捕捉多尺度目标。 - **非极大值抑制(NMS)**:去除冗余检测框,公式:$score = \text{分类置信度} \times IoU$。 #### 3. **实践步骤** **步骤1:数据准备** - **数据集**:PASCAL VOC、COCO(含标注的边界框和类别标签)。 - **数据增强**:随机裁剪、翻转、颜色扰动(代码示例): ```python import albumentations as A transform = A.Compose([A.HorizontalFlip(p=0.5), A.RandomBrightnessContrast()]) ``` **步骤2:模型搭建(以YOLOv5为例)** ```python import torch model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True) ``` **步骤3:训练与调参** - **损失函数**:多任务损失(分类损失 + 定位损失): $$L = \lambda_{\text{cls}}L_{\text{cls}} + \lambda_{\text{box}}L_{\text{box}}$$ - **优化器**:SGD或Adam,学习率衰减策略(如余弦退火)。 **步骤4:评估与部署** - **评估指标**:mAP(平均精度均值),计算各类别AP的平均值[^3]。 - **部署工具**:ONNX、TensorRT加速推理。 #### 4. **常见问题与优化** - **小目标检测困难**:使用特征金字塔网络(FPN)融合多尺度特征。 - **实时性要求**:选择轻量模型(如YOLO-Nano、MobileNet-SSD)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值