简介这是一份面向计算机视觉入门与进阶学习者的电池检测数据集聚焦 9 伏电池、纽扣电池、干电池三种常见类型的识别与定位可作为目标检测项目的数据基础。资源以 YOLOv7 标注格式组织压缩包共 2000 个文件其中 1999 个 txt 标注文件对应每张图片的类别与边界框信息每行记录一个目标的类别编号和归一化坐标另有 1 个 yaml 数据配置文件用于设置训练/验证路径、类别数量与名称。压缩包整体约 65.72MB文件命名规律清晰便于按原始图片或视频截帧对应检索。资源标题表明原始数据集包含 2030 张 640×640 分辨率图片YOLOv7 上正确识别率可达 97.7%适合用于模型训练、精度验证、算法对比和课程设计等场景。目前已有 48 人学习下载可作为电池目标检测方向实用的标注数据集。1. 电池识别数据集值不值得用2030张640×640原图与97.7%识别率意味着什么回收分拣线上传送带一小时过几千节电池人工挑9伏、挑纽扣电池、挑干电池眼睛盯两小时就花。这种场景最缺的就是一个能直接用的电池数据集。标题里这个数据集卖点很直接——2030张原始图、640×640分辨率、YOLOv7标注格式、正确识别率97.7%。四个条件放在一起意味着不用从零拍图、清洗、标注拿到手就能直接扔进YOLOv7训练省掉整个项目里最磨人的数据准备阶段。目标读者也很明确做电池回收分拣、智能垃圾箱的工程师或者想拿小目标检测练手的人。2. 拆解数据集2030张640×640原始图与YOLOv7标注文件的组织方式拿到任何标注数据集第一步不是急着训练而是把家底摸清楚。标题给的信息不多2030张原始图、640×640分辨率、三类电池、YOLOv7标注格式全在这一句话里。我一般会花半小时核对三件事——目录结构是否规整、标注坐标是否越界、类别分布是否均衡。这三件事决定了训练的起点也决定了97.7%这个识别率能不能在你手上复现出来。2.1 三类电池的形态差异决定这是一道覆盖三种难点的检测题9伏电池是方正的块状顶部有卡扣式金属接头在强光下两个触点反光非常刺眼。它在640×640的画面里通常占80×120像素左右属于中等目标YOLOv7的P4、P5检测头都能照顾到难点不在尺寸而在高反光带来的误检。纽扣电池是直径10到25毫米的金属圆片。以常见的50厘米视场、640×640分辨率的相机配置来说它在画面里只有15到40像素见方正好落在小目标的典型区间。YOLOv7有三个检测头stride分别为8、16、32这个尺寸得靠stride 8的P3层兜底锚框也得有足够小的预设来匹配。干电池AA、AAA这类是细长圆柱长宽比经常到4:1甚至5:1表面印刷商标、颜色花哨每一节电池的图案都不一样。这一类的难点是类内差异大模型容易去记商标颜色而不是学圆柱体轮廓。三类目标形态完全不重叠等于一次把小目标、高反光、极端长宽比三个检测难点全占了。也正因如此标题里强调原始图三个字才有意义没有预处理痕迹你才能干净地复现指标也才能自己掌控增强策略而不是继承别人加工过的痕迹。2.2 标注文件长什么样YOLO格式txt、类别id与坐标边界核对YOLOv7沿用Darknet的YOLO标注格式。每张JPG图片对应labels目录下一个同名txt文件图片里每个目标占一行五个字段类别id、归一化中心x、归一化中心y、归一化宽、归一化高空格分隔所有坐标除以图片宽高后落在0到1之间。这套数据集的类别映射通常长这样我训练时也沿用这个顺序类别ID类别名640×640下典型像素尺寸主要难点09v_battery9伏电池约80×120顶部金属卡扣反光1button_cell纽扣电池约15×40小目标依赖P3层2dry_battery干电池约30×140长宽比大印刷纹理多变类别id的顺序会写进data.yaml的names列表训练和推理都按这个索引走。中途如果换数据集或合并类别id一旦错位训练不报错但指标直接崩这种不报错地错最坑。拿到包以后别急着训先跑一遍标注检查脚本。我常用的核对逻辑有三条坐标越界说明标注工具或转换脚本有bug空标注说明有图片漏标超小框说明框贴目标太紧或者误标。脚本如下# check_labels.py —— 检查YOLO标注是否越界、为空、过小 from pathlib import Path label_dir Path(datasets/battery/labels) img_w img_h 640 # 数据集统一分辨率 for txt in label_dir.glob(*.txt): lines txt.read_text().strip().splitlines() if not lines: print(f[空标注] {txt.name}) continue for i, line in enumerate(lines): parts line.split() if len(parts) ! 5: print(f[格式错误] {txt.name}:{i1} 字段数{len(parts)}) continue cls, cx, cy, w, h int(parts[0]), float(parts[1]), float(parts[2]), float(parts[3]), float(parts[4]) # 归一化坐标必须在[0,1]宽高必须为正 if not (0 cx 1 and 0 cy 1 and 0 w 1 and 0 h 1): print(f[越界] {txt.name}:{i1} cls{cls} cx{cx:.3f} cy{cy:.3f} w{w:.3f} h{h:.3f}) # 反算像素尺寸筛出疑似误标的超小框 if w * img_w 8 or h * img_h 8: print(f[超小框] {txt.name}:{i1} 像素尺寸约{w*img_w:.0f}x{h*img_h:.0f})脚本逻辑很简单逐行解析五个字段越界和超小框的行全部打印出来。这里把8像素当阈值是因为YOLOv7下采样倍率最大是32一个8×8像素的目标最后只剩不到一个网格基本不可能被稳定召回出现这种框多半是标错了。修正时用labelme、labelImg或者cvat这类标注工具打开对应图片手动画一遍别偷懒。2030张图听着不少但只要有几十个坏标注整体mAP就被拖低一到两个点。97.7%这个级别的指标一个点的差异就决定了模型能不能在分拣现场用所以这一步值得花时间。2.3 划分train/val分层抽样而不是简单shuffle把图片直接随机切出20%当验证集是新手最容易犯的错。电池数据集的类别天然不均衡干电池图可能占了一半纽扣电池图也许只有三成。如果随机切小类样本可能全落进训练集验证集里纽扣电池的AP算出来虚高或虚低复现97.7%时对不上账。我的做法是按图片的类别组合分层保证每类电池在训练集和验证集里的比例一致# split_data.py —— 按类别组合分层生成train.txt/val.txt不移动原文件 import random from pathlib import Path random.seed(42) # 固定随机种子保证可复现 root Path(datasets/battery) imgs sorted((root / images).glob(*.jpg)) buckets {} # 桶key 图片包含的类别组合 for img in imgs: lbl root / labels / (img.stem .txt) classes tuple(sorted({int(l.split()[0]) for l in lbl.read_text().strip().splitlines()})) buckets.setdefault(classes, []).append(img) train_f, val_f [], [] for classes, lst in buckets.items(): random.shuffle(lst) n int(len(lst) * 0.8) # 每个桶内按8:2划分 train_f lst[:n] val_f lst[n:] # 写入YOLOv7所需的图片清单使用绝对路径 (root / train.txt).write_text(\n.join(str(p.resolve()) for p in train_f)) (root / val.txt).write_text(\n.join(str(p.resolve()) for p in val_f)) print(ftrain{len(train_f)} val{len(val_f)})桶的key是图片包含的类别组合比如一张图同时有9伏和干电池就归到(0,2)这个桶。在每个桶内部按8:2切就保证了单纯的纽扣电池图和混合图在训练、验证两侧的比例一致。2030张图的规模下验证集能稳定拿到400张左右badcase分析时样本量够看。比例上8:2或9:1都行我习惯8:2验证集更厚指标更可信。注意验证集一旦划分好就冻结后续的难例挖掘、补标注都只往训练集里加验证集保持最初那份。否则最后复现出的97.7%是对着答案做考试没有说服力。3. 复现97.7%识别率YOLOv7训练命令与四个该抠的参数标题里的正确识别率97.7%在目标检测语境下我默认是验证集上的mAP0.5。复现第一步是对齐口径别拿mAP0.5和mAP0.5:0.95去比后者通常要低七八个点不是模型不行是评价标准不同。3.1 环境准备版本对齐是复现的第一步YOLOv7对PyTorch版本不算挑剔我常配合Python 3.8、PyTorch 1.12或1.13、CUDA 11.7这一套组合兼容性最好。仓库拉下来先装依赖数据集用软链接放进datasets目录省磁盘也省等待# 拉取YOLOv7官方仓库并安装依赖 git clone https://github.com/WongKinYiu/yolov7.git cd yolov7 pip install -r requirements.txt # 数据集软链接把解压后的battery_dataset链接到datasets/battery mkdir -p datasets ln -s /data/battery_dataset datasets/battery # 训练前确认GPU可用并查看显存大小以决定batch-size python -c import torch; print(CUDA:, torch.cuda.is_available()); print(显存:, torch.cuda.get_device_properties(0).total_memory/1024**3, GB)软链接在Windows上对应mklink /D或mklink /J数据集在另一块盘时用目录联接更省事。GPU确认这步别省2030张图、640分辨率、200轮一块8GB显存的卡大约四到六小时跑完CPU按天算视觉任务不值得等。显存只有6GB就把batch-size降到8优先保证训练能跑起来。3.2 data配置与训练命令最简可复现路径YOLOv7的数据配置是一个yaml文件指定训练、验证图片清单、类别数和类别名。对应这个电池数据集我写的data/battery.yaml长这样# data/battery.yaml —— 三类电池的数据配置 train: datasets/battery/train.txt val: datasets/battery/val.txt nc: 3 names: [9v_battery, button_cell, dry_battery]train.txt和val.txt来自2.3的划分脚本每行一张图片的绝对路径。如果你拿到的是已经按train/val分好目录的数据集yaml里也可以直接填两个目录名train.py支持目录路径。清单就位后启动训练# 训练200轮、640分辨率、用COCO预训练权重做迁移学习 python train.py \ --workers 4 \ --device 0 \ --batch-size 16 \ --epochs 200 \ --img 640 640 \ --cfg cfg/training/yolov7.yaml \ --data data/battery.yaml \ --weights yolov7.pt \ --hyp data/hyp.scratch.p \ --name battery_run逐参数说明--workers 4是数据加载线程数2030张图不大4个足够开太多在Windows上容易卡死--device 0是GPU编号--batch-size 16在8GB显存上刚好11GB以上可以上32--img 640 640是训练分辨率必须跟数据集原始分辨率一致这是复现97.7%的前提--weights yolov7.pt是COCO预训练权重小数据集必须迁移学习从零训练2030张图到不了这个指标--hyp data/hyp.scratch.p是YOLOv7自带的增强超参数默认mosaic1.0后面讲什么时候要改。训练日志会实时打印每个epoch的box_loss、obj_loss和val mAP。我判断收敛的习惯是看val mAP曲线前50轮涨得快100轮后变缓连续20轮不再上升就可以停。best.pt按val mAP自动保存不用手动挑权重。3.3 四个真正决定最终指标的训练参数同样是这条命令四个参数微调一下结果可能差两三个点参数建议值对电池任务的影响--img640 640低于640纽扣电池有效像素缩水mAP明显下滑--batch-size8~32太小BN统计不稳太大容易在小数据集上过拟合--epochs150~250超过250验证损失往往开始回升hyp的mosaic0.5~1.0堆积场景保留1.0单目标干净场景降到0.5更稳第一个是分辨率。数据集本身640×640训练用640意味着不放大不缩小纽扣电池那批15像素的目标保住了。为了提速降到320小目标直接消失P3层等于废掉。第二个是batch-size它影响BatchNorm的统计量电池形状规整8和32可能差0.5个点。第三个是epochs小数据集跑满默认300轮大概率过拟合我第一版就吃过这个亏200轮合适。第四个在hyp文件里。修改方式是复制data/hyp.scratch.p成hyp.battery.yaml改mosaic那一行再传参别动原文件方便回退。mosaic对堆积场景的提升很明显但如果验证集全是单个电池的干净图mosaic反而拉大了训练分布和验证分布的差距。4. 部署验证把97.7%从验证集搬到传送带现场训练指标好看不等于现场好用。验证集是静态图光照一致、没有运动模糊产线传送带上的电池是动的可能互相遮挡、沾灰、反光角度随时变。我习惯做两层验证先用val.py复测指标对齐口径再用detect.py对现场视频抽帧看真实分布下的表现。4.1 detect.py批量推理置信度阈值按分拣代价来定detect.py是YOLOv7自带的推理入口既可以对图片文件夹跑也可以接摄像头rtsp流。# 用best.pt对验证集图片做批量推理保存可视化结果和txt检测输出 python detect.py \ --weights runs/train/battery_run/weights/best.pt \ --source datasets/battery/val/images \ --img 640 \ --conf 0.25 \ --iou 0.45 \ --save-txt \ --project runs/detect/battery_val--conf 0.25是默认置信度阈值低于它的预测被丢弃--iou 0.45是NMS的IoU阈值两个框重叠超过这个比例就合并。对电池分拣来说这两个值怎么调取决于下游代价9伏被误分成干电池分拣仓就混料了返工成本很高这时conf应该上调到0.4甚至0.5宁可漏检也别错分。漏检大不了补拍一帧错分要人工重新分拣代价完全不同。这个权衡想清楚阈值才有意义。输出的runs/detect/battery_val目录里每张图带一个同名txt每行是类别id 置信度 x1 y1 x2 y2。我建议顺手统计一下全部预测的置信度分布如果一张图平均只有两三个框而实际摆了五六节电池说明conf偏高或NMS合并严重回第5章排查。提示调阈值要对着分拣现场的badcase调别只盯着验证集的mAP数字。4.2 val.py复测mAP97.7%是怎么算出来的val.py算的是指标本身两个参数容易误导# 复测验证集mAPconf设极低是不想截断召回曲线 python val.py \ --weights runs/train/battery_run/weights/best.pt \ --data data/battery.yaml \ --img 640 \ --conf 0.001 \ --iou 0.65--conf 0.001是为了画PR曲线时不漏掉低置信度预测否则mAP被阈值截断显得虚高--iou 0.65是PR曲线上每个判定点的IoU标准。跑完输出表里的mAP0.5就是要去和97.7%对齐的口径。重点看三类各自的AP9伏可能98%、干电池99%、纽扣电池只有90%整体平均好看但掩盖了纽扣电池这条短腿。逐类AP才是验收报告里真正要写的内容这也是第6章继续优化的依据。4.3 ONNX导出与边缘端帧率规划现场部署常见做法是导出ONNX再转TensorRT的FP16引擎跑。# 导出带grid输出的ONNX简化图结构方便后续转换 python export.py \ --weights runs/train/battery_run/weights/best.pt \ --grid \ --simplify \ --img-size 640 640 \ --batch-size 1--grid把检测解码留在模型内部导出的模型直接输出x1y1x2y2、置信度和类别不懂YOLO输出结构的同事也能接手--simplify用onnx-simplifier做图优化转TensorRT前建议先跑。转TensorRT用trtexecFP16在这个模型上基本不掉点速度翻倍。帧率有个估算公式传送带速度乘以相机视场宽度再除以要求的检测间距就是最低帧率。比如带速0.5米/秒、视场宽0.5米、每10厘米检测一次最低5帧每秒。电池分拣不需要60帧稳定在15到30帧就够留出余量给光照突变和系统io抖动。真正上了产线97.7%掉到93%到95%之间是正常现象所以训练指标要留冗余。5. 避坑记录电池数据集训练中我踩过的五个坑这个数据集标题看着干净真正训练起来翻车的地方一点不少。下面五条是我在电池检测项目里反复遇到的按现场出现频率排序每条都是现象、原因、解决三个环节的完整记录。前两条影响指标后三条影响现场可用性建议全看。5.1 纽扣电池小目标漏检逐类AP被整体拖低现象训练完看逐类AP9伏和干电池都在98%上下纽扣电池只有88%左右抽检推理图小尺寸的纽扣电池经常没框。原因640×640下纽扣电池只有15到40像素YOLOv7的P3层虽然是兜小目标的主力但默认锚框偏大加上部分标注框把金属反光的外圈也框了进去模型学到的是大一圈的圆而不是电池本体。我把18×18像素以下的框全部导出来人工复核了一遍发现三成是把反光晕圈框进去了这个比例相当惊人。解决先跑第2章的check脚本把像素尺寸小于15×15的框导出来核对明显扩大了的用标注工具改小。再让YOLOv7的autoanchor干活——训练启动时会打印anchor recall看到低于0.9就让它自动重算不要跳过。这两步做完纽扣电池的AP通常能涨两到三个点。5.2 9伏电池金属卡扣反光被误检成干电池现象现场抽帧里9伏电池顶部两个金属触点被框成干电池置信度0.6以上非常顽固怎么调conf都压不掉。原因反光灯下9伏的亮金属和干电池正极帽在灰度纹理上高度相似模型学到的是亮金属干电池头部这个错误关联。本质是两类电池在训练图里的光照表现不一致模型没学会靠整体形状区分。解决先统一采集光照顶灯加扩散罩消除点状高光。再在训练集里补9伏电池的侧面和俯视角度让模型更多依赖长方体外轮廓。实在压不下去就在后处理加规则同一帧里9伏检测框内部出现的干电池预测直接丢弃用几何互斥兜底。这是典型的工程解法模型管不住的事规则来管。5.3 并排干电池的预测框在NMS后被吞并现象一排三节干电池并排放着推理结果只有两个框其中一个框横跨两节电池把两节电池框成了一个目标。原因标注时相邻电池的框贴得太近甚至互相接触NMS在iou 0.45下把高度重叠的两个预测当成同一个目标。两个预测的置信度都接近NMS按得分取舍高的留下低的被抹掉。这是标注习惯问题不是模型缺陷。解决标注时同类目标的框之间留出2到3像素间隙别切着目标边画线。推理端可以把--iou从0.45降到0.3试试能缓解但可能引入重复框。真正的解法还是回标注层把重叠样本单独整理一个子集来做验证确认修复效果后再整体复训。5.4 数据增强过猛干电池商标纹理被学丢了现象训练到后半段loss降不动badcase分析发现模型判断干电池完全依赖轮廓印刷的AAAAA字样区域没有被利用。原因hyp.scratch.p里hsv_s0.7、hsv_v0.4的颜色抖动对电池这种大面积纯色物体来说太猛商标颜色被随机漂移模型只能放弃颜色特征去学形状。颜色是这类任务的重要线索把它洗没了等于自断一臂。解决复制hyp文件成hyp.battery.yaml把hsv_s改成0.3、hsv_v改成0.2mosaic保留但把mixup关掉。电池识别本质是结构识别颜色是辅助信息增强策略要轻不能把鉴别性纹理洗掉。改完重新训练干电池的AP通常能回来一个点左右。5.5 类别不均衡纽扣电池图太少训练偏科现象2030张图里干电池相关图可能过半纽扣电池相关的不到三成训练出的模型对干电池过拟合对纽扣电池欠拟合。原因YOLOv7的损失逐类累积样本多的类别梯度占比大模型自然偏向学它。这是数据分布问题不是模型bug靠调超参解决不了。解决先从2.3的分层划分做起保证验证集类别比例一致。再把纽扣电池图片做离线复制增强旋转±30度、随机裁剪后贴到背景图上补进训练集。最后用x-anylabeling或cvat这类标注工具把漏检样本补标注出来几千张的规模不值得上自动化标注流水线手动补两三百框就够。6. 从97.7%继续往上推难例挖掘闭环与逐类AP验收97.7%不该是终点。我一般训练收敛后会做一轮难例挖掘把模型在置信度0.2到0.6这个灰色地带的预测框全导出来人工过一遍。6.1 只筛灰色地带的框不看高置信度结果置信度低于0.2的框多半是背景杂波不值得看高于0.6的要么对、要么错得一眼能看出来。灰色地带才是标注错误和难例聚集的地方。# mine_hard.py —— 导出置信度0.2~0.6的预测框供人工复核 import cv2, torch from pathlib import Path model torch.hub.load(WongKinYiu/yolov7, custom, runs/train/battery_run/weights/best.pt) for p in Path(datasets/battery/val/images).glob(*.jpg): img cv2.imread(str(p)) for det in model(img).pred[0]: x1, y1, x2, y2, conf, cls det.tolist() if 0.2 conf 0.6: # 灰色地带最有信息量 cv2.rectangle(img, (int(x1), int(y1)), (int(x2), int(y2)), (0, 0, 255), 2) cv2.putText(img, f{conf:.2f}, (int(x1), int(y1)-5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) cv2.imwrite(fhard/{p.stem}.jpg, img)把筛选出的图人工看一遍框错的用标注工具修正漏检的补上新框然后合并进训练集。这一步补进去的样本每一张都是模型真实出错的地方比随便加几百张新图有效得多。6.2 逐类AP验收别信整体数字补标后从best.pt继续微调50轮左右再用4.2的val.py复测。判断标准是逐类AP对比9伏、干电池基本不动纽扣电池从88%涨到93%这轮难例挖掘就成立。整体mAP可能只涨一个点但短板的厚度变了现场漏检率会明显下降。我做电池识别项目最大的教训拿到宣称97.7%的数据集先跑标注检查脚本再筛灰色地带badcase最后才谈训练。顺序一旦反过来浪费的是反复训练的时间这大概是这个项目里最贵的后悔药。希望帮到你。本文还有配套的精品资源点击获取
