YOLOv8 基础实战:模型结构解析、权重下载与推理

YOLOv8 是 Ultralytics 团队在 2023 年初推出的目标检测框架。说实话,从 v5 到 v8 的跨度挺大的——不光是模型结构改了,连训练和推理的 API 都重新设计了。我个人习惯把 v8 看作一个「工程化更彻底」的版本,它把数据增强、模型导出、部署转换都集成到了一个库里。

这一章我们先把 YOLOv8 的模型结构拆开看看,然后下载官方权重,最后用预训练模型跑几个推理 demo。嗯,动手之前先把原理理清楚。

YOLOv8 模型结构总览

YOLOv8 延续了「Backbone + Neck + Head」的三段式设计。但和 v5 相比,每个模块都有调整。我画了一张结构图,方便你对照着看。

YOLOv8 模型结构图 Backbone(CSPDarknet 改进版) Conv + BN + SiLU C2f 模块 ×N SPPF 多尺度特征输出 Neck(FPN + PAN 结构) 上采样 + 特征融合 下采样 + 特征融合 3 个尺度输出 Head(解耦检测头) 分类分支 (Conv + Conv + 分类头) 回归分支 (Conv + Conv + 回归头) 输出 (边界框 + 类别) C2f = Cross Stage Partial with 2 convolutions + feature fusion,是 v8 的核心改进模块

核心模块详解

1. Backbone:CSPDarknet 的进化

YOLOv8 的 Backbone 还是基于 CSPDarknet 的架构,但把原来的 C3 模块换成了 C2f。C2f 的全称是「Cross Stage Partial with 2 convolutions and feature fusion」——说白了就是让梯度在跨层连接时流得更顺畅。

我在项目中对比过 C3 和 C2f 的参数量:同样深度下,C2f 的 FLOPs 略高一点,但 mAP 能提升 0.5~1 个点。对于追求精度的场景,这个 trade-off 是值得的。

模块 输入通道 输出通道 层数 说明
Conv + BN + SiLU 3 64 1 初始下采样,步长 2
C2f ×3 64 128 3 特征提取,步长 2
C2f ×6 128 256 6 深层特征,步长 2
C2f ×6 256 512 6 最深层,步长 2
SPPF 512 512 1 空间金字塔池化
小技巧:SPPF 是 SPP 的加速版。它用三个串联的 5×5 最大池化代替了原来的并行多尺度池化,计算量更小,感受野不变。我在部署到边缘设备时特别喜欢这个设计。

2. Neck:FPN + PAN 的经典组合

Neck 部分负责把 Backbone 输出的多尺度特征融合起来。YOLOv8 沿用了 FPN(自顶向下)和 PAN(自底向上)的双向融合结构。这样做的好处是:小目标能从高层语义中受益,大目标也能保留底层细节。

具体来说,Neck 会输出三个尺度的特征图:

  • P3(80×80):负责小目标检测
  • P4(40×40):负责中目标检测
  • P5(20×20):负责大目标检测

3. Head:解耦检测头

这是 YOLOv8 和 v5 最大的区别。v5 的 Head 是耦合的——分类和回归共享同一组卷积。v8 把这两个任务拆开了:

  • 分类分支:输出每个 anchor 的类别概率
  • 回归分支:输出边界框的坐标偏移

为什么要解耦?我在做行人检测时遇到过一个问题:分类和回归对特征的需求其实不一样。分类更关注「是什么」,回归更关注「在哪里」。共享特征会导致两者互相干扰。解耦之后,每个分支可以专注自己的任务,收敛更快。

注意:YOLOv8 已经不再使用 anchor-based 的方法了,而是改用 anchor-free。这意味着输出层的通道数计算方式变了——每个特征点只预测一个目标,不再有多个 anchor box。如果你从 v5 迁移过来,这个变化要特别留意。

官方权重下载

YOLOv8 提供了 5 个不同规模的预训练模型,从轻量到高精度都有。我个人习惯在项目初期先用 nano 版本跑通流程,确认数据没问题后再换大模型。

模型 参数量 FLOPs mAP@0.5:0.95 推理速度(T4) 适用场景
YOLOv8n 3.2M 8.7G 37.3 1.2ms 移动端、边缘设备
YOLOv8s 11.2M 28.6G 44.9 1.4ms 轻量级服务器
YOLOv8m 25.9M 78.9G 50.2 2.0ms 通用场景
YOLOv8l 43.7M 165.2G 52.9 2.7ms 高精度场景
YOLOv8x 68.2M 257.8G 53.9 3.5ms 极致精度

