ARTICLE DETAIL

资讯详情

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

VOC格式搅拌车数据集:1168张精标图片助力工程车辆检测

VOC格式搅拌车数据集:1168张精标图片助力工程车辆检测 简介本资源是面向计算机视觉初学者与目标检测算法开发者的工程车辆专用数据集聚焦搅拌车jiaobanche单类别识别任务适用于VOC格式模型训练、算法验证及课程实验等场景。压缩包共2337个文件含1168张JPG图像与1168份对应XML标注文件均使用labelImg工具按矩形框规范标注另附1份说明文本整体体积47.9MB结构简洁、开箱即用。目前已有218人学习下载体现了该细分场景数据在交通工程AI应用中的实际需求。用户可直接加载至Faster R-CNN、SSD等VOC兼容框架中训练无需格式转换全部标注覆盖1931个搅拌车实例图像涵盖多角度、多光照及常见工地背景具备一定泛化代表性为模型鲁棒性验证提供可靠基础。 搞目标检测的人应该都有过这种经历想训练一个模型识别工程车辆翻遍各种数据集网站要么是通用场景下的车类大杂烩要么是清洗得不够干净的爬虫图真正能直接用来落地训练的商用级数据少得可怜。尤其是搅拌车这种“工地特供”车型公开数据集里基本找不到成规模的标注样本。我整理这套VOC格式工程车辆数据集系列5搅拌车数据集一共1168张已经标注好的图片就是为了补上这个缺口。这个系列我按车型拆成多个子集之前做了渣土车、挖掘机、装载机第五期专门做搅拌车。图片全部来自真实工地、拌合站和城市道路场景统一转成VOC格式可以直接丢进YOLO、SSD、Faster R-CNN以及MMDetection等主流框架里训练。如果你是做智慧工地、车辆监管、交通流量统计或者辅助驾驶感知的这份数据应该能帮你省掉至少一周的采集和标注时间。1. 项目背景与数据定位1.1 为什么工程车辆数据集这么难找工程车辆在公开数据集里一直处于“存在但不够用”的状态。COCO和VOC里有car、truck、bus这些大类但搅拌车、渣土车、泵车这种特种车辆要么被归类到truck里要么干脆没有标注。真正做业务的时候模型如果连搅拌车和普通卡车都分不清那后续的车辆轨迹分析、违规闯入检测就全部白搭。很多人第一反应是自己去工地门口拍但实际操作起来坑很多工地场景光线变化大、车辆遮挡严重、不同角度的外观差异极大拍回来的原始素材要经过大量筛选才能用。而且标注特种车辆本身就比标注普通轿车费劲因为搅拌车的罐体、托轮、进出料槽这些部位在图像里经常不清晰标注员一犹豫就会把边界画歪。我做这套系列的初衷很简单就是把散落在各个项目里的车辆图片按车型重新整理、清洗、标注形成一个可以反复使用的私有数据集。搅拌车这一期是系列里比较特殊的存在因为它的外观特征足够明显但数据收集难度又比普通车辆高值得单独拎出来做一套。1.2 搅拌车为什么值得单独建一个类别搅拌车在视觉上和普通卡车最明显的区别是车身后部那个大罐体这个罐体通常是倾斜安装的而且颜色多为白色、灰色或者橙黄色。罐体上一般还有搅拌方向箭头、容积标识、公司名称等文字信息这些纹理在检测时既是特征也是干扰源。从检测算法的角度看罐体的倾斜角度和车辆行进方向之间的关系并不固定车头朝左罐体可能朝右车头朝右罐体也可能朝左所以不能简单用“车头方向车身位置”来推断罐体位置。另外搅拌车的工作状态有两种行驶状态和作业状态。行驶状态下罐体在旋转作业状态下罐体可能静止而且进出料槽会放下来这时候车辆的轮廓会发生明显变化。同一个类别内部存在这么大的形态差异如果数据里只有单一角度的样本模型很容易过拟合到“只能识别侧面45度角搅拌车”的程度。我在这1168张图里特意覆盖了正面、侧面、背面的不同状态目的就是让模型学到的是“搅拌车”这个类别的本质特征而不是某几个特定角度的模板。1.3 这个系列的数据规模与定位1168张图看起来不算多但对于单类别目标检测来说是够用的起步量。我的使用经验是单类检测任务1000张左右经过精心标注的图片配合合适的数据增强和预训练权重已经可以把mAP推到0.85以上。如果效果还不够再针对失败案例补充数据就行了没必要一上来就追求上万张。数据规模和标注质量之间存在一个平衡点与其拿5000张漏标严重的图去训练不如用1000张精确标注的图。这1168张是经过三轮人工筛选留下的结果原始采集图片大约有4000多张清洗掉了大量重复、模糊和角度过于诡异的画面。这期数据集的定位是“精标小样本”适合做三类事情第一直接作为正式训练集使用第二作为预训练数据用来微调自己的私有场景第三和系列其他车型数据合并组成多类别工程车辆检测数据集。2. VOC格式的构成与标注规范2.1 VOC数据集目录结构VOC格式是目标检测领域最经典的数据组织方式之一Pascal VOC竞赛把它发扬光大后几乎所有主流框架都保留了读取VOC格式的能力。这套搅拌车数据集的目录结构如下VOCdevkit/ └── VOC2027/ ├── JPEGImages/ │ ├── mixer_000001.jpg │ ├── mixer_000002.jpg │ └── ... ├── Annotations/ │ ├── mixer_000001.xml │ ├── mixer_000002.xml │ └── ... ├── ImageSets/ │ └── Main/ │ ├── train.txt │ ├── val.txt │ └── test.txt └── labels/ └── mixer_000001.txtJPEGImages里放图片Annotations里放XML标注文件ImageSets/Main下是划分好的训练、验证、测试文件列表。每个txt文件里存的是图片文件名不含扩展名一行一个。有的工具还会额外生成YOLO格式的label文件放在labels目录下方便直接用YOLO系列框架训练但我这里主力还是VOC标准结构。2.2 XML标注文件到底长什么样VOC格式的核心是XML文件一个图片对应一个XML里面记录了图片名称、来源路径、尺寸以及所有目标的类别和边界框坐标。annotation folderVOC2027/folder filenamemixer_000123.jpg/filename source databaseConcreteMixerDataset/database /source size width1920/width height1080/height depth3/depth /size segmented0/segmented object namemixer/name poseUnspecified/pose truncated0/truncated difficult0/difficult bndbox xmin356/xmin ymin208/ymin xmax1288/xmax ymax962/ymax /bndbox /object /annotation这里有几个字段需要特别注意。truncated表示目标是否被截断如果搅拌车有一部分超出图像边界这个值要标成1difficult表示目标是否难以辨认比如远距离小目标或者被大面积遮挡的搅拌车标成1后很多评估流程会默认忽略这类样本避免拉低mAP。我当时筛选的时候特意控制了这两个字段的比例让truncated样本占比在15%左右这样模型能学到“截断的搅拌车也要检测”又不会被大量不完整样本带偏。bndbox里的xmin、ymin、xmax、ymax是边界框的左上角和右下角坐标。坐标必须是整数而且不能超出图片尺寸范围。标注时最容易出的问题就是坐标越界某些标注工具在误操作时会把xmax写到大于图片宽度训练时解析XML就会报错。我后来的处理方式是写了一个小脚本在数据集发布前自动检查所有XML中的坐标是否越界越界的自动裁到边界值。2.3 标注工具选择与标注流程标注工具我用的是labelImg虽然它已经多年没有更新但胜在稳定、轻量、操作顺手。安装方式很简单pip install labelImg或者从GitHub克隆源码后直接运行git clone https://github.com/HumanSignal/labelImg.git cd labelImg pyrcc5 -o libs/resources.py resources.qrc python labelImg.py启动后在界面里点“Open Dir”选择图片目录再点“Change Save Dir”设置XML的输出目录。如果担心手动写类名容易拼错可以在labelImg的data目录下编辑predefined_classes.txt文件提前写入类名mixer这样每次画框后直接点快捷键就能自动选择类别。标注流程我按下面的步骤来打开一张图片先用W键或矩形框快捷键画出包含整个搅拌车的矩形框。框的边界尽量贴合车身的最外侧轮廓包括突出的后视镜、罐体、保险杠但不包括地面阴影。如果车辆被电线杆、栏杆或另一辆车遮挡框仍然要包含被遮挡部分的“物理存在范围”也就是想象这辆车不遮挡时的完整轮廓。对于多辆搅拌车同时出现的图片每辆车都要单独标注不能混在一个框里。标注完成后按CtrlS保存XML然后切换下一张。这个流程听起来简单但实际操作中遮挡情况是最大的挑战。两辆搅拌车并排停放时框的边缘会重叠这时候需要靠truncated和difficult字段来区分完全可见的标difficult0被另一辆车挡掉超过30%的标difficult1挡掉超过70%的直接不标注。这样做的好处是训练时模型不会因为大量重叠框而困惑。2.4 关于统一类别名的提醒很多人在自建数据集时容易犯一个错误同一个类别在不同批次标注中用了不同的名字比如第一周标“concrete_mixer”第二周标“cement_mixer”第三周又标“mixer”。算法会把它们当成三个不同类别导致每个类别的样本数量被严重稀释。我这套数据集从第一张图开始就锁定了类别名为mixer相关文档和脚本里保持一致。你自己扩展数据时如果要把新标注的图片合并进来第一件事就是检查所有XML里的name字段是否统一最好用命令批量检查一下。grep -r name Annotations/ | awk -F {print $2} | awk -F {print $1} | sort | uniq -c如果发现类别名有出入马上用sed批量替换别拖到训练前再处理。3. 1168张数据的采集、清洗与分布3.1 采集场景怎么设计数据采集不是拿个相机随便逛一圈就完事你得先想清楚模型将来要部署在什么场景。我针对搅拌车的常见落地场景把采集目标拆成四类施工现场内部搅拌车在基坑边、料场、泵车旁作业背景复杂有大量钢筋、脚手架、渣土堆。拌合站出入口车辆排队进出通常有固定的角度和路线背景相对单一。城市道路搅拌车在红绿灯路口、收费站、施工路段行驶周边有轿车、公交车、行人。夜间和阴天低光照、逆光、雨天等条件下的样本。这四类场景在最终数据集里的比例大约是4:2:3:1。有人会觉得拌合站出入口的图最好标应该多采一些但我不建议这么做因为背景太单一会让模型学到“看到水泥罐和门禁就认为是搅拌车”这种错误的关联性。反而是施工现场内部的复杂背景对模型泛化能力提升更大。3.2 筛选规则哪些图被淘汰了初始采集的4000多张图最终只保留1168张淘汰率接近70%。淘汰的图主要包含这几类严重模糊的车速快导致运动模糊或者相机对焦失误这类图即使人眼能识别模型也很难学到有效特征。目标占比过小的搅拌车在图片中占据的面积小于32x32像素左右检测器几乎不可能稳定识别直接淘汰。重复度极高的连续帧图片中车辆位置基本没变保留中间一帧即可其余删除防止数据冗余导致过拟合。目标被遮挡超过70%的只露出一个车头或者一个罐体边缘标注出来的框意义不大。画面严重过曝或过暗的保留少量极端光线样本可以增强鲁棒性但太多就会干扰训练。筛选时我采用了一个简单但有效的辅助方法先利用一个现成的车辆检测模型跑一遍所有图片把检测置信度低于0.3的图挑出来人工二次查看。这里面大部分是模糊或者目标太小的但也有小部分是因为搅拌车外观和普通卡车相似导致模型漏检这类反而是我需要重点保留的难例。3.3 数据分布的验证数据整理完成后我统计了每张图中的目标数量。1168张图里单目标图片有862张双目标图片有216张三目标及以上有90张。这个比例说明数据集以单目标为主但包含一定量的多目标场景不至于让模型在训练时被大量拥挤样本干扰。标注框的大小分布也是关键指标。我统计了所有标注框宽度与图片宽度的比值发现大部分框的宽度占比在20%到60%之间这个范围比较理想。如果大量标注框占比超过80%意味着很多图是近景大目标模型学会的是“大目标检测”如果大量框占比低于10%那模型学的是“小目标检测”。两者对特征金字塔的要求完全不同混在一起训练容易顾此失彼。4. 数据划分、增强与框架适配4.1 划分训练集、验证集、测试集数据集划分对模型评估的可信度影响很大。我按6:2:2的比例划分也就是700张训练、234张验证、234张测试。划分的时候有两个原则第一同一条路连续拍摄的图片不能同时出现在训练集和测试集里否则测试集评估出来的精度会虚高。我的做法是先把图片按照拍摄地点分组然后按组为单位划分而不是直接随机打乱。第二尽量保证测试集中包含夜间、雨天、遮挡等难例样本比例和整体数据集的难例比例接近这样测出来的mAP才有参考意义。划分后生成的文件直接用脚本完成python split_voc.py --image_dir JPEGImages --annotation_dir Annotations --output_dir ImageSets/Main --train_ratio 0.6 --val_ratio 0.2 --test_ratio 0.2 --group_by_dir4.2 数据增强策略怎么定1168张原始图片对深度学习模型来说不算多数据增强是绕不开的环节。我试过几种主流增强方式最终在训练时固定使用以下几种组合随机翻转水平翻转概率0.5。搅拌车虽然罐体有方向性但翻转后仍然是搅拌车不影响类别语义。随机缩放在0.5到1.5倍之间随机缩放模拟不同距离下的目标尺度变化。亮度对比度扰动搅拌车罐体颜色多样白色罐体和灰色罐体在不同光照下差异很大这项增强很有必要。Mosaic增强把4张图拼接成一张可以有效提升模型对目标尺度的适应能力。MixUp增强按一定比例混合两张图和对应的标签提高模型的鲁棒性。我用的是YOLOv8自带的增强策略它在训练时默认开启Mosaic和随机透视变换。如果你的框架不支持这些增强可以在数据输入管道里自己实现。要注意的是Mosaic增强在训练后期应该逐渐关闭否则模型会一直依赖拼接图的上下文信息导致在真实单图场景上的性能下降。YOLOv8有close_mosaic10这个参数意思是在最后10轮关闭Mosaic这个设计是合理的。4.3 从VOC到YOLO、MMDetection的转换VOC格式是通用格式但不同框架的输入格式不一样。YOLO系列需要的是每个图片一个txt文件每行内容为“类别id x_center y_center width height”这些坐标都是相对于图片宽度和高度的归一化浮点数。转换脚本本身不复杂import xml.etree.ElementTree as ET import os def voc_to_yolo(xml_file, class_list): tree ET.parse(xml_file) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_list: continue cls_id class_list.index(name) xmin int(obj.find(bndbox/xmin).text) ymin int(obj.find(bndbox/ymin).text) xmax int(obj.find(bndbox/xmax).text) ymax int(obj.find(bndbox/ymax).text) x_center (xmin xmax) / 2 / img_w y_center (ymin ymax) / 2 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) return lines class_list [mixer] xml_dir Annotations label_dir labels os.makedirs(label_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue lines voc_to_yolo(os.path.join(xml_dir, xml_file), class_list) txt_name os.path.splitext(xml_file)[0] .txt with open(os.path.join(label_dir, txt_name), w) as f: f.write(\n.join(lines))MMDetection则可以直接使用VOC格式的数据集只需要在配置文件里指定data_root指向VOCdevkit目录然后将type设为VOCDatasetann_file设为ImageSets/Main/train.txt即可。如果你用的是mmrotate做旋转目标检测那需要把标注格式转成DOTA格式这属于进阶玩法了。5. 模型训练实测与问题排查5.1 基于YOLOv8s的实测效果我拿这套数据在YOLOv8s上跑了一组实验batch size为16输入分辨率640x640训练100轮。优化器用SGD初始学习率0.01动量0.937权重衰减0.0005。训练过程中mAP0.5从第10轮的0.72提升到第60轮的0.91之后缓慢上升到第100轮的0.93。mAP0.5:0.95大概在0.68左右。这个结果只能说中等偏上原因是我没有针对这个数据集做任何超参数调优。如果换成YOLOv8m或者加大输入分辨率到1280mAP0.5还能再涨两个点左右。但我想说的是1168张数据能把单类检测做到0.93的mAP0.5已经证明了“精标小样本”路线的可行性。测试集上的失败案例主要集中在这几种情况夜间远距离目标、搅拌车被塔吊钢丝绳遮挡、罐体颜色和背景颜色高度接近比如白色罐体停在白色围墙前。这些失败案例其实不是数据量的问题而是图像本身的辨识度问题靠增加数据也不一定完全解决可能需要在采集端投入更多的光照条件多样性。5.2 标注框不贴合问题标注质量直接影响训练效果。我复核过一遍标注发现最容易出问题的地方是搅拌车罐体的前后两端。罐体是椭圆形的在图片边缘会出现弧线标注员如果只盯着矩形框画经常会把罐体后部多包进去一块背景。这里我的经验是矩形框不需要切得那么精确但误差不应该超过目标宽度的5%。如果你用标注工具放大到200%后发现框的边缘和目标边缘之间还有明显空隙那说明标注不达标。另一个常见问题是漏标。一张图里有两辆搅拌车标注员只看到一辆第二辆被漏掉了这在检测任务里会被当作负样本处理损失很大。为了解决漏标问题我在标注完成后增加了一个“反向验证”步骤把所有标注框区域抠出来单独放到一个文件夹里人工快速扫一遍看有没有框错类别的情况。这个步骤虽然费时间但对数据集质量的提升是实实在在的。5.3 类别不平衡与误检怎么处理如果你是把这个搅拌车数据集和其他车型数据合并使用就会面临类间不平衡的问题。搅拌车1168张渣土车可能800张挖掘机可能600张如果直接混在一起训练模型会对搅拌车类别更敏感容易把挖掘机误检成搅拌车。我的处理方案是采样策略对样本量少的类别做复制增强重复采样对样本量多的类别做下采样让每个类别的批次数大致均衡。误检的另一个来源是搅拌车和水泥罐车的混淆。两者都有罐体但水泥罐车通常是固定罐搅拌车的罐体带有明显的前倾角度和托轮结构。如果模型把水泥罐车识别成搅拌车多半是训练数据里缺少水泥罐车的负样本。所以我在发布数据时特意附了一些负样本图片未标注直接作为背景让模型能学到搅拌车和水泥罐车之间的差异。这一点你在使用的时候可能也要补充负样本。6. 进阶玩法与数据集后续扩展6.1 检测加跟踪的落地用法拿到检测结果后很多实际项目还需要做车辆跟踪。常用的排序思路是先用检测器得到每一帧的搅拌车边界框然后用IoU匹配或者DeepSORT算法在帧间关联同一辆车。1168张静态图片本身不包含时序信息所以它只能用来训练检测器跟踪部分需要录制连续视频单独处理。我建议你把数据集里的图片按拍摄地点分组找连续帧形成短序列作为跟踪算法的验证材料。6.2 旋转目标检测的尝试搅拌车最“讨厌”的一点是它经常斜着停。在工地停车场里车辆很少规规矩矩地平齐停放可能是30度、45度、甚至60度斜停。普通水平框会同时框进旁边车辆的边缘导致特征污染。我尝试过把部分标注转成旋转框用mmrotate里的Rotated Faster R-CNN训练在斜停场景下的精度确实比水平框高不少。但旋转标注的成本比水平框高很多而且不是所有标注工具都支持所以我在这份VOC数据集里没有提供旋转标注如果你有这个需求可以使用RoLabelImg这类工具来扩展OBB标注。6.3 我对这份数据的使用建议最后说点实在的。1168张搅拌车数据集不是一份“万能钥匙”它更适合作为起点而不是终点。我建议你拿到数据后先用自己的评测指标跑一遍基线搞清楚哪些场景下模型表现差然后带着问题去补充数据。不要一次性增加几百张图而是每次增加50到100张针对性样本重新训练后看指标变化这样既能控制成本也能更清楚地知道哪些数据真正有效。我自己做工程车辆数据集的经验是标注质量永远是第一位的哪怕因此牺牲一些数据量也值得。与其追求“大而全”然后让模型学坏不如把每一张图标到无懈可击。后续我还会继续扩充这个系列陆续加入泵车、吊车、推土机等车型让整个工程车辆检测的数据生态更加完整。如果你用这套数据训练出了不错的模型也可以把你遇到的新问题反馈给我数据集的版本迭代就是这样一点点磨出来的。本文还有配套的精品资源点击获取
返回列表