卡车倾倒建筑垃圾检测数据集:从视频流到行为识别的落地拆解
2026/9/24 19:31:44 网站建设 项目流程

简介:这是一份面向计算机视觉与深度学习方向的目标检测数据集,聚焦卡车倾倒建筑垃圾这一特定行为识别任务,适合训练和评估YOLOv7等实时检测模型,可服务于城市监控、建筑工地管理与环保监测等场景。压缩包共1023个文件,约115.49MB,其中569张jpg与39张jpeg为原始图像,106张png补充样本,309个xml文件提供边界框与类别标注,覆盖不同角度、光照与倾倒阶段,便于直接投入训练与验证。据描述,模型在该数据集上训练后mAP可达0.85,说明标注质量与场景多样性具备较高实用价值。目前已有240人学习下载。读者可据此完成从图像预处理、标注解析到模型训练与评估的完整流程,并借助验证集与测试集监控过拟合,为非法倾倒行为的自动化检测提供可复用的数据基础。

1. 卡车倾倒建筑垃圾检测数据集:从“看见”到“举证”的落地拆解

工地出入口、消纳场通道、城乡结合部空地,渣土车停三秒、斗一抬、哗啦一倒,人还没跑到跟前,车已经挂挡走了。环保督查、城管执法、智慧工地项目里,这类“卡车倾倒建筑垃圾”行为的取证一直是个老大难:靠人盯监控,一个屏幕几十路,漏检是常态;靠地磅和审批数据,只能管住正规消纳场,管不住半路乱倒。卡车倾倒建筑垃圾检测数据集要解决的,就是让算法从视频流里自动认出“这辆车正在倒建筑垃圾”这个动作,而不是只认出“这里有一辆车”。它适合三类人:做智慧城管/环保 AI 落地的算法工程师、需要给现有监控加行为识别能力的集成商、以及想用开源数据先跑通 demo 再决定要不要自采数据的团队。这一章先把“检测什么、为什么难、数据长什么样”讲清楚,后面几章再动手。

2. 拆解“倾倒”这个动作:目标框、时序与场景定义

2.1 为什么普通车辆检测模型在这里会翻车

常规 YOLO 检测“卡车”,输出的是一个把整辆车框住的矩形。但“倾倒建筑垃圾”的关键信息不在车本身,而在车厢举升状态 + 车尾抛洒物 + 车辆静止/低速这三者的组合。一辆正常行驶的渣土车和一辆正在倾倒的渣土车,在单帧图像里可能只差一个举升角。如果数据集只标“卡车”,模型学到的就是“有卡车=有事件”,误报率会高到没法用。

所以这个数据集的核心标注对象通常分两层:一层是车辆目标框(卡车/渣土车),另一层是行为状态标签(是否处于倾倒姿态)。有些方案还会加第三层:抛洒物区域(车尾扬尘、落料堆)。这三层决定了你后面是走“单帧分类”还是“时序动作识别”。

我一般会先明确一件事:你的业务是要实时告警还是事后取证。实时告警对延迟敏感,倾向单帧+轻量模型;事后取证可以拉 3~5 秒片段做时序判断,准确率更高但算力翻倍。这个选择直接决定数据集怎么切、标签怎么打。

2.2 数据集应该包含哪些场景维度

一个能落地的卡车倾倒建筑垃圾检测数据集,不能只拍晴天正午的干净画面。按我的经验,至少要覆盖下面这些维度,否则模型上线后遇到真实监控就“玄学”失灵:

维度建议覆盖原因
光照白天、黄昏、夜间补光、逆光夜间车灯和扬尘会让车尾特征糊掉
天气晴、阴、雨、扬尘扬尘本身既是线索也是干扰
拍摄角度正对车尾、侧后方 45°、高位俯视举升角在不同视角下差异大
车辆类型后八轮、前四后八、小型自卸车厢结构不同,举升特征不同
背景工地口、空地、路边、消纳场背景决定误报来源
行为行驶、静止未举升、举升中、倾倒中、倾倒后负样本和过渡态必须要有

