
简介YOLOv8智能小车检测资源包面向计算机视觉学习者、毕业设计及小型智能车项目开发完整覆盖数据准备、模型训练和效果评估。包内已训练好的检测权重附带PR曲线与loss曲线便于直观判断目标检测性能配套数据集已用LabelImg完成标注图片为jpg格式标签文件同时提供xml与txt两种版本可用于YOLOv8直接训练也可适配其他检测框架。资源包共2000个文件主要类型为1984个txt标注文件以及13个md说明文档、2份pdf资料和1个yaml配置结构清晰压缩包体积148.07MB。目前已有329人在线学习。下载后可获得训练好的权重、标注数据集、性能评估曲线、配置文件与说明文档适合作为算法对标基线、毕业设计实现或智能车视觉模块的快速起点基于此资源替换自有数据集即可二次训练迁移至其他检测任务。1. YOLOv8智能小车检测为什么值得自己做一套权重和数据集很多人拿到智能小车第一件事就是去找现成的检测权重下载一个YOLOv8官方模型一跑发现确实能检测人、车、猫狗但放到自己的小车上就翻车——识别慢、误检多、特定角度完全认不出。原因不复杂官方权重是在通用场景的大数据集上训出来的而智能小车面对的是室内赛道、特定物体、固定摄像头角度、有限算力这些差异会让通用模型的表现打对折。所以做YOLOv8智能小车检测的正路不是下载一个权重凑合用而是围绕自己的小车场景准备数据集、训练专属权重、再做轻量化和部署。这套流程做完小车才能在实际环境里稳定识别目标物、完成避障或巡线。这篇文章按我自己的落地路径来写数据集怎么备、YOLOv8怎么训、权重怎么转、部署到小车尤其是RK3588这类板子有哪些坑最后给你几个验证和调优的技巧。无论你是做毕设、搞工创赛智能物流小车还是想把手头的51单片机/Arduino小车升级成视觉小车这套流程都能直接抄作业。2. 小车检测的数据集准备别在第一步就输在起跑线上2.1 先搞清楚小车检测到底需要识别什么智能小车检测的目标物一般分几类赛道元素锥桶、障碍物、特定目标红绿灯、二维码、货物、环境标志停车标志、人行道。不同任务要的数据集完全不同。做物流小车你可能只需要识别货架和货物做竞赛小车你需要识别锥桶和特定颜色的障碍物。这里有个关键决策是自己采集标注还是用现成数据集。我的建议是除非你的场景正好是公开数据集覆盖的场景比如BDD100K里有车辆和行人CCPD里有车牌HRSC2016里有船舶否则一定要自己采集。因为小车的摄像头高度、角度、运动模糊、光照都和公开数据集差异太大用别人拍的图训练到了自己车上就是两个字玄学。如果确实要先用公开数据集验证流程可以试这三个车辆检测BDD100K自动驾驶场景包含车辆、行人、交通标志适合物流小车车牌检测CCPD中国停车场车牌数据集适合做门禁小车航拍/俯视目标HRSC2016船舶检测适合俯视视角的小车视觉调试行人检测CrowdHuman密集人群适合避障小车做行人识别但注意这些数据集的标注格式不统一BDD100K是JSON格式HRSC2016是XML格式类似VOCCCPD是TXT格式。不管用哪个最终都要转成YOLOv8需要的格式。2.2 自己采集数据的三个硬性要求和标注工具自己采集数据有硬性要求第一画面分辨率要和实际部署时保持一致第二要覆盖不同时间段和光照条件第三要有目标物的正面、侧面、背面、远近视角。我一般会把摄像头固定在小车上拍一段视频然后按帧抽图。OpenCV处理视频抽帧是最快的路径命令如下import cv2 import os video_path output.mp4 out_dir frames os.makedirs(out_dir, exist_okTrue) cap cv2.VideoCapture(video_path) fps cap.get(cv2.CAP_PROP_FPS) total_frames int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 抽帧策略每隔10帧取一帧避免相邻帧过于相似 interval 10 count 0 saved 0 while cap.isOpened(): ret, frame cap.read() if not ret: break if count % interval 0: fname os.path.join(out_dir, fframe_{saved:06d}.jpg) cv2.imwrite(fname, frame) saved 1 count 1 cap.release() print(ftotal frames: {total_frames}, saved: {saved})这段代码的逻辑是读取视频流每隔10帧保存一帧。间隔设10是因为相邻两帧的画面几乎一样全部保存只会让训练集里塞满重复样本模型学不到新特征还会拉长训练时间。如果你发现抽出来的帧还是太相似可以再加大到15或20。标注工具我用LabelImg它直接支持YOLO格式导出。标注界面里画框类别名写在classes.txt里比如cone锥桶、cargo货物、obstacle障碍物。标注完每个图片会生成一个同名TXT文件里面每行是类别ID x_center y_center width height坐标用的是归一化后的相对值。一个小提醒标注框不能只贴着目标物画要稍微留一点边缘。否则模型学到的特征会被目标物边界截断推理时框经常会只框住目标物的一部分。2.3 VOC/CCPD转YOLO格式转换脚本与四个边界坑如果你选了开源数据集而不用自己标注转换格式是绕不开的。最常见的是VOC格式XML转YOLO格式TXT因为很多数据集都附带VOC标注。这里直接给一个能跑的转换脚本import os import xml.etree.ElementTree as ET def convert_voc_to_yolo(xml_dir, out_dir, classes): os.makedirs(out_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, xml_file)) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) txt_name xml_file.replace(.xml, .txt) with open(os.path.join(out_dir, txt_name), w) as f: for obj in root.findall(object): cls_name obj.find(name).text if cls_name not in classes: continue # 边界坑1不在classes列表的类别直接跳过 cls_id classes.index(cls_name) box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) # 边界坑2voc的坐标有概率超出图像边界 xmin max(0, min(xmin, img_w)) xmax max(0, min(xmax, img_w)) ymin max(0, min(ymin, img_h)) ymax max(0, min(ymax, img_h)) # 边界坑3宽高为0的框会导致训练崩溃 if xmax xmin or ymax ymin: continue x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h f.write(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}\n) classes [cone, cargo, obstacle] convert_voc_to_yolo(VOC/xmls, VOC/labels, classes)这个脚本里有四个边界问题值得注意。第一个是classes列表外的类别直接跳过不跳过的话类别ID对不上训练时标签和真实类别错位第二个是坐标裁剪很多公开数据集的标注框会略微超出图像边界不裁会导致归一化坐标出现大于1的值损失函数直接算出NaN第三个是宽高为0的框必须跳过这种脏数据在CCPD和部分自采数据里经常出现第四个虽然没有写进代码但要记住——图片和TXT文件必须同名且在同一目录结构下YOLOv8的要求是images目录和labels目录同级训练时通过配置指定路径。数据准备好之后最后一步是划分训练集和验证集。按7:2:1来分写一个简单的脚本把图片文件名随机抽样分别写进train.txt、val.txt和test.txt。这一步不能省因为YOLOv8训练时要用val集来评估每个epoch的效果没有验证集你根本不知道模型到底练到什么样了。3. YOLOv8环境配置与小车数据训练从零到自己的权重文件3.1 ultralytics环境安装与版本匹配的选择训练YOLOv8的第一步是装ultralytics库。这个包把数据集加载、模型构建、训练、导出全封装好了确实省事但版本和依赖的匹配关系要注意。Python版本建议3.8到3.10PyTorch建议2.0以上CUDA按你自己的显卡来。安装命令pip install ultralytics torch torchvision装完之后验证一下能不能跑python -c from ultralytics import YOLO; model YOLO(yolov8n.pt); print(model.model))如果你只剩CPU也能训但速度会慢到让人想放弃。GTX 1660 Ti这种6GB显存的卡训练yolov8n模型是能跑的batch size调到8到16即可。如果你的显卡显存只有4GB建议直接选yolov8nbatch size设4再开混合精度训练。3.2 数据集YAML配置与五类参数的意义进入训练之前要建一个数据集配置文件。在ultralytics框架里YAML文件指定训练集和验证集图片路径以及类别名这个文件是训练流程的入口。path: /home/user/smart_car train: images/train val: images/val test: images/test names: 0: cone 1: cargo 2: obstacle这里的path是数据集根目录train和val是相对于path的图片目录。ultralytics会自动在images目录旁边找labels目录所以你的目录结构必须是smart_car/ images/ train/ val/ labels/ train/ val/YAML配置好之后训练命令yolo detect train datasmart_car.yaml modelyolov8n.pt epochs100 imgsz640 batch16 device0几个关键参数的含义imgsz640是输入图片的尺寸越大模型看到越多的细节但推理越慢。小车场景下640够用除非你的目标物非常小那再考虑768。batch16是每轮迭代喂给GPU的图片数量显存不够就降到8梯度不不稳定就降到4。epochs100是轮数小车数据集在几百到一两千张图的情况下100轮足够了。再多就会过拟合模型在训练集上很准在真实小车上一塌糊涂。device0指定使用GPU0是第一块显卡。训练过程中你会在终端看到loss值变化同时可以在runs/detect/train目录下看到训练曲线图。如果loss持续下降说明模型在学习如果loss在某个轮次后开始回升那就是过拟合了可以提前停掉。3.3 训练完成的三个产物与best.pt和last.pt的取舍训练结束后runs/detect/train/weights目录下会有两个文件best.pt和last.pt。best.pt是验证集上表现最好的权重last.pt是最后一轮的权重。两者怎么选我的建议是有validation结果就看best.pt它代表泛化能力最好的状态。但要注意有些情况下best.pt在验证集上表现好并不一定在真实小车部署时最好因为验证集和你实际运行场景可能还有差异。所以两个都留着部署时出了问题就换last.pt试试。另外训练完成后会打印mAP50和mAP50-95指标。mAP50是IoU阈值0.5时的平均精度mAP50-95是多个IoU阈值下的平均精度。小车检测任务mAP50到0.85以上基本够用mAP50-95能到0.6就算不错了。不要追求mAP50-95到0.8以上那对小车这种算力受限的场景不现实。3.4 小数据集训练的三个提速技巧和防止过拟合如果你的数据集只有一两百张图训练时很容易过拟合。这里有三个实操技巧第一开启数据增强。ultralytics默认开了增强但你可以调大增强强度。在训练命令中加augmentTrue或者手动改ultralytics源码里的增强参数hsv_h、hsv_s、hsv_v和flipud、fliplr、mosaic等。第二用预训练权重做迁移学习而不是从头训练。从yolov8n.pt开始训练会比从随机权重训练快很多。这就是为什么我们前面训练命令直接modelyolov8n.pt而不是modelyolov8n.yaml。第三降低训练分辨率。如果目标物在画面里很小或者你的显卡不够强先用416训练一轮再在最后30轮把分辨率升到640。这叫多尺度训练YOLOv8本身支持效果在小数据集上尤其明显。4. 部署到小车硬件权重转换与RK3588上的跑法4.1 从PyTorch权重到ONNX再到板端格式训练完拿到best.pt下一步是把权重转成能部署的格式。常见的部署路径有两种一种是转成ONNX再用板子的推理框架加载另一种是直接转成板子专用的格式比如瑞芯微的RKNN、英伟达的TensorRT。最稳的中间格式是ONNX因为几乎所有推理框架都支持。导出命令yolo export modelbest.pt formatonnx imgsz640 opset12导出完成后可以用onnxruntime在PC上验证一下确认导出的模型没被转坏import onnxruntime as ort import numpy as np from PIL import Image session ort.InferenceSession(best.onnx) input_name session.get_inputs()[0].name input_shape session.get_inputs()[0].shape print(finput: {input_name}, shape: {input_shape}) # 模拟一张输入图shape要和导出时一致 x np.random.randn(1, 3, 640, 640).astype(np.float32) outputs session.run(None, {input_name: x}) print(foutput shapes: {[o.shape for o in outputs]})如果输出层的shape和你预期不一致检查一下导出时是不是改了imgsz或者模型头是不是被改过。4.2 RK3588上部署YOLOv8的完整流程与量化注意如果你的小车用的是RK3588这类瑞芯微板子那前面导出的ONNX还要再转一次RKNN格式才能用rknn-toolkit2推理。这个转换过程有几个坑值得单独拿出来说。先说整体流程# 1. 安装rknn-toolkit2在x86 PC上 pip install rknn-toolkit2 # 2. 创建Python转换脚本 from rknn.api import RKNN rknn RKNN() # i8量化模式数据集指向一个包含几百张图片的文件夹 rknn.config(mean_values[[0,0,0]], std_values[[255,255,255]], target_platformrk3588) # 加载ONNX模型 ret rknn.load_onnx(modelbest.onnx) if ret ! 0: print(load onnx failed) exit(1) # 构建RKNN模型do_quantizationTrue会做INT8量化 ret rknn.build(do_quantizationTrue, datasetquant_dataset.txt) if ret ! 0: print(build rknn failed) exit(1) rknn.export_rknn(best.rknn) rknn.release()量化这一步是用一组真实图片来校准模型从FP32到INT8的精度损失。dataset.txt文件里需要写上图片路径每行一个通常写几百张。如果不量化模型体积和推理速度都会差很多。量化之后一定要在PC上先用rknn-toolkit2做精度对比rknn RKNN() rknn.load_rknn(best.rknn) rknn.init_runtime(targetNone) img preprocess(input_image) # 按你训练时的预处理逻辑来 outputs rknn.inference(inputs[img])对比RKNN模型输出和ONNX模型输出如果检测框位置和类别差异不大就可以部署了。如果差异大常见原因是量化校准图片选得不好或者模型里的某些层对量化太敏感必要时改成FP16。4.3 树莓派/单片机小车的推理方案串口与视觉模块不是所有人的小车都有RK3588更多人用的是Arduino加树莓派或者51单片机加一个视觉模块。如果视觉计算放在树莓派上推理用ONNX Runtime配合Neon加速模型用yolov8n分辨率降到416帧率大约能在15到20FPS。检测结果通过串口发给单片机控制板串口发送的协议一般是import serial import struct ser serial.Serial(/dev/ttyUSB0, 115200) # 检测结果打包发送帧头 类别ID 中心点x 中心点y 宽度 高度 def send_detection(cls_id, cx, cy, w, h): data struct.pack(BBHHHH, 0xAA, cls_id, cx, cy, w, h) ser.write(data) send_detection(1, 320, 240, 50, 80)单片机端解析时注意帧头0xAA用于同步后面的数据要按同样的结构体解包。串口波特率选115200数据包长度不长传输延迟可以忽略。如果你的板子连树莓派都没有只有个OpenMV或者K210这类视觉模块那YOLOv8基本跑不动建议换成轻量检测方案或者直接用传统视觉处理。这也是很多人最后发现YOLOv8在小车上的瓶颈——不是模型不行是硬件根本撑不住。4.4 部署时的预处理对齐三个容易忽视的地方把PC上的模型部署到板子上最容易被坑的是预处理没对齐。训练时YOLOv8的预处理是letterbox缩放加归一化到0到1。部署到板子上这一步必须和训练完全一致。具体三个地方letterbox的缩放方式和填充方向如果训练时缩放填充在两边部署时也不能居中填充颜色通道的顺序训练时BGR还是RGB归一化的方式除以255是常规做法但要注意均值方差有没有改如果板端推理结果一直不对先检查这三项90%的问题出在这。5. 小车检测的常见踩坑记录按现象到原因到解决排雷5.1 模型在PC上能跑到板子上就检测不到目标现象同一个模型同一个摄像头在PC上用ONNX推理一切正常部署到RK3588上之后什么也检测不到输出层的置信度全是0.01这种极低的值。原因预处理不一致。最常见的是RGB和BGR通道顺序颠倒了。训练的时候PyTorch用的BGROpenCV读图默认BGR但RKNN默认期望RGB颜色通道整体错位模型输入完全不对自然检不出目标。解决在rknn.config里把mean_values和std_values设置成和训练时一致同时把输入图片的通道顺序手动转成和模型训练时一致。我一般在preprocess函数里加一句img cv2.cvtColor(img, cv2.COLOR_BGR2RGB)确保喂给RKNN的图片是RGB。5.2 INT8量化后精度掉得离谱mAP掉了0.3现象FP32时mAP50在0.87INT8量化后直接掉到0.55检测框大量偏移类别误检严重。原因量化校准集选得不合理。我踩过的坑是用了一张和实际场景差异很大的量化图片集比如全是干净的室内图结果量化后的权重遇到室外光照就完全失准。解决量化校准图片必须覆盖实际运行场景的多样性。从你的验证集里随机抽300到500张图确保包含不同光照、不同角度、不同距离。如果还是掉精度改用混合量化把最敏感的那几层保留FP16。5.3 小车运行时检测延迟忽高忽低卡顿明显现象帧率不稳定有时候20FPS有时候突然掉到5FPS过几秒又恢复。原因板子CPU频率被降频了或者推理线程和非实时任务抢资源。RK3588的NPU和CPU共用带宽如果后台跑了别的任务NPU推理就会被挤。另外如果代码里频繁在CPU和NPU之间拷贝数据也会造成延迟。解决把推理放到独立线程用CPU亲和性锁定到指定核心NPU推理前把输入图片一次性拷贝到NPU内存推理完再拷贝一次不要在循环里反复申请内存。更简单的办法是把imgsz从640降到480推理延迟能降30%左右。5.4 标签框抖动明明目标没动框却在跳现象小车静止时检测框在目标物周围跳动方差能有十几像素。原因模型对目标的置信度在阈值边缘波动或者NMS的IoU阈值设得太低多个框交替输出。解决调整推理后处理的参数。置信度阈值confidence从0.25调到0.45IoU阈值从0.45调到0.5。还可以对连续多帧的检测结果做卡尔曼滤波或简单的滑动平均让框的位置平滑过渡。5.5 小车跑起来后画面模糊检测率暴跌现象PC上测试时好好的一放到小车上跑起来检测率明显下降目标物一移动就丢。原因运动模糊。小车行驶时摄像头抖动曝光时间太长画面模糊模型认不出目标。解决从硬件和软件两侧同时处理。硬件上给摄像头加个镜头固定支架减少震动软件上提高快门速度在板端把摄像头曝光模式设置成手动曝光时间设短一些。如果用的是RK3588的MIPI摄像头可以调用rkaiq库的接口强行设置曝光参数。6. 把检测结果真正用起来损失曲线、热力图与串口联调的技巧训练完成后不要急着部署上车先做三个验证步骤能帮你省下大把现场调试时间。第一个是看训练损失曲线YOLOv8训练时会自动保存box_loss、cls_loss和dfl_loss的曲线图在runs/detect/train文件夹里。如果box_loss下降缓慢或者波动很大说明模型对位置的学习不稳定可以先降学习率重训。画损失函数曲线可以用下面这段代码它能把训练日志中的loss数据提取出来合并两条曲线import matplotlib.pyplot as plt import pandas as pd # 训练日志一般在runs/detect/train/results.csv里 df pd.read_csv(runs/detect/train/results.csv) epochs df[epoch] box_loss df[train/box_loss] val_box_loss df[val/box_loss] plt.plot(epochs, box_loss, labeltrain box loss) plt.plot(epochs, val_box_loss, labelval box loss) plt.xlabel(epoch) plt.ylabel(box loss) plt.legend() plt.savefig(loss_curve.png)第二个验证是可视化热力图。用grad-CAM对模型输入图片画热力图可以看到模型的注意力集中在哪里。如果热力图总是框在目标物的某个局部比如只注意锥桶的顶部说明训练数据里锥桶顶部的样本占比太高模型学偏了。这个负责排查可以加数据补充再训一版。第三个是串口联调。做好检测之后先在一块Arduino或者STM32上做一个简单的回环测试让小车控制板收到检测结果后打印到串口确认数据格式无误。这个步骤至少在半小时内确认不用等到上车再试省得多。我自己的教训是不要为了追求mAP好看就去堆数据集的重复样本。小车场景下你要的是面对新角度、新光照依然能识别的鲁棒性。与其在训练曲线里反复抠参数不如多花时间拍几段不同环境的视频把数据集的多样性做扎实。另外一个值得记住的技巧部署时把模型推理的置信度分开调。不同类别在小车场景下最佳置信度不一样比如障碍物需要保守一点宁可漏检也不误检而货物则可以激进一些误检了下一步还能纠正。YOLOv8支持每个类别单独设置阈值别偷懒用全局统一值。希望这篇文章能帮你把YOLOv8智能小车检测这套方案走通从数据集到部署再到联调每一步都少踩一点坑。如果你卡在某个具体环节回头看看对应章节多半能找到答案。本文还有配套的精品资源点击获取