ARTICLE DETAIL

资讯详情

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

药品布洛芬检测数据集实战:VOC与YOLO双格式解析与训练避坑指南

药品布洛芬检测数据集实战:VOC与YOLO双格式解析与训练避坑指南 简介本资源为面向目标检测初学者与药品视觉识别开发者的布洛芬检测数据集可用于训练和验证单类别目标检测模型适用于药品分拣、库存盘点、智能零售等场景的算法实验。压缩包共1430个文件约19.62MB包含476张jpg图片、476个VOC格式xml标注文件、476个YOLO格式txt标注文件及少量说明文件两种标注格式可直接对接主流检测框架省去格式转换步骤。标注由labelImg完成类别为buluofen共657个矩形框平均每张图约1.4个目标标注规范统一。目前已有175人学习下载适合需要快速搭建药品检测基线、验证模型效果或扩充训练样本的读者可节省数据采集与标注成本直接投入训练与调参。1. 476张药品布洛芬检测数据集从拿到压缩包到跑通第一轮训练药房货架、医院药房、自动化分拣线上布洛芬这类盒装药品的识别是个很具体的需求——盒子长得像、摆放角度乱、光照忽明忽暗用传统模板匹配基本没戏。这份「药品布洛芬检测数据集」就是冲着这个场景来的476张jpg图片配套476个Pascal VOC格式xml和476个YOLO格式txt单类别buluofen总框数657。标注工具是labelImg规则就是画矩形框没有分割路径的txt干净利落。它适合谁做药品零售盘点、智能药柜、仓储分拣的算法同学想快速验证一个单类别检测pipeline能不能跑通也适合刚入门目标检测、想拿一份格式规范的小数据集练手的人。476张不算大但胜在格式双份齐全VOC和YOLO都能直接用省掉自己转格式的功夫。下面我按实际拆包、转格式、训练、排坑的顺序把这份资源怎么落地讲清楚。2. VOC与YOLO双格式拆解目录结构、字段含义与转换逻辑2.1 压缩包解开后到底有什么拿到zip解压常见做法是得到两个平行目录一个放VOC一个放YOLO。VOC那边是JPEGImages存jpg、Annotations存xmlYOLO那边是images存jpg、labels存txt。因为摘要里明确写了「不包含分割路径的txt文件」所以不要指望有train.txt/val.txt这种划分文件得自己切。先确认文件数量对不对这是拆包后第一件该做的事# 统计jpg、xml、txt数量三者应该都是476 find . -name *.jpg | wc -l find . -name *.xml | wc -l find . -name *.txt | wc -l三个数字都是476才说明包完整。如果txt数量对不上大概率是解压时文件名编码出问题Linux下用unzip -O GBK再试一次。文件名形如buluofen_xyxr_369.jpg前缀统一说明是同一批采集没有混入其他来源的图这对单类别数据集是好事分布相对一致。2.2 VOC的xml里每个字段在说什么打开任意一个xml结构是标准的Pascal VOC。关键字段就几个filename对应图片名size里的width/height是原图尺寸object下的name是类别名这里全是buluofenbndbox里的xmin/ymin/xmax/ymax是左上角和右下角坐标单位是像素。这里有个容易忽略的点VOC的坐标是绝对像素值而且xmax、ymax是包含边界的转YOLO时如果直接减一或者不减会有1像素的偏差。657个框分布在476张图上平均每张1.38个框说明大部分图只有1个布洛芬盒子少数图有2个及以上。这个分布意味着训练时正样本不会太稀疏但也不能指望模型学会密集场景。2.3 YOLO的txt格式与归一化规则YOLO的txt每行一个目标格式是class_id x_center y_center width height五个值空格分隔后四个都是归一化到0~1的浮点数。class_id从0开始这里只有一类所以全是0。归一化公式是x_center (xmin xmax) / 2 / img_wwidth (xmax - xmin) / img_wy方向同理。写转换脚本时最容易翻车的地方是xml里的size字段有时和实际图片尺寸不一致尤其是经过二次压缩的图。稳妥做法是用PIL重新读一次图片拿真实宽高而不是信xml里的size。import os import xml.etree.ElementTree as ET from PIL import Image def voc_to_yolo(xml_path, img_path, out_path, class_map): # 用真实图片尺寸不信xml里的size with Image.open(img_path) as im: img_w, img_h im.size tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.findall(object): name obj.find(name).text.strip() if name not in class_map: continue cls_id class_map[name] bnd obj.find(bndbox) xmin float(bnd.find(xmin).text) ymin float(bnd.find(ymin).text) xmax float(bnd.find(xmax).text) ymax float(bnd.find(ymax).text) # 裁剪到图像边界防止越界框 xmin max(0, min(xmin, img_w - 1)) xmax max(0, min(xmax, img_w - 1)) ymin max(0, min(ymin, img_h - 1)) ymax max(0, min(ymax, img_h - 1)) xc (xmin xmax) / 2.0 / img_w yc (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {xc:.6f} {yc:.6f} {w:.6f} {h:.6f}) with open(out_path, w) as f: f.write(\n.join(lines)) class_map {buluofen: 0}这段脚本的逻辑说明先读真实图片尺寸再遍历xml里每个object把绝对坐标转成归一化中心点加宽高。参数上class_map把类别名映射到id单类别就是0坐标裁剪那几行是后悔药防止标注时手抖画出越界框导致归一化后出现负数或大于1的值YOLO训练时遇到这种值会直接报错或者静默丢弃。输出保留6位小数够用且不丢精度。2.4 划分训练集与验证集没有现成的划分文件得自己切。476张按8:2分训练380张、验证96张。注意要按图片切不能按框切否则同一张图的框会同时出现在训练和验证里造成数据泄漏。# 生成文件名列表后打乱再切分 ls images/*.jpg | shuf --random-source(yes 42) all.txt head -n 380 all.txt train.txt tail -n 96 all.txt val.txt--random-source固定随机种子保证每次切分结果一致方便复现。这一步看着简单但不固定种子的话两次训练结果对不上排查问题时会被这个玄学坑很久。3. 用YOLO格式跑通训练配置文件、参数设置与首轮结果判读3.1 数据集yaml怎么写YOLO系训练入口认一个yaml描述文件里面写路径、类别数和类别名。这份数据集单类别nc就是1names是[buluofen]。# buluofen.yaml path: /data/buluofen train: train.txt val: val.txt nc: 1 names: [buluofen]path是数据集根目录train和val是相对path的列表文件路径。列表文件里每行是图片的绝对或相对路径。常见做法是把图片和标签放成images/xxx.jpg和labels/xxx.txt同结构YOLO会自动把images替换成labels找标签。如果目录结构不是这样就得在列表文件里写全路径或者改代码里的路径替换逻辑。3.2 训练命令与关键参数以YOLOv8为例一条命令能跑起来yolo detect train \ databuluofen.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/buluofen \ nameexp1参数逐个说modelyolov8n.pt用nano版476张小数据集上大模型容易过拟合nano够用且快epochs100配合patience2020轮验证指标不升就早停省时间imgsz640是默认输入尺寸布洛芬盒子在图中占比中等640够分辨batch16看显存8G显存跑nano加640能到16不够就降到8lr00.01是初始学习率小数据集上可以再降到0.005减少震荡。如果要用VOC格式直接训得先转成YOLO因为现在主流YOLO实现不直接吃xml。转换脚本上面已经给了转完再按3.1写yaml。3.3 首轮结果该看什么指标训练完看runs/buluofen/exp1下的results.csv和confusion_matrix.png。重点看三个metrics/mAP50、metrics/precision、metrics/recall。单类别小数据集mAP50跑到0.9以上算正常如果只有0.6左右先别怀疑模型去查标注。657个框里如果有几十个框画得特别松或者特别紧mAP会被拉低。常见做法是抽10张验证集图片用yolo detect predict跑一遍把预测框和标注框叠一起看。如果预测框位置对但类别置信度低可能是学习率太大如果框位置偏检查归一化有没有算错。提示476张图训练时验证集只有96张mAP波动会比较大。跑三次不同种子取平均比单次结果可信。3.4 数据增强开哪些YOLO默认开mosaic、HSV抖动、随机翻转。这份数据集是药品盒翻转要小心水平翻转后文字镜像虽然检测框位置不变但模型学到的纹理特征会变。如果实际场景里布洛芬盒子不会倒置建议关掉上下翻转flipud0.0水平翻转保留fliplr0.5。mosaic增强对小数据集有帮助但会引入拼接边缘的伪影如果发现模型在干净背景上反而漏检把mosaic关掉再训一轮对比。4. 避坑与排查标注、格式、训练三处的血泪经验4.1 现象训练报错「negative coordinates」原因xml转txt时没做边界裁剪某个框的xmax超过了图片实际宽度归一化后x_center或width出现负数或大于1。labelImg标注时如果图片被缩放显示手画框容易超出边界。解决用2.3脚本里的裁剪逻辑把xmin/xmax/ymin/ymax都夹到[0, img_w-1]和[0, img_h-1]范围内。转完再扫一遍txt确认所有值都在0~1之间awk {if($20||$21||$30||$31||$40||$41||$50||$51) print FILENAME: $0} labels/*.txt有输出就说明还有越界回去查对应的xml。4.2 现象mAP正常但实际推理漏检严重原因训练集和验证集划分时数据泄漏同一张图的不同框被分到两边验证指标虚高。或者验证集图片和训练集图片来自同一段连续拍摄分布太像指标不代表真实泛化。解决按图片切分别按框切。切完检查train.txt和val.txt有没有重复文件名。更进一步如果图片是按时间顺序命名的比如_369、_370随机切分可能把相邻帧分到两边改成按文件名排序后隔几张抽一张做验证模拟真实场景的分布差异。4.3 现象训练loss震荡不收敛原因学习率太大或者batch太小导致梯度噪声大。476张图、batch16一个epoch只有24次迭代梯度估计本身就不稳。解决把lr0降到0.005甚至0.001加warmup_epochs3让前几轮学习率线性上升。如果还震荡把batch提到32显存够的话或者用梯度累积模拟大batch。另外检查一下有没有图片尺寸特别离谱的比如某张图是4000x3000resize到640后布洛芬盒子只剩几十像素这种图要么剔除要么单独处理。4.4 现象验证集上框位置对但类别置信度普遍偏低原因单类别数据集模型没有「不是布洛芬」的负样本可学背景和目标的边界模糊。加上657个框里可能有一部分是难例遮挡、模糊拉低了整体置信度。解决适当提高box损失权重或者在推理时把置信度阈值从默认0.25降到0.1看召回再根据业务需求调。如果实际部署要求高精度可以加一批纯背景图没有布洛芬的货架图作为负样本让模型学会区分。4.5 现象VOC和YOLO两份标注对不上原因转换脚本跑了两遍或者手动改过其中一份。476个xml和476个txt理论上应该一一对应框数都是657。解决写个校验脚本分别统计xml和txt里的框数对比是否一致import glob, os xml_boxes 0 for f in glob.glob(Annotations/*.xml): import xml.etree.ElementTree as ET xml_boxes len(ET.parse(f).getroot().findall(object)) txt_boxes 0 for f in glob.glob(labels/*.txt): with open(f) as fh: txt_boxes len([l for l in fh if l.strip()]) print(xml_boxes, txt_boxes) # 都应该是657对不上就以xml为准重新转一遍别手动补。5. 小数据集提点技巧从657个框里再榨出几个点476张图、657个框这个量级想训出能上线的模型光靠默认配置不够。我一般会做三件事。第一件是难例挖掘。先用默认配置训一轮拿模型在训练集上跑推理把置信度低于0.5但和标注框IoU大于0.5的样本挑出来这些是模型「看到了但没认准」的难例。把这些图复制一份在训练时重复采样相当于给难例加权。具体做法是在列表文件里把这些文件名多写几遍YOLO按行采样写三遍就是三倍权重。第二件是锚框聚类。虽然YOLOv8是anchor-free但如果你用的是v5或者更早版本默认锚框是基于COCO的和布洛芬盒子的长宽比不一定匹配。用k-means在657个框的宽高上聚一次换成数据集自己的锚框召回能提一两个点。命令是yolo detect train ... anchors9让它自动聚类或者手动跑k-means脚本。第三件是推理时的TTA。训练完部署前用多尺度加水平翻转做测试时增强mAP通常能再涨0.5到1个点。代价是推理耗时翻几倍看业务能不能接受。如果只是做离线盘点TTA值得开如果是实时分拣线老老实实单尺度。验证方法上别只看mAP。抽20张验证集图片人工数一遍漏检和误检算一个业务口径的准确率。我见过mAP 0.92但实际漏检三分之一的案例原因是验证集里大部分图背景干净而实际场景背景杂乱。所以拿到这份数据集后最好再补拍几十张真实场景图做测试集哪怕不训练只用来评估也比纯用验证集靠谱。从那以后我每次拿到小数据集都强制走一遍「真实场景测试集」这一步哪怕只有20张。希望帮到你。本文还有配套的精品资源点击获取
返回列表