这里有个血泪经验:“举升中”和“倾倒中”一定要分开标。很多团队图省事只标“倾倒”,结果模型把刚抬斗还没倒的也算进去,告警提前几秒,执法时被质疑“人家还没倒”。过渡态样本是这类行为数据集的灵魂。

2.3 标注规范:框怎么画、标签怎么定

标注规范不统一,后面训练全是坑。我一般会写一份内部规范,核心几条:

  • 车辆框:框住车身可见部分,车厢举升时框要包含举升后的车厢,不要只框底盘。
  • 抛洒物:只标从车尾落下的料堆或明显扬尘区域,路面已有的旧垃圾不标。
  • 状态标签:按帧打,dumping表示正在落料,lifting表示斗已抬但未见落料,normal表示正常行驶或静止未举升。
  • 遮挡处理:车厢被遮挡超过 50% 的帧直接丢弃,不硬标。

标注工具用 LabelImg、CVAT 或 Label Studio 都行,关键是导出格式统一。我倾向 COCO 格式,因为后面转 YOLO 或做时序切片都方便。

3. 从原始视频到可训练数据集:切片、清洗与格式转换

3.1 视频抽帧与片段切分的最小脚本

拿到原始监控视频后,第一步不是急着标,而是抽帧和切片。全帧标注太浪费,行为识别只需要关键片段。下面这个脚本按“每 N 帧抽一帧 + 按时间切 3 秒片段”处理:

import cv2 import os def extract_clips(video_path, out_dir, fps_sample=5, clip_sec=3): """ 从视频中按间隔抽帧,并按 clip_sec 秒切分片段 fps_sample: 每秒抽几帧,监控一般 25fps,抽 5 帧足够 clip_sec: 每个片段时长,倾倒动作通常 2-5 秒 """ cap = cv2.VideoCapture(video_path) fps = cap.get(cv2.CAP_PROP_FPS) if fps <= 0: fps = 25 # 兜底,部分监控流读不到 fps step = max(1, int(fps / fps_sample)) frame_idx = 0 clip_idx = 0 buffer = [] frames_per_clip = int(fps * clip_sec) while True: ret, frame = cap.read() if not ret: break if frame_idx % step == 0: buffer.append(frame) if len(buffer) >= frames_per_clip // step: clip_dir = os.path.join(out_dir, f"clip_{clip_idx:05d}") os.makedirs(clip_dir, exist_ok=True) for i, f in enumerate(buffer): cv2.imwrite(os.path.join(clip_dir, f"{i:03d}.jpg"), f) buffer = [] clip_idx += 1 frame_idx += 1 cap.release() print(f"done, {clip_idx} clips saved") extract_clips("site_gate.mp4", "./clips", fps_sample=5, clip_sec=3)

逻辑说明:fps_sample控制抽帧密度,监控场景 5 帧/秒足够捕捉举升过程,太高会让标注量爆炸。clip_sec是片段长度,倾倒动作从抬斗到落完一般 2~5 秒,取 3 秒是折中。step是抽帧间隔,用fps/fps_sample算出来,避免不同摄像头帧率不一致导致切片错位。

参数怎么改:如果目标是实时告警,fps_sample可以降到 2~3,减少数据量;如果要做精细时序,提到 10。clip_sec遇到慢速倾倒的大车可以放到 5 秒。

3.2 清洗:三类必须删掉的脏数据

抽完帧别直接标,先过一遍清洗。我踩过的坑里,下面三类数据不删,后面训练 loss 会莫名其妙震荡:

  1. 纯背景帧:片段里车已经开走,只剩空场地。这类帧如果混进正样本,模型会学“空场地=倾倒”。
  2. 重复帧:监控卡顿导致连续多帧完全一样,标注时容易漏标或重复标。
  3. 极端模糊帧:夜间噪点、雨滴糊住镜头,人眼都看不清举升角,标了也是噪声。

清洗可以用简单的帧差法筛掉静止片段,再用拉普拉斯方差筛模糊帧:

