YOLOv8实战:从零构建车辆检测系统(保姆级教程+完整代码)


前言

Hello,大家好,我是GISer Liu😁,一名热爱AI技术的GIS开发者。本系列是作者参加DataWhale 2025年6月份Yolo原理组队学习的技术笔记文档,这里整理为博客,希望能帮助Yolo的开发者少走弯路!

🚀 终于来到了 YOLOv8 实战入门教程!在目标检测领域,YOLO(You Only Look Once)系列以其高效和精准而闻名。本文旨在提供一个从零开始、保姆级的实践指南,帮助初学者快速掌握使用 ultralytics 框架和 YOLOv8 模型完成一个完整的项目。

为了避免与其他dw学习者文章同质化,作者不采用常见的猫狗或官方COCO数据集,而是从kaggle选择了一个更具挑战性也更实用的场景——城市交通车辆检测。通过这个项目,你将学到:

  1. 完整的项目流程:从环境搭建、数据集准备,到模型训练、推理和结果分析,体验AI项目开发全链路。
  2. YOLOv8核心操作:掌握 ultralytics 库的核心API,理解如何配置、训练和使用YOLO模型。
  3. 实践中的思考与泛化:学习如何将一个基础教程(如笔记中的犬种识别)的知识,迁移和应用到一个全新的项目中。

无论你是刚入门的大学生,还是希望将YOLOv8应用于自己项目的开发者,相信本教程都能为你提供坚实的起点。OK,让我们开始吧!


一、项目整体流程概览

在正式开始编码之前,我们先通过一个流程图来了解整个项目的生命周期。这有助于我们建立一个清晰的“地图”,知道自己身在何处,下一步要去哪里。

核心步骤解读

  • 环境搭建:创建独立的Python环境并安装所有必需的库,这是“善其事,利其器”的第一步。
  • 数据集准备:获取车辆检测数据集,并理解其目录结构和标注格式。
  • 数据探索:可视化部分样本和标注,确保数据质量,这是模型成功的基础。
  • 配置文件:编写data.yaml,这是告知YOLOv8训练数据在哪、类别是什么的“说明书”。
  • 模型训练:加载YOLOv8模型,并使用我们的数据对其进行“教导”。
  • 模型推理:使用训练好的模型在新的图片和视频上进行预测,检验学习成果。
  • 结果分析:查看模型的性能指标,并可视化预测结果。

二、环境搭建:构建你的炼丹炉

一个稳定、隔离的开发环境是项目顺利进行的前提。我们将使用 conda 来管理Python环境。

1. 创建并激活Conda环境

打开你的终端(Terminal),执行以下命令。这会创建一个名为 yolo-car,使用Python 3.10 的新环境。

# -- 创建conda环境 --
# (在terminal中运行,假设你已有anaconda/miniconda)
conda create -n yolo-car python=3.10 -y

# -- 激活环境 --
conda activate yolo-car

# -- 安装ipykernel,以便在Jupyter Notebook中使用此环境 --
# 记得在Notebook中选择内核为'yolo-car'
conda install ipykernel -y

2. 安装核心依赖库

环境激活后,我们需要安装PyTorch、Ultralytics等核心库。

① 安装PyTorch

PyTorch是驱动我们模型训练的深度学习框架。请访问 PyTorch官网,根据你的操作系统和GPU情况(是否有NVIDIA显卡,CUDA版本等)选择对应的安装命令。以下是一个基于CUDA 12.1的示例:

# 推荐使用conda安装,能更好地处理CUDA依赖
conda install pytorch torchvision torchaudio pytorch-cuda=12.1 -c pytorch -c nvidia -y

思考与探索 🤔:为什么推荐用conda安装PyTorch?因为conda在处理复杂的二进制依赖(如CUDA工具包)时比pip更强大,可以减少很多环境配置的麻烦。

② 安装Ultralytics及其他工具

ultralytics 是YOLOv8的官方库,封装了训练、推理等所有功能。我们同时安装其他辅助库。

# -- 安装YOLOv8官方库 --
pip install ultralytics

# -- 安装其他常用工具库 --
# numpy, pandas: 数据处理
# matplotlib, seaborn: 可视化
# opencv-python: 图像处理
# pyyaml: 用于处理YAML配置文件
pip install numpy pandas matplotlib seaborn opencv-python pyyaml --quiet

至此,我们的“炼丹炉”就搭建完毕了!

③在线云环境

作者这里使用的是colab的在线云环境,如果前面安装不太方便,可以直接在云环境中运行;

作者这里使用的是colab!🙂👌


三、数据集:模型的“食物”

本项目使用Kaggle上的 Cars Detection Dataset,其中包含了五类常见车辆的图像和YOLO格式的标注。

1. 数据集下载与观察

如果你在使用Kaggle Notebook环境,可以直接通过kagglehub下载。本地用户需要先安装kaggle库并配置好API密钥后,使用API下载或直接在网站上手动下载解压。

