尧图精选

YOLOv5目标检测实践:汽车充电插口识别数据集的构建与训练

🕒 发布时间:2026/10/1 4:09:35 📁 来源:尧图网络
简介汽车充电插口识别数据集是一份面向目标检测任务的专业标注数据聚焦快充与慢充两类插口的识别适用于新能源汽车充电设施管理、自动泊车辅助等场景。压缩包共481个文件包含240张JPG图片、240个对应的TXT标注文件以及1个YAML配置文件TXT文件采用YOLOv5标准格式记录每个插口的位置坐标与类别信息YAML文件定义了类别名称、训练验证路径等参数可无缝接入YOLOv5、YOLOv8等主流检测框架。整个资源包仅9.54MB轻量易用方便快速下载与本地实验。目前已有244人浏览学习数据规模适合目标检测入门者快速验证流程也适合研究者作为迁移学习或数据增强的原始素材。借助这份数据集开发者能够训练出区分快充口与慢充口的视觉模型为后续充电桩智能管理、车辆自动对准等上层应用打下数据基础。1. 汽车充电插口识别数据集快充、慢充能不能分开直接决定充电运营自动化的下限在充电场站装了一段时间摄像头后我意识到“判断用户有没有插枪、插的是直流还是交流”这件事如果靠人工盯着视频看运维成本根本兜不住。所谓汽车充电插口识别数据集是一份面向YOLOv5训练的目标检测标注数据集标注对象就是快充插口和慢充插口两大类。它的价值不在“能认出充电口”而在能把直流口和交流口当成两类独立目标让充电桩侧边的视觉识别系统自动返回插口类型和位置。适合谁往下读做充电场站智能监控、巡检机器人以及想用yolo v5快速切入工业视觉检测的开发者。2. 快充、慢充插口的视觉边界数据标注的类别设计决定模型最后一公里的误检率2.1 直流快充与交流慢充外观上到底差在哪人们习惯用标准名称讨论问题国标GB/T直流口、国标GB/T交流口、CCS、CHAdeMO、Type 2。但真正做数据集时有意义的维度不是协议而是孔径大小、针脚排布、腔体深度。直流快充口的针脚一般是两三根粗铜柱金属高光明显交流慢充口的针脚细密多沿圆周排布整体开口直径不小腔体却比直流口浅得多。也就是说视觉识别能依赖的稳定特征集中在“口内纹理”而不是“口外轮廓”。这是很多第一次做这个项目的团队翻车的根源把整个盖板框进去白天识别率还行一到夜晚和雨雾天就全线崩坏。标框时单看盖板轮廓快慢充可能一样大真正稳定的是口内高光反射区域和针脚密度。采集阶段最好按孔径、针脚密集程度筛选图片做不到的话宁可靠标注框把外饰盖板切掉。另外CCS这类组合式插口自身包含直流腔体和交流腔体两层结构在同一张图里应标成两个独立框不要标成一个大框。原因很简单现场要回答的是“用户刚才用的是快充还是慢充”而不是“这辆车有没有充电口”。户外场景还有一个容易忽略的问题枪头插着时口内细节被遮挡拍出来的图里腔体几乎不可见。做充电运营的在线识别时常见做法是在枪头未插入状态下布点采集或结合挡板的开合状态辅助判断。把“插着枪”的照片全部扔进训练集会让模型把枪头胶壳当成主要特征等遇到不同品牌、不同磨损程度的枪头时反而全面漏检。2.2 类别划分只分成快充、慢充两类还是再拆别的标注数据集怎么做类别设计我一般只分两类CLASS 0 快充口DC_inlet、CLASS 1 慢充口AC_inlet不再按标准拆。理由和部署目标强相关一是真实场景出现的接口形态相对规范二是终端逻辑只需要二值语义。如果打算进一步识别插枪状态就单独开第三类“带枪头”不要混进前两类。负样本要单独准备一份这一点经常被忽略。负样本指没有充电口但有近似形状的车身区域比如盖板凹痕、圆形装饰、油箱口。YOLOv5在做目标检测时会把背景当作负样本但数量天然不足模型容易把圆环形状误判为插口。我一般在数据集中额外放一批只包含背景的JPG配合空标签txt用于压低误检。这也说明了“标注数据集”的价值不止标签本身还包括它如何规划负样本分布。2.3 两类目标标注要点速查标注对象关键视觉特征框选建议最容易出现的误标快充直流孔径粗、针脚粗、腔体深框贴住腔体内沿宁可小不要大把外圈装饰盖板圈进框慢充交流针脚细密、圆周分布、腔体浅从针脚外缘开始框与快充框距离近时错误合并成一个框带枪头/被遮挡枪头胶壳占满视野直接删除或归入负样本被当成正常快慢充特征学进去这张表看起来简单却是我整理数据时最花时间的一张。标注工具里肉眼看着差不多的框在模型眼里可能是两种完全不同的特征分布。框大一圈等于把车身涂漆、锈斑、阴影全部送进特征统计里框小一点中心点偏移量又随拍摄距离放大。两者都会导致小目标漏检。反过来如果框选得过紧把针脚边缘裁掉特征又不够完整。快慢充识别这类任务标注框的松紧直接影响最终混淆率。3. 落到YOLOv5标注格式目录结构、标签文件和一套转格式的检查流程3.1 一张图一条txtYOLOv5标签文件的完整规范YOLOv5的标注数据集中标签文件不是放多边形点集而是每一行“class x_center y_center width height”坐标全部归一化到0~1。例如一个快充口位于图像中心、宽高约占整张图的四分之一txt里就是0 0.500000 0.500000 0.250000 0.250000配套的目录结构我固定按官方工程风格组织避免训练脚本路径要反复改dataset ├── images │ ├── train │ ├── val ├── labels │ ├── train │ ├── valimages与labels下面的train文件名一一对应只是扩展名不同。一个特别容易踩的规则图片没有目标时txt文件必须保留为空文件。不要把空标签删掉否则YOLOv5在验证阶段会少读一批对应关系训练本身不受影响mAP计算却会失真。官方README里没有强调这点我是吃过亏之后才养成的习惯。3.2 从VOC标注转成YOLOv5标签的转换脚本多数标注工具默认导出VOC XML转换逻辑不复杂但批量转换时每天都能改坏一批。这是一段常用的转换脚本import os import xml.etree.ElementTree as ET # 类别名 - 数字ID这行决定了data.yaml里的labels顺序务必固定 CLASS_MAP {DC_inlet: 0, AC_inlet: 1} def voc2yolo(xml_dir: str, out_dir: str): os.makedirs(out_dir, exist_okTrue) for fname in os.listdir(xml_dir): if not fname.endswith(.xml): continue xml_path os.path.join(xml_dir, fname) root ET.parse(xml_path).getroot() img_w int(root.find(./size/width).text) img_h int(root.find(./size/height).text) yolo_lines [] for obj in root.findall(object): cls_name obj.find(name).text if cls_name not in CLASS_MAP: print(f[跳过] {fname}: 类别{cls_name}不在映射表) continue box obj.find(bndbox) xmin float(box.find(xmin).text) xmax float(box.find(xmax).text) ymin float(box.find(ymin).text) ymax float(box.find(ymax).text) x_center (xmin xmax) / 2 / img_w y_center (ymin ymax) / 2 / img_h bw (xmax - xmin) / img_w bh (ymax - ymin) / img_h yolo_lines.append( f{CLASS_MAP[cls_name]} {x_center:.6f} {y_center:.6f} {bw:.6f} {bh:.6f} ) label_name os.path.splitext(fname)[0] .txt with open(os.path.join(out_dir, label_name), w) as f: f.write(\n.join(yolo_lines)) if __name__ __main__: voc2yolo(voc_xml/, yolo_labels/)逻辑说明VOC记录的是左上角和右下角的绝对像素值YOLO需要的是中心点加宽高、再除以图片尺寸归一化。整个过程只有简单的四则运算但常见翻车点也在这里——有人忘了除以宽高就写进txt训练时loss直接退到NaN。执行转换后不要直接开训先抽三张图把预测框叠在图上看看位置有没有偏移。参数说明xml_dir指向VOC标注目录out_dir是输出的txt目录。脚本不读取JPG文件所以即使图片损坏转换也照常通过图片完整性要交给下一道检查。3.3 训练前花5分钟做的标注体检标注体检比训练本身更能省时间。需要做四件事标签是否存在、坐标是否越界、图片能否正常打开、类别分布是否异常。下面这个简短脚本可以顺手跑import os from PIL import Image label_dir yolo_labels/ image_dir dataset/images/train/ bad 0 for txt in os.listdir(label_dir): stem os.path.splitext(txt)[0] img_path os.path.join(image_dir, stem .jpg) if not os.path.exists(img_path): print(f[缺图] {stem}) bad 1 continue try: Image.open(img_path).verify() except Exception: print(f[图片损坏] {img_path}) bad 1 continue for line in open(os.path.join(label_dir, txt)): parts line.split() if len(parts) ! 5: print(f[格式错] {stem}: {line.strip()}) bad 1 continue _, cx, cy, bw, bh parts for v in (cx, cy, bw, bh): if not (0.0 float(v) 1.0): print(f[越界] {stem}: {line.strip()}) bad 1 break print(f发现异常 {bad} 条)逻辑说明脚本会找出缺图、图片损坏、行列数不对、坐标越界四类问题。之前我有一批数据因为标注工具的自动补点把xmin记成0、ymin记成0而右侧正常导致目标缩到图像一角训练出来的模型对近处插口完全无感。没有这段体检问题会一直拖到验证集mAP崩坏才暴露。拿到一套已经标注好的数据时先跑一遍这个检查花不了五分钟却能把后面几小时的训练时间省回来。参数说明image_dir里的.jpg后缀根据实际图片格式改成.png或.bmpPIL会自动识别。4. 用YOLOv5训练快慢充识别data.yaml配置、训练参数与指标判读4.1 data.yaml的写法与三个易错值path: ./datasets/charging_inlet train: images/train val: images/val nc: 2 names: 0: DC_inlet 1: AC_inletpath建议直接用绝对路径否则在Linux和Windows之间切换时相对路径会引发找不到文件的怪问题。nc必须与names数量一致names顺序必须与txt里第一列数字严格对应。这里如果调换顺序相当于把快充和慢充标签对调模型用统计指标看依然收敛到现场却完全不可用。有人习惯把names写成中文也可以但要统一编码我建议用英文因为后面的部署日志、可视化、导出ONNX都要复用这个名字。4.2 训练命令与参数取舍训练命令采用官方train.pypython train.py --data data/dc_ac.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --cache参数说明img640是输入分辨率和现场摄像头视野里充电口的大小密切相关。当监控画面里插口宽度只有40到80像素时想识别稳定建议把img调到1280并配合--rect做长方形推理而不是盲改anchor尺寸。batch按显存给不够就用8宁愿缩小batch也别把图片resize缩水。weights用yolov5s.pt做迁移学习能复用COCO低层特征中的圆形边缘和金属高光快慢充数据集样本量不大从头训练没有意义。还有一个常见问题数据集中在白天采集训练完RGB通道分布整体偏亮。解决策略是在超参文件里把hsv_h、hsv_s、hsv_v幅度往上调例如hsv_v从0.0调到0.4。调整方法是在训练命令里加--hyp data/hyps/hyp.scratch-low.yaml再手工修改对应值。这招不是玄学本质是弥补采集时段单一带来的光照分布偏差。4.3 不看总mAP先看混淆矩阵训练结束后会生成confusion_matrix.png和PR_curve.png。对快慢充这种两类高度相似的任务总mAP到0.9以上仍然可能隐藏问题。更可靠的做法是先看混淆矩阵重点检查AC_inlet被识别成DC_inlet那一格的比重如果超过3%说明类别在视觉上的可分性没有被充分利用。常见修改办法不是换模型而是回到标注环节把框收紧再提高分辨率重训。另外用detect.py跑一遍验证集python detect.py --source dataset/images/val --weights runs/train/exp/weights/best.pt --conf 0.25在输出图片里逐张观察漏检和重复框。有些模型训练曲线很漂亮实际图片里快充框和慢充框互相压住这类问题只能靠肉眼提前发现自动指标不会告诉你。5. 识别训练与部署中的避坑记录翻车最容易发生在数据划分和边界遮挡5.1 夜间漏检白天训练、夜晚部署立刻打回原形现象验证集mAP在0.93一到地下车库摄像头快充口漏检率超过40%。原因训练集里白天照片占绝大多数没有夜晚低照度的分布。YOLOv5虽然做了马赛克增强但增强是在已有明暗比例上微调没法凭空补出“车灯过曝加口内阴影”的组合。解决把收集到的夜间视频按10秒抽帧加入训练单独划出一部分夜间数据放进val。然后在超参里把hsv_v调到0.3以上补充曝光抖动。这样处理后夜间漏检明显下降。比把置信度阈值从0.45压到0.25更可靠压阈值只会让误检一起上升。5.2 快慢充混淆模型认得插口却说不清是哪个口现象训练集里快充、慢充都标了总mAP也不低实际部署时同一个车位上快充口频频被标成慢充口。原因标注框过宽把两种插口外圈相似的装饰件都收进特征模型学到的是外壳轮廓而不是口内针脚和孔径差异。另一种原因是输入分辨率太低目标过小时针脚形态对模型来说就是一团纹理噪声。解决先按第2章的框选规则重标了约40%的图把框紧贴腔体内部同时把img从640提到1280。重训后混淆矩阵里快慢充互混的比例从7.5%降到1.8%。一句话分类分不清的时候不要急着换网络先检查框是不是太松。5.3 带枪头照片进入训练导致枪头遮蔽时漏检现象充电枪插在车上枪头把口内细节全部挡住模型把枪头当成快充口的强特征。换另一种品牌枪头时同一个车位直接漏检。原因数据集里“插着枪”的照片和裸口照片混在一起标签都叫快充口。模型为了拟合训练分布把枪头胶壳、线缆特征当成了快充口的一部分。解决花一天做清洗把带枪头的图全部移出训练集单独放进难例池并给它们打上负样本标签也就是空txt让模型知道这是一种干扰。重新训练后枪头遮挡场景转为“不检测”而不会错误地报出快充。5.4 标注坐标越界训练loss一路降到NaN现象转换脚本跑完训练前几步loss正常某轮突然Loss变为NaN验证集完全不动。原因有一张图里目标贴着图像边缘标注框的xmax大于原图宽转换后坐标超过1.0在YOLOv5的loss计算分支里产生不稳定值。解决用第3.3节的体检脚本把所有越界坐标限制回0到1之间并对贴边目标做轻微收缩避免零尺寸框。这个坑在第一次转换时没能防住后来把越界检查纳入每次训练前的固定步骤再没复发过。5.5 验证集划分太随意mAP虚高现象随机划分images/train和images/val训练结果mAP很理想切到新的场站视频后识别效果明显下滑。原因同一视频连续帧高度相似随机划分会让相似帧同时落在train和val相当于提前把答案透露给模型验证集过拟合被当成性能。解决按视频或按时间片划分数据而不是按图片随机划分。现在的做法是用一段10分钟的视频抽1000帧做训练绝不把这1000帧打乱后取200帧当valval要另取其他时段或其他车位的视频帧。这个划分习惯是标注数据集使用中最容易默认踩进去的深坑。6. 从验证集到现场部署前保留这两个验证习惯6.1 用连续视频帧验收而不是单张抽图数据集本身能识别快充、慢充但现场场景还有插枪动作过程。我会选取连续30到60帧视频对每一帧跑模型看快充框的出现频率和位置稳定性。一个正确检测不应该第5帧出现、第6帧消失、第12帧又出现而应稳定落在同一个插口位置。出现闪烁时优先检查漏检帧的图像内容多数是逆光或机械臂遮挡造成。单张图片通过不代表时序上通过连续视频才是部署级验收方式。6.2 置信度阈值和最小框尺寸一起过滤现场画面的充电口再小也有一定像素尺寸推理时可以给一组双重过滤import cv2 results model(frame, size1280) for *xyxy, conf, cls in results.xyxy[0]: x1, y1, x2, y2 [int(v) for v in xyxy] box_w, box_h x2 - x1, y2 - y1 if box_w 40 or box_h 40: continue # 目标过小通常是远处的装饰件而非真实插口 if conf 0.5: continue # 置信度阈值按实测场景微调 label model.names[int(cls)] draw_box(frame, (x1, y1, x2, y2), label, conf)逻辑是过滤两类假阳性远处类似圆形的物体和低置信度的疑似框。参数说明里的40px是根据部署画面经验得来的200万像素俯拍车位时快充口正常拍摄距离下约为60到120像素40像素以下基本可以判断为误检。置信度阈值0.5适用于白天夜间适当降到0.4。我在部署每套识别方案时会固定留档当天数据划分记录和训练超参记录否则两三个月后做模型迭代完全不知道上一次是怎么调出这个效果的。这套习惯帮我保住了很多次现场验收希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →