资讯动态

充电口识别实战:VOC标注转YOLO格式与YOLOv8训练复现

发布时间:2026/9/10 13:50:54 来源:尧图企业网站定制
简介面向新能源汽车充电口识别场景这套VOC标注格式的数据集覆盖特斯拉、CCS1、CCS2、CHAdeMO、Type1、Type2等主流充电接口类型适合视觉检测算法工程师、自动驾驶或充电设施相关技术人员用于模型训练、精度评估与算法迭代。压缩包共2000个文件全部为VOC标准xml标注文件每个文件包含单一样本的类别与边界框标注信息整体约137.67MB可直接用于目标检测模型的数据准备。已有589人浏览学习在充电口识别相关数据集中具备一定参考价值。数据集提供多类型接口的细粒度标签识别精确度达到91.1%可支撑充电口识别模型的训练与评估也便于开展数据增强、类别均衡或模型调优有助于减少自建标注样本的时间成本为新能源汽车充电口的自动识别与多制式兼容性判断提供扎实标注数据。1. 充电口识别标签比模型更值钱自动充电机器人对准车身侧面的充电口时真正决定插枪成败的不是机械臂的毫米级定位而是它把面前的东西认成了CCS2还是CHAdeMO。这两类接口的占用面积和插针布局完全不同一旦分类互换插枪机构轻则报警重则损坏口盖。新能源电车的充电口识别也因此不是普通目标检测任务六类接口在外观上高度相似且训练样本的视角、光照、反光差异极大。这份资源把目前常见的充电口类型整理成VOC标记格式压缩包内XML标注齐全整理后训练检测网络可复现约91.1%的精度适合正在做自动充电、充电枪引导或车辆充电口质检的视觉工程师。2. VOC标记结构与CCS1/CHAdeMO类别定义2.1 六类接口的外观差异这是分类先验在打开XML之前先建立类别先验。CCS1和CCS2都是Combo标准它们在交流插座下方增加两个直流大针脚针脚粗且间距固定区别只在于交流段底座是Type1还是Type2。Type1多见于北美是五边形轮廓的7针交流口Type2多见于欧洲是圆角矩形7针交流口CHAdeMO来自日本轮廓更接近正方形带有一个明显的圆形通信接口。特斯拉的插件轮廓在六类里最窄接口上部有锁扣底部没有额外直流孔。车辆表面曲率、颜色和反光会让这些特征在图像里模糊分类时必须同时看轮廓宽高比和针脚排布。类别常见市场关键视觉特征最容易混淆对象Tesla北美、中国部分超充窄跑道形轮廓按钮区在上方Type2、CCS2CCS1北美Type1七针下方加两个直流孔上下双层CCS2、Type2CCS2欧洲Type2七针下方加两个直流孔外壳方正CCS1、Type2CHAdeMO日本、欧洲近似正方形的圆角轮廓圆形通信针Type2、CCS2Type1北美、日本五边形轮廓七针横排无下排孔CCS1Type2欧洲圆角矩形七针内部有挡板CCS2、Tesla这张表对应到标注时需要把“特斯拉”统一写成TeslaCHAdeMO不要写ChadeMo。原始压缩包标题里的ChadeMo是拼写变体实际标准叫CHAdeMO。如果训练框架以标签文本区分类别大小写不一致会让同一个接口被拆成两个类CHAdeMO样本本来就少再被拆开就没法收敛。我的建议是在使用前先做一次字符串归一化把所有标签统一成首字母大写、其余小写的形式。这六个类别并不是等价的。CCS1和CCS2的差别仅在交流针脚区Type1与CCS1在普通视角下几乎一样唯一的稳定特征是CCS1下方多出的两个直流孔训练时如果图像来自低分辨率摄像头这两个孔在缩放到640后经常只剩下两三个像素。这也是为什么这类任务不能只看总体准确率必须单独看CCS1的recall。我在实际项目中会先检查训练图的分辨率分布低于960x540的样本要单独复制一份做增强否则模型学到的是插口周围的塑料壳纹理。2.2 Roboflow导出的XML长什么样这份zip里没有像公开数据集那样规整的images和labels目录文件命名是connector_127_png_jpg.rf.40e2d9f8438e16707d6c8d78f8b4fb96.xml这种形式。这个命名是Roboflow导出VOC格式时的特征connector_127是原图名png_jpg是Roboflow生成的副本格式rf.后面的哈希用于区分同一张图的不同导出副本。如果一个xml对应一张图片图片文件名就是前面去掉.xml后的.jpg。解析时不要自己改文件名否则图片和标签的对应关系会断。annotation folderroboflow/folder filenameconnector_127_png_jpg.rf.40e2d9f8438e16707d6c8d78f8b4fb96.jpg/filename size width1920/width height1080/height depth3/depth /size object nameCCS2/name poseUnspecified/pose truncated0/truncated difficult0/difficult bndbox xmin328/xmin ymin411/ymin xmax712/xmax ymax689/ymax /bndbox /object /annotationbndbox保存的是原始像素坐标不是归一化坐标。width和height就是图片分辨率坐标必须落在0到width、0到height之间。如果一个xml里有多辆车的多个充电口就会有多个object块每个块有自己的name和bndbox。Roboflow导出时还可能附带segmented等其他标签训练用不到直接忽略即可。如果这批XML是公开数据集中下载的需要注意zip里可能只有xml没有jpg此时需要先把对应原图补齐再进训练流程否则后面所有脚本都会空转。3. 从VOC清洗到YOLO格式坐标归一化的正确姿势训练前第一件事不是转格式而是看类别分布。比如Type1的样本量远多于CHAdeMO时模型会把所有偏圆的接口都判成Type1。先解析全部XML统计每个name出现次数顺便找出损坏文件。这个脚本在任何有XML格式的数据集上都通用不限于充电口识别。3.1 解析XML统计类别分布import glob import xml.etree.ElementTree as ET from collections import Counter xml_files glob.glob(/data/charging_inlet/*.xml) counter Counter() broken [] for xf in xml_files: try: tree ET.parse(xf) except ET.ParseError as e: broken.append((xf, str(e))) continue root tree.getroot() for obj in root.findall(object): label obj.find(name).text.strip() counter[label] 1 print(label count:, dict(counter)) print(broken xml:, broken)这里glob的模式按实际目录改如果XML分散在train/valid/test三个子目录需要把模式换成**/*.xml并在glob.glob里加recursiveTrue。统计分析中label拼写不统一是最常见的坑比如CCS1和ccs1并存合并后数量才真实。如果某个类少于20个框直接用这个类训练会得不到稳定梯度需要先做类别重采样或复制增强。损坏XML的数量如果超过1%要回头检查是不是文件没下载完整而不是直接删除。提示统计类别时同时记录每个标签框的面积CHAdeMO的框通常比Type2小面积分布能告诉你是不是存在大量套错的框。3.2 转换为YOLO txt归一化坐标YOLO训练框架不直接读VOC XML需要把绝对像素坐标转成相对坐标每个txt文件的一行对应一个框class x_center y_center width height。转换时最忌讳的是用固定宽度1280、固定高度720去归一化因为压缩包里的原图分辨率不统一。import glob import os import xml.etree.ElementTree as ET CLASSES [Tesla, CCS1, CCS2, CHAdeMO, Type1, Type2] OUT_DIR labels_yolo def normalize(xml_file): tree ET.parse(xml_file) root tree.getroot() size root.find(size) img_w float(size.find(width).text) img_h float(size.find(height).text) lines [] for obj in root.findall(object): name obj.find(name).text.strip() if name not in CLASSES: name {tesla: Tesla, ccs1: CCS1, ccs2: CCS2, chademo: CHAdeMO, type1: Type1, type2: Type2}.get(name) if name is None: continue cls_idx CLASSES.index(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) 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 if min(w, h) 0 or w 1 or h 1: continue lines.append(f{cls_idx} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) return \n.join(lines), os.path.basename(xml_file).replace(.xml, .txt) os.makedirs(OUT_DIR, exist_okTrue) for xf in glob.glob(/data/charging_inlet/*.xml): content, out_name normalize(xf) if content: with open(os.path.join(OUT_DIR, out_name), w) as f: f.write(content)转换时除以img_w和img_h而不是固定值是因为训练集中可能有1920x1080也有1280x720。过滤掉宽高非正数或超过1的框这类标注通常是标注工具导出的脏数据留着会让loss变成nan。上面的字典映射同时兼容了大小写不一致的情况把chademo归一化成CHAdeMO避免同一个类在标签文件里被拆成两类。3.3 训练/验证划分的细节Roboflow原生导出时如果选了train/valid/test比例会直接生成三个目录如果下载的只有单个标注文件夹就要自己划分。按8:1:1随机划分是常见做法但必须保证同一张图片的所有框都在同一个集合里不能一张图的标注一半在train一半在val。import random, shutil, pathlib random.seed(42) src pathlib.Path(/data/charging_inlet/images) dst pathlib.Path(/data/charging_inlet/split) for d in (train, val, test): (dst / d / images).mkdir(parentsTrue, exist_okTrue) (dst / d / labels).mkdir(parentsTrue, exist_okTrue) files list(src.glob(*.jpg)) random.shuffle(files) n len(files) cuts [int(n*0.8), int(n*0.9)] for idx, f in enumerate(files): if idx cuts[0]: split train elif idx cuts[1]: split val else: split test lab pathlib.Path(/data/charging_inlet/labels) / (f.stem .txt) shutil.copy(f, dst / split / images / f.name) if lab.exists(): shutil.copy(lab, dst / split / labels / lab.name)随机种子42保证每次划分结果固定。注意这里按文件名配对如果xml转换为txt时文件名被改过需要保持与jpg同名否则训练时图像和标签对不上yolo不会报错只会忽略所有目标。划分完成后检测一下每个集合的标签覆盖率用下面命令快速对比cd /data/charging_inlet/split for d in train val test; do img$(ls $d/images | wc -l) lab$(ls $d/labels | wc -l) echo $d images$img labels$lab done如果labels数量比images少说明有图无标签直接用循环比对文件名把缺失标签的图移出训练集。这一步不做训练过程会显得很正常但验证集里这张图永远没有预测目标mAP会莫名偏低。4. 基于YOLOv8的充电口识别训练与91.1%精度复现充电口目标在图像中属于中等尺度目标宽高比相对固定YOLOv8s在640分辨率下推理延迟能压到几十毫秒适合机械臂实时插枪。Faster R-CNN在小目标、密集场景更好但这里的误分类更多来自形状相似而非尺度差异单阶段检测加数据增强在几百张图上更容易收敛。摘要给出的91.1%在目标检测里一般对应mAP50口径也就是IoU阈值为0.5时的平均精度不是分类准确率把它当成验证集上的基准线更合理。4.1 data.yaml与训练命令把上一章的split目录组织好之后写一份数据描述文件。六个类名的顺序必须和转换脚本里CLASSES列表保持一致否则Tesla标签会落到CCS1的类别索引上训练出来的模型完全没法用。path: /data/charging_inlet/split train: train/images val: val/images nc: 6 names: [Tesla, CCS1, CCS2, CHAdeMO, Type1, Type2]yolo detect train \ datacharging_inlet.yaml \ modelyolov8s.pt \ epochs200 \ imgsz640 \ batch16 \ optimizerAdamW \ lr00.001 \ lrf0.01 \ patience30 \ mosaic1.0 \ mixup0.2 \ fliplr0.5 \ cacheram \ projectcharging_yolo \ namev8s参数表里几个直接影响精度的点imgsz不能低于512CCS1和CCS2的区分点在底部两个直流孔缩到448时这些孔可能只剩几个像素batch要按显存调整batch小就同步调低lr0mosaic把四张图拼在一起能缓解CHAdeMO样本少的问题但最后10个epoch建议关掉否则拼接边界会让验证集mAP出现抖动。参数建议值说明imgsz640保留Type1/Type2内部针脚纹理960更稳但显存翻倍batch16以单卡显存为准batch小则调低lr0optimizerAdamW小数据集收敛比SGD快mAP波动略大mosaic1.0缓解CHAdeMO样本少的问题最后阶段关掉mixup0.2提升形状相似类别的泛化过大会导致边缘模糊patience30验证集mAP连续30轮不升就停避免过拟合训练过程中如果loss变成nan优先检查三件事XML转换出的坐标是否越界、data.yaml里nc是否与实际类别数一致、batch是否超过显存导致混合精度溢出。这三个原因在充电口数据集上发生的概率远高于模型结构问题。4.2 验证指标与混淆矩阵解读训练结束后单独跑一次验证conf设低是为了让每个候选框都参与mAP计算否则一些低置信度的真样本会被提前过滤掉指标虚高。yolo detect val \ datacharging_inlet.yaml \ modelcharging_yolo/v8s/weights/best.pt \ splitval \ conf0.001 \ iou0.6看结果时重点盯三类指标CCS1的recall、CHAdeMO的precision、Tesla的recall。CCS1和CCS2混淆是因为两个直流孔在图像里太小CHAdeMO precision低是因为Type2倒置后轮廓接近Tesla recall低通常因为深色车漆导致整个充电口区域对比度不足。混淆矩阵在charging_yolo/v8s/confusion_matrix.png如果两个类别连续多轮互混先补这两个类的近距离样例而不是调NMS阈值。5. 从验证集到实车部署时最容易翻车的三个细节5.1 充电口 vs 充电枪负样本不能省在真实场景摄像头经常看到插枪头而不是插座训练集如果只有插座模型会把枪头误报成CCS2。常见做法是收集几百张枪头照片作为负样本单独建一个plug类让模型把充电枪和插座区分开。如果不想加类别就在NMS之后检查检测框的宽高比充电口的框通常更宽扁枪头更窄长。5.2 低光与反光用颜色增强替代换模型夜间充电口识别红外补光下Type1和Type2轮廓几乎一样此时不需要换大模型在原有best.pt上做颜色增强重训一轮就行yolo detect train \ modelcharging_yolo/v8s/weights/best.pt \ datacharging_inlet.yaml \ epochs50 \ imgsz640 \ hsv_h0.015 \ hsv_s0.7 \ hsv_v0.4 \ degrees5 \ translate0.1 \ scale0.5 \ fliplr0.5 \ cacheTruehsv_v0.4把亮度变化范围拉大让模型不依赖金属反光位置degrees5限制旋转因为充电口不会倒置过度旋转会产生伪样本。重新训练时用小学习率epochs给50就够再长会破坏之前学到的轮廓特征。5.3 导出ONNX并调整NMS阈值验证完直接导出ONNX在工控机上用onnxruntime跑推理可以摆脱PyTorch环境依赖yolo export modelcharging_yolo/v8s/weights/best.pt formatonnx opset12 imgsz640 dynamicTrue simplifyTrue导出后建议conf阈值取0.35到0.45iou阈值取0.45到0.5。如果类间重叠严重把conf调高因为充电口场景宁可漏检也不要误报。如果部署的是Tesla专用识别直接把conf提到0.65漏检的影响远小于把Type2误判成CCS2后的插枪动作。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价