# --- 中文注释:导入必要的库 ---
import os
import glob as glob  # 用于查找文件路径
import matplotlib.pyplot as plt # 用于绘图
import cv2 # OpenCV库,用于图像处理
import requests # 用于网络请求
import random # 用于生成随机数
import numpy as np # 数值计算库
import shutil # 用于文件操作
import yaml # 用于读写YAML文件

from ultralytics import YOLO # 导入YOLOv8核心库

# 设置随机种子,保证实验可复现
np.random.seed(42)

# --- 中文注释:在Kaggle环境中下载并挂载数据集 ---
# 如果你在本地运行,请手动下载并解压数据集,然后将路径指向你的本地文件夹
# Kaggle Notebook 会自动处理以下代码
import kagglehub
# 下载车辆检测数据集
abdallahwagih_cars_detection_path = kagglehub.dataset_download('abdallahwagih/cars-detection')

print('数据集导入完成.')
print(f'数据集路径: {abdallahwagih_cars_detection_path}')

# 定义数据集根目录 (请根据你的实际情况修改)
# 在Kaggle中,路径通常是 '/kaggle/input/cars-detection/Cars Detection'
DATA_ROOT = os.path.join(abdallahwagih_cars_detection_path, 'Cars Detection')

在线云环境中数据会被下载到根目录下面:

2. 数据探索:眼见为实

在训练前,务必检查一下数据!看看图片是否正常,标注框是否准确。YOLO的标注格式是 [class_id, x_center, y_center, width, height],所有值都是相对于图像宽高归一化的。

我们编写几个辅助函数来可视化它们。

# --- 中文注释:定义类别名称和颜色 ---
# 必须与数据集中label的id顺序对应: 0: Ambulance, 1: Bus, ...
class_names = ['Ambulance', 'Bus', 'Car', 'Motorcycle', 'Truck']
colors = np.random.uniform(0, 255, size=(len(class_names), 3)) # 为每个类别随机生成一种颜色

# --- 中文注释:将YOLO格式的坐标转换为边角坐标 (xmin, ymin, xmax, ymax) ---
def yolo2bbox(bboxes):
    """
    将 [x_center, y_center, width, height] 格式的YOLO bbox
    转换为 [xmin, ymin, xmax, ymax] 格式
    """
    xmin = bboxes[0] - bboxes[2] / 2
    ymin = bboxes[1] - bboxes[3] / 2
    xmax = bboxes[0] + bboxes[2] / 2
    ymax = bboxes[1] + bboxes[3] / 2
    return xmin, ymin, xmax, ymax

# --- 中文注释:在图像上绘制边界框和标签 ---
def plot_box(image, bboxes, labels):
    """
    输入图像、bbox列表和标签列表,返回绘制好的图像
    """
    # 获取图像的原始高和宽,用于反归一化
    h, w, _ = image.shape
    for box_num, box in enumerate(bboxes):
        # 将YOLO格式坐标转为边角坐标
        x1, y1, x2, y2 = yolo2bbox(box)

        # 反归一化,得到在原图上的像素坐标
        xmin = int(x1 * w)
        ymin = int(y1 * h)
        xmax = int(x2 * w)
        ymax = int(y2 * h)

        # 获取当前框对应的类别名称
        class_name = class_names[int(labels[box_num])]
        # 获取该类别的颜色
        color = colors[class_names.index(class_name)]

        # 使用OpenCV绘制矩形框
        cv2.rectangle(image, (xmin, ymin), (xmax, ymax), color=color, thickness=2)

        # --- 绘制类别标签背景和文字 ---
        font_scale = 0.8
        font_thickness = 2
        text_size, _ = cv2.getTextSize(class_name, cv2.FONT_HERSHEY_SIMPLEX, font_scale, font_thickness)
        text_w, text_h = text_size
        # 绘制填充的矩形作为文字背景
        cv2.rectangle(image, (xmin, ymin - text_h - 5), (xmin + text_w, ymin - 5), color, -1)
        # 写入类别文字
        cv2.putText(image, class_name, (xmin, ymin - 5), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (255, 255, 255), font_thickness)
        
    return image

# --- 中文注释:随机抽取并展示样本 ---
def plot_samples(image_dir, label_dir, num_samples=4):
    """
    从给定的目录中随机选择N个样本并进行可视化
    """
    all_image_paths = glob.glob(os.path.join(image_dir, '*.jpg'))
    all_label_paths = {os.path.basename(p).split('.')[0]: p for p in glob.glob(os.path.join(label_dir, '*.txt'))}
    
    plt.figure(figsize=(15, 12))
    
    # 随机选择 N 张图片
    selected_images = random.sample(all_image_paths, num_samples)
    
    for i, image_path in enumerate(selected_images):
        image = cv2.imread(image_path)
        
        # 找到对应的标签文件
        image_name = os.path.basename(image_path).split('.')[0]
        label_path = all_label_paths.get(image_name)
        
        bboxes = []
        labels = []
        if label_path:
            with open(label_path, <