import cv2 import numpy as np def is_blurry(img_path, threshold=80): """拉普拉斯方差低于阈值判为模糊,阈值按分辨率调""" img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE) if img is None: return True return cv2.Laplacian(img, cv2.CV_64F).var() < threshold def frame_diff_ratio(f1, f2): """两帧差异比例,用于筛重复帧""" g1 = cv2.cvtColor(f1, cv2.COLOR_BGR2GRAY) g2 = cv2.cvtColor(f2, cv2.COLOR_BGR2GRAY) diff = cv2.absdiff(g1, g2) return np.count_nonzero(diff > 20) / diff.size

threshold这个参数没有万能值,1080P 监控我一般从 80 起调,模糊就往上加。frame_diff_ratio低于 0.01 基本可判为重复帧。清洗这一步偷懒,后面标注和训练要加倍还回来。

3.3 转成 YOLO 格式:转换脚本与四个边界坑

标注导出 COCO 后,训练常用 YOLO,需要转格式。转换本身不难,坑在边界:

import json import os def coco_to_yolo(coco_json, img_dir, out_label_dir, class_map): """ class_map: {"truck":0, "dumping":1, "lifting":2} 注意:行为标签如果按帧打,需要单独处理,这里只转目标框 """ with open(coco_json, "r", encoding="utf-8") as f: data = json.load(f) img_info = {img["id"]: img for img in data["images"]} os.makedirs(out_label_dir, exist_ok=True) for ann in data["annotations"]: img = img_info[ann["image_id"]] w, h = img["width"], img["height"] x, y, bw, bh = ann["bbox"] # COCO 是左上角+宽高,YOLO 是中心点+宽高,且要归一化 cx = (x + bw / 2) / w cy = (y + bh / 2) / h nw = bw / w nh = bh / h # 边界裁剪,防止浮点误差越界 cx = min(max(cx, 0), 1) cy = min(max(cy, 0), 1) nw = min(max(nw, 0), 1) nh = min(max(nh, 0), 1) cls = class_map[ann["category_id"]] label_path = os.path.join(out_label_dir, img["file_name"].replace(".jpg", ".txt")) with open(label_path, "a") as lf: lf.write(f"{cls} {cx:.6f} {cy:.6f} {nw:.6f} {nh:.6f}\n")

四个边界坑:一是bbox 越界,标注时手抖框出图像外,不裁剪训练会报错;二是宽高为 0,极小目标归一化后接近 0,YOLO 会忽略,需要设最小阈值;三是类别 id 不连续,COCO 的 category_id 可能从 1 开始,YOLO 要求从 0 连续,必须用class_map映射;四是文件名对不上,图片和标签必须同名同目录结构,否则训练时找不到标签,loss 直接是 nan。

4. 训练与验证:让模型真的认出“正在倒”

4.1 单帧检测 + 时序投票的混合方案

纯单帧检测对“举升中”和“倾倒中”区分弱,纯时序模型又重。我常用的是单帧检测出车辆和状态,再用滑动窗口投票:连续 5 帧里如果有 3 帧以上判为dumping,才触发告警。这样既压误报,又不用上 3D 卷积。

训练单帧模型时,把dumpingliftingnormal当成三个类别和车辆框一起训,或者分两个头:一个头出车辆框,一个头出状态分类。数据量小于 5000 张时,我倾向用 YOLOv8n 这种轻量模型先跑通,别一上来就上大模型。

# 常见做法是用 ultralytics 训练,配置文件写好路径和类别 yolo detect train data=dataset.yaml model=yolov8n.pt epochs=100 imgsz=640 batch=16

imgsz设 640 是速度和精度的折中,监控画面里车尾细节小,可以提到 960,但显存和推理时间会涨。epochs100 起步,看验证集 mAP 曲线,早停 patience 设 20。

4.2 验证指标:别只看 mAP