下载权重很简单,一行代码搞定:

# 自动下载 YOLOv8n 权重(首次运行会自动下载)
from ultralytics import YOLO
model = YOLO('yolov8n.pt')  # 会自动从 GitHub Release 下载

权重文件会保存在当前目录下。如果你想手动下载,也可以去 Ultralytics 的 GitHub Release 页面找。嗯,不过我建议直接用代码自动下载,省事。

使用预训练模型进行推理

推理是 YOLOv8 最爽的部分——API 设计得非常简洁。我们分三种场景来看:图片、视频、摄像头。

图片推理

from ultralytics import YOLO

# 加载模型
model = YOLO('yolov8n.pt')

# 单张图片推理
results = model('bus.jpg')

# 批量图片推理
results = model(['img1.jpg', 'img2.jpg', 'img3.jpg'])

# 查看结果
for result in results:
    boxes = result.boxes  # 边界框
    print(f"检测到 {len(boxes)} 个目标")
    for box in boxes:
        x1, y1, x2, y2 = box.xyxy[0].tolist()
        conf = box.conf[0].item()
        cls = box.cls[0].item()
        print(f"类别: {int(cls)}, 置信度: {conf:.2f}, 坐标: ({x1:.0f}, {y1:.0f}, {x2:.0f}, {y2:.0f})")
输出说明:results 对象包含检测框、类别、置信度、分割掩码(如果是分割模型)等属性。你可以直接调用 result.show() 显示图片,或者 result.save() 保存结果。

视频推理

视频推理其实就是逐帧处理。YOLOv8 封装好了,你只需要传入视频路径:

model = YOLO('yolov8n.pt')

# 视频推理,自动保存结果
results = model('test_video.mp4', save=True)

# 如果想实时显示,可以用 stream=True
results = model('test_video.mp4', stream=True)
for result in results:
    # 处理每一帧
    pass

我在项目中处理过一段 10 分钟的 4K 视频,用 YOLOv8m 跑,T4 显卡上大概花了 3 分钟。如果换成 YOLOv8n,能压缩到 1 分钟以内。所以视频推理时,我建议先评估一下精度要求,再选模型。

摄像头实时推理

摄像头推理和视频推理几乎一样,只是输入源变成了摄像头 ID:

model = YOLO('yolov8n.pt')

# 使用摄像头 0(默认摄像头)
results = model(source=0, show=True, conf=0.5)

# 或者用更底层的写法
import cv2
cap = cv2.VideoCapture(0)
while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break
    results = model(frame)
    annotated_frame = results[0].plot()
    cv2.imshow('YOLOv8 Detection', annotated_frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()
避坑指南:我曾经在 Jetson Nano 上跑摄像头推理,发现帧率只有 5 FPS。后来发现是摄像头分辨率设得太高(1920×1080)。把分辨率降到 640×480 后,帧率直接翻了三倍。所以摄像头推理时,记得调整输入尺寸。

推理参数调优

YOLOv8 的推理函数支持很多参数,我列几个常用的:

参数 默认值 说明
conf 0.25 置信度阈值,低于此值的检测框会被过滤
iou 0.7 NMS 的 IoU 阈值,值越小重复框越少
imgsz 640 输入图片尺寸,越大精度越高但速度越慢
max_det 300 每张图片最大检测目标数
device None 指定设备,如 'cpu'、'cuda:0'

举个例子,如果你想要高精度检测:

results = model('bus.jpg', conf=0.5, iou=0.5, imgsz=1280)

如果你想要快速推理:

results = model('bus.jpg', conf=0.3, iou=0.7, imgsz=320)
经验之谈:我一般把 conf 设为 0.25~0.5 之间。太低会出很多假阳性,太高会漏检。具体值取决于你的场景——如果是安防监控,宁可漏检也不能误报,那就把 conf 调高到 0.6 以上。

本章小结

这一章我们做了三件事:

  • 拆解了 YOLOv8 的 Backbone、Neck、Head 结构,重点讲了 C2f 和解耦检测头
  • 下载了官方预训练权重,了解了 5 个模型的性能差异
  • 用预训练模型跑了图片、视频、摄像头三种推理场景

说实话,YOLOv8 的 API 设计得确实好——几行代码就能跑通一个完整的检测流程。但别急着高兴,真正的工作量在后面:数据标注、模型训练、调参、部署……这些才是硬骨头。