第五章:计算机视觉(Computer Vision)- 项目实战之目标检测实战

第二部分:目标检测实战:中国交通标志检测

第一节:经典目标检测算法 YOLOv8 流程详解

1. 项目背景

交通标志检测是智能交通系统(ITS)、自动驾驶和辅助驾驶(ADAS)的关键任务。
中国交通标志种类繁多,形状各异(圆形、三角形、矩形等),且分布环境复杂:

  • 白天/夜晚光照变化;

  • 天气干扰(雨、雾、雪);

  • 遮挡与小目标问题。

因此,选择 YOLOv8 进行目标检测,具有高精度、速度快、部署灵活等优势。


2. YOLOv8 模型结构概述

YOLOv8 延续 YOLO 系列思想,但引入了 Anchor-Free 设计,更简洁高效。

其整体结构分为三部分:

  1. Backbone(骨干网络):特征提取,采用 CSPDarknet 改进版,残差结构增强表示能力。

  2. Neck(特征融合):采用 PAN-FPN,融合不同层级的特征,提升小目标检测效果。

  3. Head(检测头):Anchor-Free,直接预测目标的中心点、宽高与类别概率。


3. YOLOv8 的训练与推理流程
(1) 数据准备
  • 数据集:使用 中国交通标志检测数据集(例如 TT100K 或自建数据集)

  • 标注格式:采用 COCO JSON 或 YOLO txt 格式,每个目标由 类别 x_center y_center width height 表示。

  • 数据增强

    • Mosaic:将 4 张图片拼接,提高小目标样本数量;

    • MixUp:混合样本,提升泛化能力;

    • 颜色扰动:增强光照鲁棒性。

(2) 模型训练流程
  1. 输入图像:尺寸一般为 640×640;

  2. Backbone 提取特征:得到多层级特征图;

  3. Neck 融合特征:PAN-FPN 融合高低层语义信息;

  4. Head 预测:输出每个网格点的 类别 + 边界框位置 + 置信度

  5. Loss 函数

    • 分类损失:BCE Loss

    • 边界框回归:IoU/GIoU/CIoU Loss

    • 置信度损失:Binary Cross Entropy

(3) 模型推理流程
  1. 输入交通场景图片;

  2. YOLOv8 Backbone + Neck 提取多尺度特征;

  3. Head 输出预测框(包含类别、位置、置信度);

  4. NMS(非极大值抑制) 去除冗余框;

  5. 最终输出检测结果,如 “限速 60km/h 标志”、“禁止鸣笛标志”等。


4. YOLOv8 在中国交通标志检测中的优势
  1. Anchor-Free → 避免 anchor 参数调优,提升小目标检测能力。

  2. 轻量化 & 部署友好 → 支持 ONNX / TensorRT / OpenVINO / CoreML,可直接部署在嵌入式设备、行车记录仪或智能驾驶系统。

  3. 高鲁棒性 → 数据增强与多尺度特征融合,提升对复杂天气、光照、遮挡场景的适应能力。

  4. 高精度 → 在 COCO/TT100K 等数据集上达到 SOTA 水平,尤其对小目标交通标志检测有优势。


5. 流程总结图(简化版)
输入交通图像 → 数据预处理 → YOLOv8 Backbone 特征提取
          ↓
      Neck 特征融合 (PAN-FPN)
          ↓
     Head 输出预测框 (Anchor-Free)
          ↓
   NMS 去冗余 → 输出交通标志类别 + 位置

6. 应用场景
  • 自动驾驶车辆的交通标志识别模块;

  • 智能交通监控系统(违章检测、道路安全预警);

  • 车载辅助驾驶系统(驾驶员提醒、道路指示解析)。


7.代码实现
1) 环境与依赖

建议 Python >= 3.8,GPU 环境(CUDA 11.x / 12.x)下运行效果最佳。

推荐安装(示例):

# 推荐用虚拟环境
python -m venv venv && source venv/bin/activate

# 核心依赖(Ultralytics 提供 YOLOv8)
pip install ultralytics torch torchvision timm opencv-python matplotlib seaborn albumentations -U
# 或者如果你需要 TensorRT 导出、ONNX 等,请按官方文档安装对应包

说明:ultralytics 包提供 yolov8 的训练/推理 Python API 和 CLI。若没有 ultralytics,也可以用官方/社区实现,但这里用 ultralytics 最省事。


2) 数据准备(YOLO 格式)与 data.yaml

我们建议使用 YOLO 格式(每张图一个 .txt 标签文件,格式:class x_center y_center width height,均为归一化到 [0,1] 的相对坐标)。目录示例:

dataset/
  images/
    train/
      img0001.jpg
      img0002.jpg
    val/
      img0101.jpg
  labels/
    train/
      img0001.txt
      img0002.txt
    val/
      img0101.txt
  names.txt   # 可选:每行一个类名