行为检测的验证不能只看 mAP。mAP 高不代表告警准。我一般会额外看三个指标:

  • 事件级召回:一段真实倾倒视频,模型是否至少触发一次告警。这个比帧级召回更贴近业务。
  • 误报/小时:每路摄像头每小时误报几次。超过 2 次,值班人员就会关掉告警。
  • 提前/延迟帧数:告警发生在倾倒开始后第几帧。太晚,车都走了;太早,可能只是抬斗。

验证集要按摄像头划分,不能按帧随机分。同一摄像头相邻帧高度相似,随机分会导致验证集“作弊”,指标虚高。按摄像头分,才能看出模型换场景后的真实泛化。

4.3 数据增强:哪些能用,哪些会帮倒忙

增强不是越多越好。对卡车倾倒场景,马赛克增强要慎用,它会把两辆车的车厢拼在一起,举升角变得不真实。我一般开这几类:

  • 亮度/对比度扰动:模拟昼夜和逆光。
  • 随机裁剪:模拟不同安装角度。
  • 轻微旋转 ±5°:监控支架会有小倾斜。
  • 扬尘模拟:叠加半透明噪声层,增强抗扬尘能力。

翻转要小心:水平翻转后,某些车型的举升方向反了,如果业务里方向重要,就别开。

5. 避坑与排查:五条上线前必须过的坎

5.1 现象:训练 loss 正常,但验证集 mAP 一直 0.2 上不去

原因:大概率是标签格式或路径错了。YOLO 找不到标签时不会报错,只会把背景当负样本学。解决:先跑一遍yolo detect val,看labels数量是否为 0;再抽查几个.txt,确认类别 id 从 0 开始、坐标归一化在 0~1。

5.2 现象:白天准,夜间全是误报

原因:夜间车灯高光让车尾特征过曝,模型把“亮斑”当成了倾倒线索。解决:训练集里补夜间负样本(正常行驶的夜间车),并在预处理里加 CLAHE 或 gamma 校正。别指望模型自己学会,它没见过就是不会。

5.3 现象:模型把“举升中”误判成“倾倒中”

原因:过渡态样本太少,或者标注时把两者混为一类。解决:单独统计lifting帧数,如果不到dumping的 30%,就要补采或重标。也可以在时序投票里加状态机:先liftingdumping才算完整事件。

5.4 现象:同一段视频,换台机器推理结果不一样

原因:预处理不一致。训练时用了归一化、resize 方式,推理时没对齐。解决:把预处理写成一个函数,训练和推理共用,别一边用 OpenCV 一边用 PIL,插值方式不同结果就会飘。

5.5 现象:告警太频繁,值班员直接关掉

原因:阈值定太松,或者没做事件去重。解决:加滑动窗口投票 + 冷却时间,同一辆车 30 秒内只报一次。阈值用验证集上的误报/小时曲线来定,别拍脑袋。

6. 进阶技巧:用半自动标注把数据量翻三倍

数据量是这类行为检测的天花板。纯手工标 1 万帧,一个人要标一周。我的习惯是先用小样本训一版粗模型,再用它预标注,人工只做修正。具体做法:先标 500~1000 帧,训一个 YOLOv8n,置信度阈值调低到 0.25,让它把剩余视频全跑一遍,输出预标注框,人工在 CVAT 里只改错的、补漏的。实测能把标注速度提 2~3 倍。

预标注有个注意点:别用预标注结果直接训练,一定要人工过一遍。模型自己的错误会被当成真值,越训越偏,这就是典型的“模型自嗨”。我一般要求预标注修正率低于 10% 才允许进入下一轮。

另一个技巧是难例挖掘:把验证集里误报和漏报的片段单独存一个文件夹,每轮训练后把新难例加进去,迭代 3~4 轮,事件级召回通常能从 70% 提到 85% 以上。这个循环比换更大模型划算得多。

最后说个我自己的教训:早期我总想一步到位搞个“全能模型”,结果数据没标够、场景没覆盖,上线后天天救火。后来改成“先跑通一个摄像头、一个场景,再横向复制”,反而稳。卡车倾倒建筑垃圾检测数据集这件事,数据质量比模型结构重要十倍,标注规范比标注数量重要。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询