简介:一套基于YOLOv8的图像识别Python工程包,适合具备Python基础、正在学习深度学习目标检测的开发者,可用于安全监控、工业质检、自动驾驶等场景的对象识别与动手实践。资源共包含53个文件,打包为18.4MB的rar压缩包,主要文件类型包括模型训练/测试/推理脚本、jpg样例图片、yolov8n.pt预训练权重以及中英文说明文档,目录划分清晰,便于按流程查阅。项目提供从数据处理、模型训练、精度评估到本地图片推理、视频检测、摄像头实时识别的完整代码链,并附有测试图片与训练脚本,可帮助读者快速跑通YOLOv8流程,理解每步实现细节。资源还展示了从数据准备到模型部署的工程化思路,读者可根据自带说明将模型迁移到自己的图像数据集,直接复用或二次修改。已有148人学习,适合作为课程设计参考或入门到进阶的实践素材。 刚接触YOLOv8的人,十个里有八个会在同一道坎上卡住:教程看了一堆,代码复制下来也能跑,但换了自己的图片、自己的需求,立刻不知道该从哪儿下手。这篇我就把整个流程掰开揉碎讲一遍,从环境配置到训练自己的数据集,再到"摄像头为什么会重复识别同一个物体"这类实战高频问题,一次说清楚。文章会全程使用Python和YOLOv8官方代码,你照着敲就能出结果。
1. YOLOv8到底能干哪些活:先把适用边界摸清楚
很多刚入门的朋友把YOLOv8当成一个"万能识别器",觉得给它一张图它就能告诉你"这是猫""这是狗""这是车"。这个理解方向是对的,但有个关键前提:YOLOv8只负责做目标检测、实例分割、姿态估计和图像分类这四类任务,具体能认出什么,取决于你喂给它的权重文件和数据,它本身不具备常识。
官方Ultralytics仓库把YOLOv8分成了几个主模型:
yolov8n.pt、yolov8s.pt、yolov8m.pt、yolov8l.pt、yolov8x.pt,从n(nano)到x(超大),体积和精度依次递增,适合不同的算力环境。- 后缀带
-seg的是实例分割模型,能输出每个目标的轮廓mask;带-pose的是姿态估计模型,可以输出人体关键点;带-cls的是纯分类模型。
拿yolov8n.pt来说,它是在COCO数据集上预训练好的,能检测80类日常物体——人、车、猫、狗、杯子、椅子这些都在里面。如果你想识别特定的东西,比如"检测流水线上有没有螺丝缺失",那COCO预训练权重就帮不上忙了,得自己标注数据、训练模型,这部分我放到第3节详细讲。
从网络结构角度看,YOLOv8相比YOLOv5有几个明显的改动。骨干网络继续沿用CSPDarknet结构,但C2f模块替代了原来的C3模块,简单理解就是梯度分流更丰富,特征提取更充分,模型做深了也不容易出现梯度消失。颈部是FPN+PAN的经典组合,负责融合不同尺度的特征;检测头改成了Anchor-Free的Decoupled Head,也就是分类和回归分支分开了,每个分支自己学自己的。这个改动换来的是更快的收敛速度和更好的回归精度,再配合TaskAlignedAssigner做正样本匹配和DFL损失函数,整体在小目标和遮挡场景的表现都有提升。
还有一个经常被新手忽略的点:YOLOv8里的"v8"指的是模型的版本,不是必须用8系列权重。比如yolov8n.yaml和yolov8n.pt这两个,前者是网络结构的定义文件,只有结构,没有训练好的参数;后者是已经在COCO上训练完毕的权重。你加载yolov8n.pt就能直接对图片做推理,但加载yolov8n.yaml之后还得先train(),因为初始化的权重数值是随机的。
经验:入门阶段老老实实用官方
ultralytics包就够了,不要去GitHub上找各种"魔改版"代码,算法本身没吃透之前,改结构只会让你踩进更大的坑里。
2. 环境准备与"要不要GPU"的真实答案
很多人的第一个疑问是:跑YOLOv8是不是必须要显卡?这个问题的标准答案是——推理可以不必须,但训练建议一定要。
我用CPU(i5-12400)跑过yolov8n的推理,一张普通照片大约耗时1到3秒,分批处理还能接受,但跑到yolov8x就会明显感觉到卡顿,单张可能要8秒以上。到了训练环节,CPU跑一个epoch,哪怕是最小的n模型,COCO级别的数据集也得按小时算,而同样的活,一块GTX 1660Ti能快30倍不止。
所以如果你手头是GTX 1660Ti、RTX 3060、RTX 4060这种入门级显卡,完全够用。1660Ti是6GB显存,实测训练yolov8s模型,batch size设16没问题;yolov8m就得把batch降到8,再大就会显存溢出。训练自己的小数据集,用yolov8n或yolov8s起步是最稳的。没有GPU的话,可以先跑通推理代码,训练部分建议用云服务器,或者干脆在Google Colab上做。
环境安装部分,最核心的是三样:Python、PyTorch和Ultralytics库。Python装3.8到3.11之间的版本都行,太新的3.13有时会在某些依赖库的编译环节出问题,推荐直接装3.10。PyTorch的安装有一个特别容易踩的坑:pip install torch会自动装CPU版本,所以如果你有NVIDIA显卡,必须先去PyTorch官网选好CUDA版本再复制对应的安装命令,不能直接用默认的pip命令。
以CUDA 11.8为例,标准安装命令是:
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118装完验证一下CUDA是否生效:
import torch print(torch.__version__) print(torch.cuda.is_available()) # 返回True说明GPU可用接着装Ultralytics:
pip install ultralytics这个包会自动把OpenCV、NumPy、pandas这些依赖拉下来,所以不需要单独再装cv2。装完之后在Python里执行:
from ultralytics import YOLO model = YOLO("yolov8n.pt") results = model("bus.jpg")第一次运行会从GitHub自动下载预训练权重,国内网络环境下这步经常超时。解决方法是手动去https://github.com/ultralytics/assets/releases下载对应权重,然后把.pt文件放到项目根目录。如果下载还是慢,可以用镜像加速。这块属于基础环境问题,卡住的人不少,但别在这一步浪费太多时间。
3. 最简单的推理代码:从安装到跑通人脸级Demo
环境就绪后,推理实际上是YOLOv8最没门槛的一环。官方设计得很人性化,几行代码就能交付一个能用的检测脚本。我建议你按下面这个层级去理解API,而不是死记硬背。
3.1 核心调用逻辑
创建模型的三种方式:
from ultralytics import YOLO # 方式一:使用预训练权重(最常见) model = YOLO("yolov8n.pt") # 方式二:使用yaml结构文件生成新模型(需要再训练) model = YOLO("yolov8n.yaml") # 方式三:加载自己训练好的模型 model = YOLO("runs/detect/train/weights/best.pt")这三种方式返回的model对象,调用接口完全一样:model.predict(source=...)或者直接在model(...)括号里传参数。
3.2 完整推理脚本
from ultralytics import YOLO # 加载COCO预训练权重 model = YOLO("yolov8n.pt") # 对单张图片推理 results = model.predict( source="test.jpg", conf=0.5, # 置信度阈值,低于0.5的结果会被过滤 save=True, # 自动保存标注后的图片 device="0", # "0"表示用第一块GPU,cuda核显用"cpu" show=False # 推理时是否实时弹出窗口 ) # 对文件夹内所有图片批量推理 results = model.predict(source="images/", save=True) # 对视频文件推理 results = model.predict(source="test.mp4", save=True) # 对摄像头实时流推理 results = model.predict(source="0", save=False, show=True)运行model.predict之后,它会自动在项目根目录创建runs/detect/predict文件夹,把标注好的图片或视频存进去。如果你不想用命令行参数去控制这些选项,也可以直接写在model(source="test.jpg", save=True, conf=0.5)这样的方法调用里,效果是一样的。
3.3 结果对象里到底有什么
results不是一张图片,而是一个Results对象列表,每个元素对应输入中的一帧或一张图。最常用的属性有这么几个:
results[0].boxes:检测框对象,包含坐标、置信度和类别。results[0].boxes.xyxy:每个框的左上角和右下角坐标(像素值)。results[0].boxes.conf:每个框的置信度。results[0].boxes.cls:每个框的类别序号。results[0].names:类别序号和名字的映射字典。results[0].plot():返回一张画好框的BGR图像(用OpenCV展示或保存)。
看这段代码你就理解了:
from ultralytics import YOLO model = YOLO("yolov8n.pt") results = model("test.jpg") for box in results[0].boxes: x1, y1, x2, y2 = box.xyxy[0].tolist() conf = float(box.conf[0]) cls = int(box.cls[0]) label = results[0].names[cls] print(f"检测到 {label}: 置信度 {conf:.2f}, 坐标 ({x1:.0f}, {y1:.0f}) -> ({x2:.0f}, {y2:.0f})")跑一遍你就能看到,每行输出都在告诉你:这张图里哪里有目标,模型认为它是什么,把握多大。Python本身作为一种胶水语言,在这里的价值体现得特别明显——你不需要关心模型内部怎么算的,只需要接好输入、读好输出,然后写自己的业务逻辑就行了。
注意:检测框坐标默认是分辨率像素坐标,不是归一化的0到1之间的值。不管是做OCR的预处理,还是做追踪算法的输入,都要注意这个坐标系,避免拿到坐标后直接当比例去用。
4. 从0训练自己的数据集:标注、训练、看损失曲线
如果预训练模型不能满足需求,那就得训练自己的数据。很多新手在这一步被"数据集"劝退,其实只要流程清晰,没你想象中那么复杂。
4.1 数据标注:yolo格式的真相
先用手机或相机准备好各类目标图片,数量上可以先从每类三四百张起步。然后用Labelimg或者Labelme标注。如果做检测任务,我推荐Labelimg,输出直接选YOLO格式。
YOLO标注格式的关键点是:每张图片对应一个同名的txt文件,文件里每一行代表一个目标,内容是"类别序号 中心点x 中心点y 宽度 高度",其中坐标值全部归一化到0到1之间。
举个例子,一行标注0 0.5 0.5 0.2 0.3,含义是:这张图里有一个类别为0的目标,它的中心点在这张图的(50%, 50%)位置,宽度占整张图的20%,高度占30%。
注意两点:类别序号从0开始,而且txt文件的名字必须和图片名完全一致,比如img001.jpg对应img001.txt。
4.2 数据集目录结构与配置文件
按YOLO惯例组织目录:
dataset/ ├── images/ │ ├── train/ │ ├── val/ ├── labels/ │ ├── train/ │ ├── val/训练集和验证集建议按8比2或9比1划分,验证集不是可选项,它能帮你看模型是否过拟合。
然后在项目里写一个data.yaml文件:
path: dataset train: images/train val: images/val nc: 1 names: ['helmet']nc是类别数量,names是类别名字列表。这个文件里不要写中文注释,有些版本解析会出问题。路径写的就是data.yaml所在目录下的相对路径结构。
4.3 训练命令与参数解读
from ultralytics import YOLO model = YOLO("yolov8n.yaml") # 用结构文件创建新模型 model = YOLO("yolov8n.pt") # 或加载预训练权重做迁移学习 results = model.train( data="data.yaml", epochs=100, # 迭代轮数 batch=16, # 批大小,按显存调 imgsz=640, # 输入分辨率 name="helmet_run", # 实验名,输出在runs/detect/helmet_run )如果你想用自己的数据微调预训练模型,用第二个方式加载yolov8n.pt,训练时它会自动只训练需要更新的层,训练速度明显加快,而且不容易从零开始就发散。这是最推荐的做法。
训练过程会在终端输出每个epoch的box_loss、cls_loss、dfl_loss以及验证集上的mAP50、mAP50-95这些指标。终端里看着它们跳动就行,不需要实时盯着。
4.4 损失函数曲线图怎么画
训练结束后,runs/detect/helmet_run/目录下会生成一个results.csv文件和一个results.png图片。results.png就是你的损失函数曲线和精度曲线,不需要自己从头画,官方已经把train/box_loss、train/cls_loss、val/box_loss、val/cls_loss、metrics/mAP50这些指标全部画在一张图上了。
如果你想画更自定义的曲线,比如只看某个类别的AP变化,那你可以读取results.csv:
import pandas as pd import matplotlib.pyplot as plt df = pd.read_csv("runs/detect/helmet_run/results.csv") plt.plot(df["epoch"], df["train/box_loss"], label="train box_loss") plt.plot(df["epoch"], df["val/box_loss"], label="val box_loss") plt.xlabel("epoch") plt.ylabel("loss") plt.legend() plt.show()如果训练后没看到results.csv,自查一下是不是老版本,或者训练中断了没写完整。升级到最新版ultralytics基本不会再出这种问题。
4.5 训练时要不要做数据增强
YOLOv8默认开启Mosaic、随机翻转、颜色扰动、缩放宽高比等数据增强策略,对大多数中小规模数据集来说,保持默认就是最省心的方案,不要一上来就关掉。如果你的数据集特别干净、而且目标尺寸变化很小,可以留10%左右的图像的Mosaic增强,避免增强过度导致模型学不到真实特征。
5. 实战中的高频难题:视频解码、重复识别、小目标
训练好模型只是起点,真正让新手崩溃的往往是在实际业务中暴露出的细节问题。
5.1 视频推理到底要不要自己解码
直接把视频文件传给model.predict就行,不用自己做解码。Ultralytics内部用OpenCV按帧读取视频,再逐帧送入模型推理,最后把结果写回视频。对大多数用户来说,这是最省事的方式。你唯一需要关注的就是性能:如果你的GPU推理速度跟不上视频帧率,会出现视频输出"一卡一卡"的现象。
处理方法是跳帧策略:
import cv2 from ultralytics import YOLO model = YOLO("yolov8n.pt") cap = cv2.VideoCapture("test.mp4") fps = int(cap.get(cv2.CAP_PROP_FPS)) frame_idx = 0 while cap.isOpened(): ret, frame = cap.read() if not ret: break if frame_idx % 3 == 0: # 每3帧处理1帧 results = model(frame, verbose=False) annotated = results[0].plot() # 把 annotated 写入输出视频 frame_idx += 1 cap.release()这是实际项目中非常常见的处理方式,能显著提升视频处理速度,缺点是会丢失跳过的帧里的目标,在安全监控这类要求"不漏检"的场景需要评估后再用。
5.2 运动的物体经过摄像头只识别一次的问题
有人问"运动的物体经过摄像头只识别一次,怎么办",这个问题背后的真实需求往往是:他希望追踪物体、统计数量,或者对同一物体只输出一次检测结果,而不是每一帧都重复标注。
首先要区分概念:YOLOv8本身是帧间独立的检测器,它不知道上一帧里那个目标是谁,每一帧都是独立检测,所以视频里同一个物体会被标框几十次,这是正常且必然的。要做"只识别一次"或"持续追踪同一目标",需要引入目标追踪算法。
Ultralytics已经内置了ByteTrack和BoT-SORT的接口:
model = YOLO("yolov8n.pt") results = model.track( source="test.mp4", tracker="bytetrack.yaml", persist=True, # 跨帧保持同一个ID save=True )通过results[0].boxes.id可以拿到每个框的追踪ID,相同ID表示同一个物体在连续帧中出现。这时你就可以只对第一次出现的ID做业务处理,比如计数、触发报警,后续帧直接跳过。这是解决"重复识别"问题的标准姿势。
5.3 小目标检测头怎么加
如果你要检测的目标在画面里很小,比如无人机视角下的人、远距离的车牌,直接用默认YOLOv8经常出现漏检。官方提供了P2检测层的改进版本,叫yolov8-p2.yaml。它比默认模型多一个更浅层的特征图,专门用来捕捉小目标信息,代价是计算量增加、推理速度变慢。
选择P2层的时候别盲目加,我的建议是:
- 先按原始比例把图片分辨率提高一点点(比如640改成800),有时比换模型更有效。
- 如果目标确实太小,再用P2配置。
- 如果P2还不够,可以试试把原图切成多个512x512的块分别推理再合并结果,也就是Tiling策略,实战中对小目标的提升非常明显。
6. 部署与加速:导出ONNX、边缘设备上的取舍
训练完模型之后,把.pt文件直接拿来部署在Python环境里跑,这只是最基础的方式。实际项目里,尤其是需要部署到RK3588、Jetson Orin Nano这类边缘设备上时,通常要转换模型格式。
Ultralytics官方导出命令非常简单:
yolo export model=yolov8n.pt format=onnx导出后得到一个yolov8n.onnx文件,可以用ONNX Runtime加载它进行推理,速度比PyTorch原生推理快不少:
import onnxruntime as ort import cv2 import numpy as np session = ort.InferenceSession("yolov8n.onnx") input_name = session.get_inputs()[0].name img = cv2.imread("test.jpg") img_resized = cv2.resize(img, (640, 640)) # 转成模型需要的输入格式:1,3,640,640,归一化到0-1 input_tensor = np.transpose(img_resized, (2, 0, 1)).astype(np.float32) / 255.0 input_tensor = np.expand_dims(input_tensor, axis=0) output = session.run(None, {input_name: input_tensor})[0]ONNX模型在Jetson上还能进一步转成TensorRT格式,推理速度能再翻几倍,但TensorRT的转换过程对版本极其敏感,新手不建议一上来就碰。先把ONNX跑通,理解输入输出张量的形状,再去研究TensorRT会顺很多。
在边缘设备上部署还有一个容易被忽视的问题:设备的算力预算。RK3588的NPU跑yolov8s级别的模型,实测大部分场景能把帧率做到30FPS以上,但如果你用的是过大的模型或者输入分辨率设得过高,帧率会急剧下降。在边缘设备上做部署,第一件事就是确定你的实时性指标,然后倒推模型选型和分辨率设置,而不是追求最大模型最好的精度。
7. 给新手的几条实战心得
最后分享几个我在实际项目中总结出来的经验,不算成体系的知识,但卡住人的往往就是这些细节。
第一,别在环境搭建上反复折腾。我见过很多人在Python版本、CUDA版本、PyTorch版本的组合上花了整整两天,最后发现最稳定的组合反而是文档推荐的默认组合:Python 3.10 + CUDA 11.8 + PyTorch 2.x。如果电脑上已经装了很多Python版本,建议用conda建一个独立环境,避免依赖冲突。
第二,训练set和验证set的类别分布要均匀。这是数据层面最容易被忽略的点。如果你在验证集里放了很多不含任何目标的纯背景图,mAP会被拉低,而模型本身没有问题;如果你训练集里某一类目标的数量是另一类的三倍,模型会偏向学常见类。这些都要在标注阶段就想好。
第三,把置信度阈值作为第一个调参对象。很多新手发现模型"误检"或者"漏检",第一反应是改网络结构或加数据,但实际上有50%的概率你只需要调整conf参数。生产环境中,安全类场景建议把阈值调高到0.7以上减少误触,而监控类场景可以调到0.3以下多抓一些目标,后道人工确认。
第四,注意中文路径的问题。在Windows上用Ultralytics,图片路径、数据集路径如果有中文,经常在训练或导出时莫名其妙报错。把所有路径统一改成英文是成本最低的解决方案。
YOLOv8在目标检测这个方向上已经非常成熟,官方生态把代码、权重、文档都做得很完整。你不需要读懂每一层网络的数学原理也能用它完成实际需求,但要把它用出生产力,你必须理解数据怎么组织、输入输出长什么样、推理和训练之间有什么差异。把这篇里的每一步动手走一遍,你就不再是"会跑代码"的人,而是真正有了做视觉项目的能力。
本文还有配套的精品资源,点击获取