YOLOv8实战:从零构建车辆检测系统(保姆级教程+完整代码)
"🚀 本教程手把手教你用YOLOv8实现车辆检测实战!从环境搭建、数据集处理到模型训练与推理,完整覆盖目标检测全流程。基于Kaggle真实交通数据集,详细讲解YOLO格式转换、配置文件编写等核心技巧,特别适合CV初学者快速入门。附完整代码和可视化方案,轻松掌握工业级检测系统开发。"
前言
Hello,大家好,我是
GISer Liu
😁,一名热爱AI技术的GIS开发者。本系列是作者参加DataWhale 2025年6月份Yolo原理组队学习的技术笔记文档,这里整理为博客,希望能帮助Yolo的开发者少走弯路!
🚀 终于来到了 YOLOv8 实战入门教程!在目标检测领域,YOLO(You Only Look Once)系列以其高效和精准而闻名。本文旨在提供一个从零开始、保姆级的实践指南,帮助初学者快速掌握使用 ultralytics
框架和 YOLOv8 模型完成一个完整的项目。
为了避免与其他dw学习者文章同质化,作者不采用常见的猫狗或官方COCO数据集,而是从kaggle选择了一个更具挑战性也更实用的场景——城市交通车辆检测。通过这个项目,你将学到:
- 完整的项目流程:从环境搭建、数据集准备,到模型训练、推理和结果分析,体验AI项目开发全链路。
- YOLOv8核心操作:掌握
ultralytics
库的核心API,理解如何配置、训练和使用YOLO模型。 - 实践中的思考与泛化:学习如何将一个基础教程(如笔记中的犬种识别)的知识,迁移和应用到一个全新的项目中。
无论你是刚入门的大学生,还是希望将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, 'r') as f:
for line in f:
parts = line.strip().split(' ')
labels.append(parts[0])
bboxes.append([float(p) for p in parts[1:]])
# 绘制标注框
result_image = plot_box(image, bboxes, labels)
plt.subplot(2, 2, i + 1)
# Matplotlib 显示的是RGB, OpenCV读的是BGR,需要转换
plt.imshow(cv2.cvtColor(result_image, cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.tight_layout()
plt.show()
# --- 中文注释:可视化训练集中的4个样本 ---
print("可视化训练集样本...")
plot_samples(
image_dir=os.path.join(DATA_ROOT, 'train/images'),
label_dir=os.path.join(DATA_ROOT, 'train/labels'),
num_samples=4
)
思考🤔:为什么要花时间做可视化?这一步能帮你快速发现潜在问题,例如:标签错误、类别ID不匹配、标注框异常等。所谓“Garbage in, garbage out”,高质量的数据是模型性能的根本保障。
3. 创建data.yaml
配置文件
这个YAML文件是连接你的数据集和YOLOv8训练引擎的桥梁。它告诉模型:
- 训练图片和标签在哪里 (
train
) - 验证图片和标签在哪里 (
val
) - 测试图片和标签在哪里 (
test
) - 总共有哪些类别,以及它们的名称 (
names
)
# --- 中文注释:创建并配置 data.yaml ---
# 数据集提供的YAML文件可能路径不正确,我们需要动态修改它
source_yaml_path = os.path.join(DATA_ROOT, 'data.yaml')
# 将其复制到一个可写目录,例如当前工作目录
destination_yaml_path = './data.yaml'
shutil.copyfile(source_yaml_path, destination_yaml_path)
print(f"已将 {source_yaml_path} 复制到 {destination_yaml_path}")
# --- 读取并修改YAML文件 ---
with open(destination_yaml_path, 'r') as f:
data_yaml = yaml.safe_load(f)
# 更新'train'和'val'的路径为绝对路径,确保YOLO能找到它们
data_yaml['train'] = os.path.join(DATA_ROOT, 'train/images')
data_yaml['val'] = os.path.join(DATA_ROOT, 'valid/images')
data_yaml['test'] = os.path.join(DATA_ROOT, 'test/images')
# 确保 'names' 字段与我们的 class_names 变量一致
data_yaml['names'] = class_names
# 删除 'path' 字段,因为我们已经为 train/val/test 提供了绝对路径
if 'path' in data_yaml:
del data_yaml['path']
# --- 将更新后的配置写回文件 ---
with open(destination_yaml_path, 'w') as f:
yaml.dump(data_yaml, f)
print(f"已更新 {destination_yaml_path} 的内容:")
with open(destination_yaml_path, 'r') as f:
print(f.read())
现在,我们有了一个指向正确数据路径的 data.yaml
文件,可以随时用于训练。
在云环境中有时候,文件是只读的,因此需要copy一份复制到可写位置后了再更新,代码如下:
import yaml
import shutil
import os
# 定义data.yaml的源路径和目标路径
source_yaml_path = '/kaggle/input/cars-detection/Cars Detection/data.yaml'
destination_yaml_path = '/content/data.yaml'
# 将data.yaml文件复制到可写位置
shutil.copyfile(source_yaml_path, destination_yaml_path)
print(f"已复制 {source_yaml_path} 到 {destination_yaml_path}")
# 读取复制的data.yaml文件
with open(destination_yaml_path, 'r') as f:
data_yaml = yaml.safe_load(f)
# 更新'train'和'val'路径为相对于data.yaml文件的路径
data_yaml['train'] = '/kaggle/input/cars-detection/Cars Detection/train/images'
data_yaml['val'] = '/kaggle/input/cars-detection/Cars Detection/valid/images'
# data.yaml中的'path'参数通常用作相对路径的基础目录
# 由于我们下面使用绝对路径进行训练和验证,可以将其设置为空字符串或相关基础路径(如果需要)
# 为了清晰起见,我们将其设置为数据集的基础目录(尽管下面的绝对路径并不严格需要它)
data_yaml['path'] = '/kaggle/input/cars-detection/Cars Detection'
# 将更新后的内容写回复制的data.yaml文件
with open(destination_yaml_path, 'w') as f:
yaml.dump(data_yaml, f)
print(f"已更新 {destination_yaml_path} 中的正确路径。")
四、模型训练:释放GPU的力量
万事俱备,只欠东风!现在我们可以开始训练模型了。
# --- 中文注释:模型训练 ---
# --- 1. 加载模型 ---
# 我们从头开始构建一个YOLOv8n (nano) 模型。
# 'yolov8n.yaml' 定义了模型的结构。
# 你也可以使用预训练权重 'yolov8n.pt' 来进行微调(迁移学习),这通常会更快收敛。
model = YOLO("yolov8n.yaml")
# --- 2. 开始训练 ---
# data: 指向我们刚刚配置好的 data.yaml 文件
# epochs: 训练轮次。对于这个数据集,100轮是一个不错的起点。
# imgsz: 训练时图像的尺寸。640是YOLOv8的常用尺寸。
# device: 使用哪个设备进行训练,'cpu'或'0' (代表第一块GPU)。
results = model.train(
data=destination_yaml_path,
epochs=100,
imgsz=640,
device=0, # 如果有GPU,设置为0;如果没有,设置为'cpu'
name='yolov8n_car_detection' # 本次实验的名称,结果将保存在 runs/detect/yolov8n_car_detection 目录下
)
# --- 3. 验证模型性能 ---
# 训练完成后,会自动在验证集上进行一次评估。
# 我们也可以手动调用 model.val() 来重新评估。
# 'best.pt' 是在验证集上表现最好的模型权重。
print("在验证集上评估模型性能...")
metrics = model.val(data=destination_yaml_path)
思考 🤔:
- 模型选择:为什么用
yolov8n
?n
(nano) 是YOLOv8系列中最小的模型,参数最少,训练速度最快,非常适合入门和快速迭代。如果追求更高精度,可以尝试yolov8s
,yolov8m
等更大的模型,但需要更多的计算资源和训练时间。- 超参数:
epochs
,imgsz
,batch
(批大小)是影响训练最重要的几个参数。epochs
太少模型学不会,太多会过拟合。imgsz
更大通常精度更高但更慢。batch
越大训练越稳定,但越吃显存。你需要根据自己的硬件情况进行调整。
训练过程中的日志、图表(如损失曲线、PR曲线)和模型权重都会保存在runs/detect/yolov8n_car_detection
目录下,这是我们分析模型表现的重要依据。
五、模型推理:让模型“看”世界
训练完成后,我们得到了一个性能不错的车辆检测模型!让我们用它来检测一些新的图像和视频。
1. 图像推理
我们从测试集中随机选择一张图片进行预测。
# --- 单张图片推理 ---
from ultralytics import YOLO
import os
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
# 1. 指定模型路径(确认这个路径存在)
best_model_path = '/content/runs/detect/train8/weights/best.pt'
print(f"模型路径: {best_model_path}")
# 2. 加载模型
model = YOLO(best_model_path)
# 3. 指定测试图片(改成你实际存在的图片路径)
test_image_path = '/kaggle/input/cars-detection/Cars Detection/test/images/08c8b73e0c2e296e_jpg.rf.effa65856584463c08848031cab357b9.jpg' # 示例路径
print(f"测试图片: {test_image_path}")
# 4. 运行预测(会自动创建输出目录)
results = model.predict(
source=test_image_path,
project='/content/runs/detect', # 基础目录
name='predict', # 会在基础目录下创建这个子目录
exist_ok=True, # 允许覆盖已有目录
save=True # 确保保存预测结果
)
# 5. 查找最新预测结果
predict_dir = '/content/runs/detect/predict' # 这是预测结果的实际保存位置
predicted_image_path = os.path.join(predict_dir, os.path.basename(test_image_path))
# 6. 显示结果
if os.path.exists(predicted_image_path):
print(f"预测结果保存在: {predicted_image_path}")
img = mpimg.imread(predicted_image_path)
plt.figure(figsize=(10, 8))
plt.imshow(img)
plt.title("predict result")
plt.axis('off')
plt.show()
else:
print("预测失败!可能原因:")
print(f"1. 测试图片路径不存在: {test_image_path}")
print(f"2. 模型路径不正确: {best_model_path}")
print(f"3. 输出目录无写入权限: {predict_dir}")
print("请检查以上路径是否正确!")
2. 视频推理
视频推理同样简单,只需将 source
指向视频文件即可。
# --- 中文注释:视频推理 ---
# 首先,你需要准备一个测试视频。这里我们假设在 /kaggle/input/testvideo/ 目录下有一个 Input.mp4
# 请将 'path/to/your/video.mp4' 替换为你的视频真实路径
test_video_path = '/content/runs/detect/video/cars.mp4'
# 检查视频文件是否存在
if not os.path.exists(test_video_path):
print(f"错误:视频文件 '{test_video_path}' 不存在。请修改路径或上传一个测试视频。")
else:
# 使用CLI进行视频推理
!yolo task=detect mode=predict model={best_model_path} source={test_video_path}
# --- 中文注释:在Notebook中播放结果视频 ---
# 定义一个函数,用于在Jupyter/Kaggle环境中显示视频
from IPython.display import HTML
from base64 import b64encode
def show_video(file_name, width=640):
mp4 = open(file_name,'rb').read()
data_url = "data:video/mp4;base64," + b64encode(mp4).decode()
return HTML(f"""
<video width="{width}" controls>
<source src="{data_url}" type="video/mp4">
</video>""")
# 找到最新的预测结果文件夹
list_of_predict_dirs = glob.glob('./runs/detect/predict*')
latest_predict_dir = max(list_of_predict_dirs, key=os.path.getctime)
# 找到预测生成的视频文件(可能是.avi或.mp4)
output_video_path = glob.glob(os.path.join(latest_predict_dir, '*.avi'))
if not output_video_path:
output_video_path = glob.glob(os.path.join(latest_predict_dir, '*.mp4'))
if output_video_path:
# 如果原始输出是avi,最好转换为mp4以获得更好的浏览器兼容性
final_video_path = os.path.join(latest_predict_dir, 'output.mp4')
!ffmpeg -y -loglevel panic -i {output_video_path[0]} {final_video_path}
print("视频推理完成,正在显示结果...")
display(show_video(final_video_path, width=960))
else:
print("未找到输出的视频文件。")
总结
本文我们从零开始,完整地走完了一个基于YOLOv8的车辆检测项目。通过这个过程,我们学习了代码的实现,更重要的是建立了解决实际问题的思维框架。
回顾一下,我们取得的成果:
✅ 掌握了项目全流程:从环境搭建到模型部署,亲手实践了AI项目的每一个关键步骤。
✅ 学会了泛化与迁移:将基础教程的知识成功应用到了一个全新的、更复杂的车辆检测场景中,这是非常有价值的能力。
✅ 理解了YOLOv8的核心用法:熟悉了ultralytics
库,学会了如何准备数据、配置data.yaml
、训练模型以及进行推理。
目标检测是一个很有趣的领域。希望这个实战教程能为各位读者打开一扇门,激发你探索更多可能性的热情。接下来你可以尝试去创造一个属于你自己的目标检测应用😎🎉!
今天我们就学习到这里🏆🎉👌!
文章参考
- YOLO系列官方论文:
- 核心数据集与代码:
拓展阅读
- Ultralytics GitHub 仓库 (YOLOv3/v5/v8 的主流实现)
- 作者的算法专栏CSDN 博客专栏(包含更多YOLO技术文章)
💖 感谢您的耐心阅读!
如果您觉得本文对您理解和实践YOLOv8有所帮助,请考虑点赞、收藏或分享给更多有需要的朋友。您的支持是我持续创作优质内容的动力!欢迎在评论区交流讨论,共同进步。

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。
更多推荐
所有评论(0)