ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

新能源汽车目标检测数据集构建与YOLOv8训练实战

新能源汽车目标检测数据集构建与YOLOv8训练实战 简介新能源汽车数据集源码包面向AI、新能源与智慧出行领域的研究人员与开发者围绕能源管理、故障预测、能耗估计、用户行为分析、充电需求预测、电池异常检测等方向收录粤港澳大湾区新能源汽车健康度、电动汽车充电站用户行为、充电运营、城市充电桩、充电需求时空、电池异常检测、电动公交驾驶、新能源车牌检测等8个细分场景数据集并提供数据背景、应用领域、数据目录与字段说明便于直接用于模型训练、算法验证和方案落地。包体仅5KB共3个文件以HTML预览页、inscode配置及gitignore为主轻量精简适合快速浏览数据集结构并嵌入到个人项目中。目前已有176人学习浏览虽体积小却覆盖了从充电网络规划到电池安全的完整研究链条对开展新能源汽车AI应用或编写行业解决方案具有直接的参考价值。 大家都在传新能源汽车相关的数据集很难找即便找到了要么是国外路况拍回来的跟国内复杂的交通场景对不上要么就是纯图片没有标注拿到手还得自己重新标一遍。我之前做ADAS相关项目的时候也在这上面折腾了很长时间后来干脆整理了一套自己的新能源汽车数据集并且把配套的处理源码一起开源了出来。这篇文章就把我搭建这套数据集和源码背后的思路、踩过的坑、以及怎么把它用起来的全过程写清楚希望能帮到同样在做目标检测、自动驾驶感知、或者纯电/混动车辆状态分析的朋友。1. 新能源汽车数据集和普通目标检测数据集差别到底在哪很多人一开始会问目标检测数据集不就是图片加标注框吗跟是不是新能源有什么关系这个疑问很合理但实际做过项目就明白差别不是一点半点。1.1 检测对象变了数据构成也随之变化传统自动驾驶数据集核心关注的是车道线、交通标志、行人、普通轿车和卡车。而新能源汽车数据集除了这些通用交通参与者之外更关键的是要覆盖新能源特有元素比如充电桩以及充电枪状态是否插枪、是否在充电动力电池外观特征底盘下方电池包是否可见、是否有变形新能源车牌典型的绿色渐变车牌这是和燃油车最直观的区别车内中控屏、仪表盘能量流界面面向座舱视觉分析场景行人骑行电动车、平衡车城市里新能源车周边最常见的弱势交通参与者这些对象在COCO、VOC这些通用数据集里几乎很难找到标注或者样本量极少。而实际上充电桩识别、车牌类型区分、底盘电池状态检测这些恰恰是新能源车落地项目里被点名最多的需求。1.2 数据维度比普通数据集更丰富我整理的这套资料不只是静态图片。新能源汽车数据集在实际项目里往往需要包含多模态数据我按用途分成了三层视觉层前视、环视、舱内摄像头采集的图像帧JPG或PNG格式车辆状态层通过OBD或CAN总线记录的车速、电机转速、电池SOC、单体电压、温度等时序数据通常存成CSV或parquet融合标注层将视觉检测结果与车辆状态对齐形成例如某时刻画面中检测到充电桩同时车辆SOC低于20%这类复合事件标注说实话大部分刚接触这个领域的朋友只拿到了图片层的标注以为数据集这就齐了。但其实很多实际算法落地需要的是视觉和状态数据联合训练。这也是我强调带源码的原因——没有源码数据维度再多你也很难做数据清洗、多模态对齐和格式转换。1.3 场景复杂度反而更高新能源汽车目前集中在一二线城市和高速路网收集到的数据往往具有典型的中国特色电动车和行人混行、外卖车穿插、非标准交通标识多、老小区里的充电桩位置极其刁钻。如果用国外数据集训练模型再直接搬到国内误检和漏检率会非常难看。所以有针对性自建一套新能源数据集不是锦上添花而是真正做产品落地前的必要准备。2. 搭建数据集之前先想清楚标注规范和格式选型不少人拿到原始图片后第一件事就是打开标注工具开始画框这其实是最容易返工的开局。标注规范和数据格式这一层想不清楚后面训练模型时基本都会出问题。2.1 标注类别定义要具体不要拍脑袋我见过很多人把类别直接命名为carperson看起来没错但对于新能源汽车项目来说信息量不够。比如你检测到了一辆车你根本不知道这车是不是新能源这对后续应用毫无帮助。我建议在这个场景下按下面的粒度来定义类别ev_car新能源轿车ev_suv新能源SUVev_bus新能源公交/大巴charging_pile充电桩charging_gun:充电枪green_plate新能源车牌person行人cyclist骑行者包含电动车和自行车类别定义粒度粗模型好训练但业务不好用粒度太细数据标注成本翻倍。对于第一版数据集我建议以上述8类为主等模型稳定后再做长尾类别的扩展。2.2 标注格式选型VOC、COCO还是YOLO这是所有做检测的人都要做的一道选择题。我在这份源码里同时提供了VOC和YOLO两种格式值得说下我的建议格式存储方式适合场景优缺点VOC XML每张图一个XML通用训练、格式转换中转信息全但文件碎需要额外解析COCO JSON所有标注合成一个JSON需要跑MMDetection等框架结构统一但手工查看不方便YOLO TXT每张图一个TXT每行一个目标YOLOv5/v8系训练极简效率高但可读性较差如果你确定要训练YOLOv5或YOLOv8直接用YOLO格式最省事。别像我开始那样先标注成VOC再写脚本转YOLO虽然也就几十行代码的事但多一步转换就多一个出错的可能。2.3 标注质量校验不能省标注框画得整不整齐直接影响模型收敛速度和最终mAP。推荐两个很实用的小工具用labelme做精细多边形标注适合需要分割能力的场景用LabelImg做矩形框快速标注矩形检测场景够用更重要的是标注完成后的自动校验脚本我在源码里放了一个validate_annotations.py专门检查标注类别是否在配置文件里、框坐标是否超出图像边界、是否有空标注文件、是否有重复标注。数据标注环节经过这一层校验能帮你省掉后面排错的大量时间。3. 从原始图片到可训练数据源码里的数据管线设计数据集的本身价值固然重要但源码这部分才是我最想分享的。因为真正干活的时候你会发现你耗在数据管线上的时间比训练模型的时间还要多。3.1 核心目录结构规划我见过很多项目的目录结构写到后面就乱成一锅粥。建议一开始就按下面的方式组织new_energy_vehicle_dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ ├── annotations/ │ ├── train.json │ └── val.json ├── configs/ │ └── dataset.yaml ├── scripts/ │ ├── split_dataset.py │ ├── voc2yolo.py │ ├── validate_annotations.py │ └── visualize_annotations.py └── README.md这套结构的好处是训练集、验证集、测试集泾渭分明图片和标注一一对应脚本统一放在scripts里。你用YOLO训练时只需要把dataset.yaml里的路径指对就行。3.2 数据集划分源码的核心逻辑划分数据集的脚本看起来简单但里面有个很容易被忽略的点一定是先对整个数据集做随机打乱再按比例切分而且要固定随机种子保证每次切出来的结果是可复现的。下面是我源码中split_dataset.py的核心思路import os import random import shutil def split_dataset(img_dir, label_dir, train_ratio0.8, val_ratio0.1, seed42): random.seed(seed) images [f for f in os.listdir(img_dir) if f.endswith((.jpg, .jpeg, .png))] random.shuffle(images) train_num int(len(images) * train_ratio) val_num int(len(images) * val_ratio) splits { train: images[:train_num], val: images[train_num:train_num val_num], test: images[train_num val_num:] } for split, imgs in splits.items(): os.makedirs(fimages/{split}, exist_okTrue) os.makedirs(flabels/{split}, exist_okTrue) for img in imgs: base os.path.splitext(img)[0] shutil.copy(os.path.join(img_dir, img), fimages/{split}/{img}) shutil.copy(os.path.join(label_dir, base .txt), flabels/{split}/{base}.txt) return {k: len(v) for k, v in splits.items()} if __name__ __main__: print(split_dataset(raw_images, raw_labels))注意这里有一个非常容易踩的坑——不是所有数据都能直接参与随机划分。比如视频抽帧得到的数据前后帧非常相似如果直接随机划分同一个场景的相似图片可能会同时出现在训练集和验证集里导致验证指标虚高。更严谨的做法是先按视频片段分组以片段为单位划分保证同一个视频的帧只出现在一个集合中。我在源码里也加了group_split模式就是为了处理这种情况。3.3 可视化检查比看日志实在模型训练前一定要做一次可视化检查把标注框画到图片上自己肉眼看几张。别嫌麻烦这一步能发现很多脚本层面看不出的问题比如框位偏移、类别标反、小目标漏标。我自己写了一个visualize_annotations.py核心是用OpenCV把YOLO格式的归一化坐标还原成像素坐标然后画框import cv2 def draw_yolo_boxes(image_path, label_path, class_names): img cv2.imread(image_path) h, w img.shape[:2] with open(label_path, r) as f: for line in f.readlines(): cls_id, x_center, y_center, bw, bh map(float, line.strip().split()) x1 int((x_center - bw / 2) * w) y1 int((y_center - bh / 2) * h) x2 int((x_center bw / 2) * w) y2 int((y_center bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, class_names[int(cls_id)], (x1, y1 - 8), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) return img看可视化结果时重点检查三件事小目标是否被框完整、密集目标是否有漏框和重叠框、绿色新能源车牌是否被正确识别为green_plate而不是ev_car。4. 用这份数据集跑通YOLOv8训练全流程数据集和源码有了接下来就是把模型跑起来。我以目前大家用得最普遍的YOLOv8为例完整走一遍。4.1 环境准备与目录配置创建虚拟环境并安装依赖conda create -n nevd python3.9 -y conda activate nevd pip install ultralytics opencv-python pyyaml这里说个小经验ultralytics这个包会自动安装torch等依赖如果你之前装过CPU版torch很可能会被覆盖或冲突建议在干净环境中直接整体装。然后在configs/dataset.yaml里写清楚数据集的路径和类别信息path: /path/to/new_energy_vehicle_dataset train: images/train val: images/val test: images/test nc: 8 names: 0: ev_car 1: ev_suv 2: ev_bus 3: charging_pile 4: charging_gun 5: green_plate 6: person 7: cyclist4.2 训练命令与参数调优思路基础训练命令很简单yolo detect train dataconfigs/dataset.yaml modelyolov8n.pt epochs100 imgsz640 batch16 device0但参数不能盲目照抄我根据新能源汽车数据集的特点说一下调优思路如果充电桩、充电枪、新能源车牌这类小目标比较多imgsz建议从640提升到960或1280小目标检测能力会有明显改善代价是训练显存占用和推理耗时增加batch要根据显存大小动态调整显存不够时优先降batch而不是降imgsz因为分辨率对检测精度的影响更直接类别不均衡很常见尤其是charging_gun这种目标少、又小建议给少样本类别提高损失权重或者在数据增强时做Mosaic和Copy-Paste增强我已经在源码里写好了一份train.sh把超参数和注释都整理好了直接改路径就能用。4.3 训练结果怎么看不要死盯mAP很多新人训练结束后只看mAP这是不全面的。我建议按下面几步来跑完看results.png中的val/box_loss和val/cls_loss确认训练曲线没有剧烈震荡单独计算每个类别的per-class mAP这一步非常重要——有时候整体mAP看着还行但charging_gun的AP却只有0.2这种类别就是当前数据集的短板用训练好的权重跑一批验证集图片把检测结果可视化重点看是否存在大车漏检、远处充电桩误检如果你发现某个类别的AP明显低于均值大概率是样本不足或标注不一致这时候返工去补数据比调模型参数更有效。4.4 模型的导出与部署验证训练完成后导出成ONNX或TensorRT格式做部署验证yolo export modelruns/detect/train/weights/best.pt formatonnx opset12用ONNX运行时做一次简单的推理测试import onnxruntime as ort import numpy as np import cv2 session ort.InferenceSession(best.onnx) input_name session.get_inputs()[0].name img cv2.imread(test.jpg) img_resized cv2.resize(img, (640, 640)) blob img_resized[:, :, ::-1].transpose(2, 0, 1) / 255.0 blob np.expand_dims(blob, axis0).astype(np.float32) outputs session.run(None, {input_name: blob})这里有个常被忽略的细节用ONNX部署时输入张量的归一化方式和预处理顺序必须跟官方保持一致YOLOv8是BGR通道、除以255千万不要自作主张改成RGB。我之前在这个小地方吃过亏出来的检测结果特别离谱。5. 训练过程中必然会遇到的坑我替你踩过了这部分是真正的经验沉淀。数据集的坑不在数据本身而在处理链路和模型训练的交叉处。我把最有代表性的几个问题列出来。5.1 绿色车牌的色偏灾难新能源车牌是绿色渐变的这在视觉上非常有辨识度但对于模型训练来说反而是个大麻烦。因为很多数据集的整体色调偏暗或偏暖绿色车牌和深色车身在低光照条件下的区分度变得很低。应对方法在数据增强阶段加入色彩抖动的随机化包括HSV的hue、saturation、value扰动并特意模拟不同光照条件下的色温变化。否则模型在白天测试表现尚可一到黄昏或阴天环境就各种漏检车牌。5.2 充电桩小目标检不出问题未必是模型充电桩在画面里通常只占很小一块区域尤其当你用行车记录仪视角拍摄时远处的充电桩往往只有几十个像素。你可能会第一时间想到换更复杂的模型但我想提醒你先看你的标注有没有把小目标完整标出来。因为很多标注工具在缩放下很难精确框出小目标经常出现框大了一圈、把背景也包进去的情况这会导致模型学到错误的特征。针对小目标我的建议是在split_dataset.py里加一个小目标统计逻辑计算每个标注框的面积占比把占比小于0.5%的目标单独列出来检查是否都标对了。这个检查脚本我已经写在了源码中。5.3 类别不平衡不能靠简单过采样硬解新能源车辆数据集中ev_car的数量往往远大于charging_gun、charging_pile直接训练会导致少数类别被多数类别压制。但简单的过采样虽然有效也很容易过拟合。更推荐的做法是在线增强时对少数类别做更强的变换比如随机旋转、缩放、翻转、亮度调整对包含少数类别目标的那部分图片在训练采样时赋予更高的采样概率更进一步的可以考虑用生成式方法补充少量稀有类别的合成数据我在源码中给出的weighted_sampler.py就是实现了第二种思路按图片中包含的类别频次反比计算采样权重这样不用复制图片数据也能让模型每个epoch更多地看到稀有类别的样本。5.4 数据泄漏问题这个问题最隐蔽。很多人的图片是从视频里一帧一帧抽出来的如果不对视频片段做隔离随机划分会直接造成训练集和验证集包含相似场景。表现就是训练过程loss正常下降验证mAP也很高可一到实际道路测试就崩了。严格的做法是每一个视频片段是一个不可分割的单位训练集、验证集、测试集按视频片段划分而不是按单帧划分。源码中的group_split模式已经内置了这个逻辑大家用的时候记得选对模式。6. 拿到数据之后下一步可以怎么玩有了这套新能源汽车数据集和源码你可以做的事其实远超目标检测本身。6.1 扩展成多模态融合模型如果你手里的数据还包含车辆CAN总线或OBD的时序状态数据可以尝试做一个视觉状态的融合模型。例如检测到前方有充电桩时同时结合当前SOC和电池温度判断是否需要提示驾驶员充电。这比单纯输出前方有充电桩的检测框更有工程价值。具体思路是视觉分支用轻量级检测网络输出特征时序分支对SOC、电压、电流做编码两路特征融合后做决策输出。这种模型的训练代码我现在也在整理后续会补进这套源码里。6.2 应用到具体的业务场景充电站运营方可以用它自动识别充电桩占用、充电枪是否归位停车场管理方可以用它统计新能源车辆占比辅助充电位规划车企售后可以用它检测车辆底盘电池包是否有明显形变这个需要特殊拍摄角度数据得单独采集6.3 向BEV视角或纯视觉方案演进目前这套数据是标准的平面图像检测。如果你的项目往BEV鸟瞰视角或占用网络方向发展可以基于现有标注做投影变换生成BEV视角的训练样本同时结合车辆本身的位姿信息做时序融合。这一步源码里没有完全覆盖但作为后续演进方向值得大家去探索。最后分享一个我在实际使用这套数据时的体会数据集的整理永远没有完全完成的一天随着落地场景的变化你会不断发现新的类别需要加、新的边界情况需要补。关键是先把数据管线这套基础设施搭好源码的能力在于让你能够快速迭代、重复清洗、随时扩展而不是每次有新需求就把数据从头整理一遍。这套源码我放在开源仓库里拿过去直接改路径就能跑通希望它也能帮你省掉那些我当年白白浪费掉的周末。本文还有配套的精品资源点击获取
返回列表