data.yaml(项目根目录下)示例:

# data.yaml
train: ./dataset/images/train
val:   ./dataset/images/val
# optional test: ./dataset/images/test

# 类名示例(交通标志示意)
names:
  0: speed_limit_20
  1: speed_limit_30
  2: speed_limit_40
  3: speed_limit_50
  4: speed_limit_60
  5: no_entry
  6: stop
  7: pedestrian_crossing
  8: yield
  9: parking
# 如果类别很多,你也可以引用一个 names.txt 文件,或用 dict 列表

如果你使用 COCO 格式(TT100K 有 COCO 转换脚本),也可以直接用 data.yaml 指向 train.json/val.jsonultralytics 支持 COCO。


3) train_yolov8.py — 训练脚本(Python API,支持断点续训、混合精度)
# train_yolov8.py
from ultralytics import YOLO
import argparse
import os

def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('--data', type=str, default='data.yaml', help='path to data yaml')
    parser.add_argument('--model', type=str, default='yolov8n.pt', help='backbone / pretrained model')
    parser.add_argument('--epochs', type=int, default=50)
    parser.add_argument('--batch', type=int, default=16)
    parser.add_argument('--imgsz', type=int, default=640)
    parser.add_argument('--device', type=str, default='0')  # 'cpu' or '0' or '0,1'
    parser.add_argument('--project', type=str, default='runs/exp')
    parser.add_argument('--name', type=str, default='yolov8_tt100k')
    parser.add_argument('--resume', action='store_true', help='resume from last checkpoint')
    return parser.parse_args()

if __name__ == '__main__':
    args = parse_args()

    # 创建模型对象(可直接使用官方预训练权重 yolov8n.pt,yolov8s.pt,yolov8m.pt,yolov8l.pt,yolov8x.pt)
    model = YOLO(args.model)

    # 训练
    model.train(
        data=args.data,
        imgsz=args.imgsz,
        epochs=args.epochs,
        batch=args.batch,
        device=args.device,
        project=args.project,
        name=args.name,
        resume=args.resume,
        optimizer='AdamW',        # 可选 SGD/Adam/AdamW
        lr0=1e-3,                 # 初始学习率
        warmup_epochs=3,
        lr_scheduler='cosine',    # 可选 step, cosine
        val=True,
        save=True,                # 保存最佳权重
        save_period=5,            # 每 N epoch 保存一次
        mixed_precision=True      # 混合精度训练(AMP)
    )

    # 训练结束后,最好调用 model.val() 查看验证结果
    # model.val()  # 可选

运行示例:

python train_yolov8.py --data data.yaml --model yolov8s.pt --epochs 100 --batch 16 --imgsz 640

建议:

  • 资源充足时使用 yolov8s / yolov8m;资源受限可用 yolov8n(nano)。

  • 若样本小或类别不均衡,开启强数据增强(Mosaic、MixUp),或使用 Class-balanced sampling、FocalLoss(见下文)。


4) 自定义数据增强(可选)—— 使用 Albumentations(更强)

你可以在 ultralytics 训练中传 augment=True,或使用 Dataset 层自定义预处理。下面示例是在训练前准备 pipeline 的想法(若要深度定制请写自定义 dataloader)。


5) detect_yolov8.py — 推理脚本(单图 / 批量 / 可视化)
# detect_yolov8.py
from ultralytics import YOLO
import cv2
import matplotlib.pyplot as plt
import numpy as np
import argparse

def visualize(img, boxes, scores, classes, names, save_path=None):
    # img: BGR numpy
    img = img.copy()
    for (x1, y1, x2, y2), conf, cls in zip(boxes, scores, classes):
        label = f"{names[int(cls)]} {conf:.2f}"
        # draw rectangle
        cv2.rectangle(img, (int(x1), int(y1)), (int(x2), int(y2)), (0,255,0), 2)
        cv2.putText(img, label, (int(x1), int(y1)-6), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 1)
    if save_path:
        cv2.imwrite(save_path, img)
    return img

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('--weights', type=str, default='runs/exp/weights/best.pt')
    parser.add_argument('--img', type=str, default='test.jpg')
    parser.add_argument('--conf', type=float, default=0.25)
    parser.add_argument('--iou', type=float, default=0.45)
    args = parser.parse_args()

    model = YOLO(args.weights)
    res = model.predict(source=args.img, conf=args.conf, iou=args.iou, save=False, imgsz=640)

    # res 是一个 Results 对象列表(batch),提取信息如下:
    r = res[0]
    boxes = r.boxes.xyxy.cpu().numpy() if r.boxes is not None else np.array([])
    scores = r.boxes.conf.cpu().numpy() if r.boxes is not None else np.array([])
    classes = r.boxes.cls.cpu().numpy() if r.boxes is not None else np.array([])
    names = model.names

    img = cv2.imread(args.img)
    vis = visualize(img, boxes, scores, classes, names, save_path='pred.png')
    # 显示
    plt.imshow(cv2.cvtColor(vis, cv2.COLOR_BGR2RGB))
    plt.axis('off')
    plt.show()

