
简介这份卡车倾倒建筑垃圾检测数据集面向计算机视觉与深度学习方向的开发者、算法工程师及环保智能监控研究者用于训练和评估目标检测模型识别图像或视频流中卡车倾倒垃圾的行为可服务于城市监控、建筑工地管理与环保监测等场景。资源包共1023个文件以569张jpg、106张png、39张jpeg图像为主体覆盖不同角度、光照与倾倒阶段另含309个xml标注文件提供边界框坐标与类别标签压缩包约115.49MB便于直接投入YOLOv7等模型的训练与验证。据描述模型训练后mAP可达0.85说明数据标注质量与场景覆盖度较好能支撑较高精度的检测效果。目前已有240人学习下载适合希望快速搭建非法倾倒行为识别实验、验证检测算法性能或扩充自有数据集的读者参考使用。1. 卡车倾倒建筑垃圾检测数据集从“看见”到“判定”的落地拆解工地出入口的监控画面里一辆渣土车停了三秒车厢缓缓抬起几块混凝土块滑落——这个动作在肉眼看来再普通不过但如果要把它变成一条可追溯的告警记录靠人盯着屏幕是不现实的。卡车倾倒建筑垃圾检测数据集要解决的正是把“倾倒”这个连续动作从监控视频里自动识别出来的问题。它面向的是工地扬尘监管、渣土车违规倾倒取证、城市管理非现场执法这类场景核心诉求不是识别卡车本身而是判断“这辆车正在倒东西”。适合谁用做智慧工地视觉算法的工程师、需要快速验证违规倾倒检测可行性的产品团队以及手里有监控视频但不知道怎么标注成训练集的开发者。这一章先把问题边界划清楚后面再讲怎么从零构建一套能跑起来的数据集和检测流程。2. 拆解“倾倒”动作数据集要标什么、为什么这样标2.1 从“卡车”到“倾倒”检测目标的三层定义很多人第一次拿到这个任务会下意识把它当成普通的车辆检测来做标一个“truck”就完事。但真正落地时会发现模型能框出卡车却完全不知道这辆车在干什么。倾倒建筑垃圾的判定至少需要三层信息第一层是卡车本体第二层是车厢举升状态或货斗倾斜角度第三层是抛落物与地面的交互区域。常见做法是把前两层合并成一个复合标签比如“dump_truck_lifting”第三层单独标“falling_debris”或“debris_pile”。这样标注的好处是模型在推理时能同时输出“哪辆车”和“它处于什么状态”后处理逻辑只需要判断同一辆车的举升标签是否持续超过阈值帧数就能触发告警。为什么不直接标“倾倒中”一个类别因为倾倒是一个过程单帧图像里很难区分“正在倒”和“倒完了停着”。把状态拆开标相当于把时序判断的负担从标注阶段转移到了后处理阶段标注一致性会高很多。我一般会建议标注规范里写清楚车厢举升角度超过15度且货斗内有可见物料才打“lifting”标签物料离开货斗进入空中或地面才打“falling”标签。这样标注员有明确的视觉锚点不会凭感觉标。2.2 数据采集监控视频抽帧的四个参数数据集的质量在采集阶段就决定了。建筑垃圾倾倒的场景光源复杂、遮挡多、卡车进出频繁直接拿公开数据集迁移效果通常很差。常见做法是从工地出入口的球机或枪机视频里抽帧抽帧参数需要根据卡车动作速度来定。下面是一段用 OpenCV 抽帧的脚本我一般会按这个模板改import cv2 import os # 输入视频路径和输出目录 video_path site_gate.mp4 out_dir frames os.makedirs(out_dir, exist_okTrue) cap cv2.VideoCapture(video_path) fps cap.get(cv2.CAP_PROP_FPS) # 原始帧率 interval int(fps * 0.5) # 每0.5秒抽一帧倾倒动作通常持续2-5秒 frame_id 0 saved 0 while True: ret, frame cap.read() if not ret: break if frame_id % interval 0: # 可选裁剪ROI只保留出入口区域减少背景干扰 h, w frame.shape[:2] roi frame[int(h*0.3):int(h*0.9), int(w*0.2):int(w*0.8)] cv2.imwrite(f{out_dir}/frame_{saved:06d}.jpg, roi) saved 1 frame_id 1 cap.release() print(f抽帧完成共保存 {saved} 张)这段脚本的关键参数是interval。倾倒动作从车厢开始举升到物料落地通常持续2到5秒如果按每秒25帧算整个过程有50到125帧。每0.5秒抽一帧能拿到4到10帧覆盖完整动作既不会漏掉关键状态也不会让标注量爆炸。ROI裁剪那一步不是必须的但如果监控画面里天空和远处建筑占比大裁掉上下边缘能显著降低误检。抽帧之后建议按“车辆进入-举升-倾倒-驶离”把同一辆车的帧归到一个子文件夹标注时上下文更清晰。2.3 标注规范边界框、属性与难例处理标注工具用 LabelImg 或 CVAT 都可以导出 YOLO 格式或 COCO 格式看后续训练框架。类别设计上我一般会设四个类truck卡车整体、lifting车厢举升状态、falling抛落物、pile地面垃圾堆。truck框住整车lifting框住举升的车厢部分falling框住空中的物料pile框住地面已有的垃圾堆。这样设计的好处是即使某帧没有抛落物lifting标签也能提供状态信息。难例处理是标注阶段最耗时的部分。夜间红外画面里卡车和背景对比度低边界模糊标注员容易把车厢和货物混在一起。我的经验是夜间帧单独放一个文件夹标注时允许truck框稍微宽松一点但lifting框必须紧贴车厢举升后的轮廓。另外如果画面里有多辆车同时出现每辆车都要独立标注不能只标正在倒的那辆否则模型会学到“只有一辆车时才倒”的错误关联。标注完成后至少抽10%的帧做交叉复核重点看lifting和falling的边界是否一致。3. 用 YOLOv8 跑通训练从标注文件到可推理模型3.1 数据集划分与 YOLO 格式转换标注导出后通常是 COCO JSON 或 LabelImg 的 XML。YOLOv8 需要的是每张图对应一个.txt文件每行格式为class_id x_center y_center width height坐标归一化到0到1。下面是一个把 COCO 格式转成 YOLO 格式的脚本我处理建筑垃圾数据集时常用import json import os from PIL import Image coco_file annotations.json img_dir images out_dir labels os.makedirs(out_dir, exist_okTrue) # 类别映射根据你的标注类别顺序修改 cat_map {truck: 0, lifting: 1, falling: 2, pile: 3} with open(coco_file) as f: data json.load(f) # 建立 image_id 到文件名的映射 img_info {img[id]: img for img in data[images]} for ann in data[annotations]: img img_info[ann[image_id]] img_path os.path.join(img_dir, img[file_name]) w, h img[width], img[height] # COCO bbox 格式: [x_min, y_min, width, height] x, y, bw, bh ann[bbox] x_center (x bw / 2) / w y_center (y bh / 2) / h nw bw / w nh bh / h cat_name [k for k, v in cat_map.items() if v ann[category_id]][0] line f{cat_map[cat_name]} {x_center:.6f} {y_center:.6f} {nw:.6f} {nh:.6f}\n txt_path os.path.join(out_dir, img[file_name].replace(.jpg, .txt)) with open(txt_path, a) as f: f.write(line)转换时最容易翻车的地方是类别 ID 对不上。COCO 的category_id通常从1开始而 YOLO 要求从0开始连续。上面脚本里用cat_map手动映射就是为了避免这个坑。另外如果一张图里某个类别没有实例对应的.txt文件可以是空的但文件必须存在否则训练时 YOLOv8 会报找不到标签。划分训练集和验证集时按时间顺序切分比随机切分更合理用前70%的帧做训练后30%做验证这样验证集里的卡车外观和光照变化更接近真实部署场景。3.2 训练参数batch size、imgsz 与学习率的实操取值YOLOv8 的训练命令很简洁但参数取值直接影响收敛。我一般用下面这套配置起步yolo detect train \ datadataset.yaml \ modelyolov8s.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ lrf0.01 \ patience20 \ device0 \ projectruns/dump_truckdataset.yaml里写清楚train、val路径和names列表。imgsz640是默认值但如果监控画面里卡车占比较小可以提到imgsz960代价是显存占用增加。batch16在单张 8G 显存的卡上比较稳如果爆显存就降到8。lr00.01是初始学习率建筑垃圾数据集通常几千张图这个值能较快收敛如果 loss 震荡厉害降到0.005。patience20表示验证集指标20轮不提升就早停避免过拟合。modelyolov8s.pt是轻量版如果追求更高精度可以换yolov8m.pt但推理速度会下降。训练过程中重点看mAP50-95和precision、recall的曲线如果 recall 明显低于 precision说明漏检多可能是lifting类样本太少需要补标。3.3 推理与后处理怎么从单帧结果判断“正在倾倒”模型训练完推理输出的是每帧的检测框。要判断“正在倾倒”需要把连续帧的结果串起来。下面是一个简单的后处理逻辑import cv2 from ultralytics import YOLO model YOLO(runs/dump_truck/weights/best.pt) cap cv2.VideoCapture(test_clip.mp4) lifting_counter 0 alert_frames 0 while True: ret, frame cap.read() if not ret: break results model(frame, conf0.4, iou0.5)[0] has_lifting False has_falling False for box in results.boxes: cls_id int(box.cls[0]) if cls_id 1: # lifting has_lifting True if cls_id 2: # falling has_falling True if has_lifting: lifting_counter 1 else: lifting_counter 0 # 连续5帧检测到举升且出现过抛落物触发告警 if lifting_counter 5 and has_falling: alert_frames 1 print(f第 {alert_frames} 次倾倒告警) lifting_counter 0 # 重置避免重复告警conf0.4是置信度阈值建筑垃圾数据集里falling类目标小、运动模糊阈值设太高会漏检设太低误报多0.4 是实测比较平衡的值。iou0.5用于 NMS如果同一辆车被重复框出可以降到0.4。连续5帧的判断是为了过滤掉单帧误检按25fps算5帧只有0.2秒不会漏掉真实倾倒。如果部署在边缘设备上可以把lifting_counter的阈值提到8到10帧进一步降低误报。4. 避坑与排查标注、训练、部署里最容易翻车的五件事4.1 现象模型把“停着的举升车”也判成倾倒原因训练集里缺少“举升但未倾倒”的负样本。很多标注员看到车厢举起来就标lifting但实际场景里卡车可能举着车厢等红灯或排队并没有倒东西。模型学到的是“举升倾倒”而不是“举升抛落倾倒”。解决在标注规范里明确只有同时出现lifting和falling的帧才作为正样本单独lifting的帧作为难负样本加入训练集。训练时可以把falling类的损失权重调高或者在后处理里要求falling必须出现至少1帧才触发告警。4.2 现象验证集 mAP 很高但实际视频里漏检严重原因训练集和验证集按随机切分同一辆车的不同帧被分到了两边导致验证集里出现的卡车外观和训练集几乎一样模型过拟合到了特定车辆。建筑垃圾场景里不同工地的卡车颜色、车型差异很大随机切分会让指标虚高。解决按视频片段或按天切分确保验证集里的卡车和训练集不重叠。如果数据量允许留出整个工地的视频做测试集这样得到的指标更接近真实部署效果。4.3 现象夜间红外画面里falling类几乎检不出来原因红外画面里抛落物的热特征和地面背景接近且运动模糊严重标注时边界框本身就画不准。模型在低对比度目标上召回率天然低。解决夜间数据单独训练一个模型或者用图像增强把红外帧的对比度拉高再送入模型。标注时对falling框适当放宽允许包含少量背景让模型有更多上下文。如果夜间数据太少可以考虑用白天的falling样本做迁移学习但需要微调最后几层。4.4 现象训练 loss 不下降或者下降后突然反弹原因学习率设太大或者batch太小导致梯度噪声大。建筑垃圾数据集里正负样本不均衡pile类可能占了70%以上模型容易偏向多数类。解决先用lr00.001跑10个epoch看loss趋势如果下降太慢再提到0.01。对类别不均衡可以在dataset.yaml里加cls_weights或者用 YOLOv8 的fraction参数控制每类采样比例。另外检查标注文件里有没有坐标超出0到1范围的异常值这种脏数据会让loss直接爆炸。4.5 现象推理时同一辆车被重复告警原因后处理里lifting_counter重置逻辑不严谨。如果卡车举升动作持续很久每5帧就触发一次告警导致同一次倾倒产生多条记录。解决引入“告警冷却”机制一次告警后至少等待30帧再允许下一次告警。或者用falling类的首次出现作为触发点而不是持续检测。更稳妥的做法是记录lifting的起始帧和结束帧只有完整的一次举升-抛落-降下过程才算一次事件。5. 进阶技巧用时序模型补上单帧检测的短板单帧检测加后处理能解决大部分场景但遇到“车厢举升但物料被遮挡”或者“多辆车同时举升”时规则逻辑会变得很脆弱。我后来习惯在检测框基础上加一个轻量时序分类器把连续16帧的检测结果类别、置信度、框位置拼成一个序列送进一个小的 LSTM 或 1D-CNN输出“倾倒/非倾倒”二分类。这样模型能学到动作的时序模式而不是依赖人工阈值。具体做法是先用 YOLOv8 对视频抽帧推理把每帧的检测结果存成 JSON然后按滑动窗口切分序列。窗口大小16帧步长4帧正样本窗口要求中间至少有一帧falling负样本窗口可以包含lifting但没有falling。时序模型用 PyTorch 写两层 LSTM隐藏层64训练20个epoch就够。部署时YOLO 和 LSTM 可以串行跑YOLO 负责每帧检测LSTM 每16帧输出一次判定延迟增加不到100毫秒。验证时序模型是否有效不能只看准确率要看事件级的召回率和误报率。我一般会统计测试视频里真实倾倒次数然后看模型告警次数和真实次数的比值。如果误报集中在“举升等待”场景说明负样本还不够需要补标更多“举升但未倒”的片段。另外时序模型的输入特征里框的坐标变化比类别置信度更有信息量——车厢举升时lifting框的宽高比会明显变化这个特征比单纯看类别更稳。这套方案我前后调了三个月最大的教训是不要一上来就上时序模型。先把单帧检测的标注质量和后处理逻辑打磨好确认单帧模型在验证集上的falling召回率超过85%再考虑加时序。否则时序模型只是在拟合标注噪声反而更难排查。希望帮到你。本文还有配套的精品资源点击获取