运行示例:

python detect_yolov8.py --weights runs/exp/yolov8_tt100k/weights/best.pt --img ./dataset/images/val/img0101.jpg

6) 验证与评估(mAP / COCO-style)

使用 ultralyticsmodel.val() 可以直接评估 COCO 风格的 mAP:

from ultralytics import YOLO
model = YOLO('runs/exp/yolov8_tt100k/weights/best.pt')
metrics = model.val(data='data.yaml', iou=0.5)  # mAP@0.5
print(metrics)
# COCO mAP(0.5:0.95):
metrics_all = model.val(data='data.yaml', iou=(0.5,0.95))

若你有 coco 格式的 val.json,ultralytics 会自动读取并计算 COCO 风格指标(AP50, AP75, AP@[.5:.95], AR, etc)。


7) 导出模型(ONNX / TensorRT / CoreML)

ultralytics 支持导出:

from ultralytics import YOLO
model = YOLO('runs/exp/yolov8_tt100k/weights/best.pt')
# 导出为 ONNX
model.export(format='onnx', imgsz=640)   # 生成 best.onnx

# 导出到 TensorRT (如果系统已安装 tensorrt)
model.export(format='tensorrt')

导出注意事项:

  • ONNX 导出后,使用 TensorRT / ONNXRuntime 可进一步加速;

  • 若需要移动端部署,可导出 CoreML / TFLite(ultralytics 支持部分格式);

  • 导出前使用 model.model.fuse() 做层融合可提高推理速度。


8) 工程化与调优建议(针对交通标志 / 小目标场景)
  1. 输入尺寸与多尺度训练

    • 交通标志往往较小,建议采用 imgsz=640 或更大尺寸;训练时用 multi-scale(ultralytics 默认支持)。

  2. 增强(必做)

    • Mosaic、MixUp、RandomRotate、ColorJitter、Cutout 等对小目标非常有帮助。

    • 在训练时启用 augment=True

  3. 损失函数调整

    • 使用 CIoU / SIoU 损失能提升框定位精度;

    • 若类别高度不平衡可尝试 Focal Loss 或 class-weight。

  4. 正负样本与 NMS

    • NMS 阈值 (iou) 与 conf 阈值会影响 precision/recall trade-off。测试不同组合。

  5. 复合策略

    • 训练阶段使用 yolov8s / m,当精度稳定后可用 yolov8l/x 做蒸馏或微调;

    • 使用模型蒸馏(Teacher → Student)可在轻量化模型上保留精度。

  6. 小目标技巧

    • 提升输入分辨率;

    • 在 head/neck 使用更强的特征融合(更深的 PAN-FPN);

    • 使用更多的正样本采样策略。

  7. 度量与错误分析

    • 常用 mAP@0.5 和 mAP@[0.5:0.95];

    • 画 PR 曲线、混淆矩阵,重点分析哪些类常混淆或漏检;

    • 保存失败样本用于针对性增强/标注修正。


9) 典型训练命令(命令行)
# ultralytics CLI 方式也很方便:
yolo detect train data=data.yaml model=yolov8s.pt epochs=100 imgsz=640 batch=16 project=runs/traffic name=yolov8_tt100k

10) 简易示例流程(从零到部署)
  1. 准备 YOLO 格式数据(images & labels)并写好 data.yaml

  2. 选预训练权重 yolov8s.pt(速度/准确度平衡)或 yolov8m.pt(更高精度)。

  3. 运行 python train_yolov8.py 或 ultralytics CLI,观察 runs/exp 的训练曲线(loss, box, cls, metrics)。

  4. detect_yolov8.py 在验证集上可视化预测结果,调整阈值/augment/超参。

  5. model.val() 获取 mAP 等指标,做报表。

  6. 导出 ONNX / TensorRT,部署到推理服务器或边缘设备(Jetson / NPU /手机)。


11) 附:常见问题与排查建议
  • 训练损失不下降:检查数据标注格式是否正确、学习率是否太低/太高、是否加载预训练权重。

  • 模型过拟合:增加数据增强、使用 dropout、早停或减少模型容量。

  • 小目标漏检:增大输入尺寸、增强小目标样本、增加 neck 的特征融合能力。

  • 训练过慢 / 显存不足:开启混合精度(AMP),降低 batch,或使用 yolov8n

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