资讯动态

无人机视角河道违建检测数据集:VOC+YOLO双格式构建全复盘

发布时间:2026/10/21 15:08:42 来源:尧图企业网站定制
接手这个河道巡检项目时我第一件事不是打开训练脚本而是先把已有航拍图片从头翻了一遍。翻完之后说实话有点泄气——河道两边的违规建筑和普通农房、集装箱、临时工棚混在一起从无人机视角往下看大多数目标都小得可怜有的整栋建筑只占画面宽度的3%左右人眼不放大都容易漏。这也让我意识到项目能不能做成关键不在模型训练那一步而在于有没有一份真正贴合“无人机视角河道场景”的违规建筑数据集。这次要聊的就是一份“无人机视角智慧河道巡检河道违建检测数据集”VOCYOLO双格式、1034张图片、1个类别从数据整理到格式转换、从训练参数到踩坑实录完整复盘一遍。这份数据集解决的最核心问题很直接给目标检测模型提供“什么算违建、违建长什么样”的样本。它适合三类人参考一是做水利信息化或者智慧城市巡检的算法工程师二是刚入门目标检测、想找一份结构清晰的双格式数据集练手的学生三是负责无人机巡检业务落地、需要评估数据价值的项目管理人员。接下来我按实际做项目的顺序来拆解。1. 这份数据集解决的是什么问题1.1 河道巡检的痛点不在“航拍”而在“看完这些照片”很多没真正跑过河道巡检项目的人会以为难点在无人机飞行本身。其实飞起来太简单了设定航线、一键起飞一个上午能拍完几十公里河道。真正的瓶颈是数据回来之后怎么办。一段10分钟的视频抽帧出来可能有一千多张图片一个中等规模的河段巡检任务往往积累上万张照片。让巡查人员一张张看眼睛很快就花了而且人眼在连续看几百张高度相似的河面图片之后对异常目标的敏感度会急剧下降。我印象很深的是项目初期做人工筛查一个经验丰富的巡查员一天最多认真看完两千张图再往后基本就是在“完成任务式”地翻页。河道违规建筑在无人机视角下有很强的特殊性。它不像道路上违章停车那样轮廓清晰、形态统一而是各种形态都有河滩上的彩钢瓦棚子、河道管理范围内的活动板房、岸边堆料场边的临时砖混房甚至还有用防水布搭的半永久棚。这些建筑从正上方看轮廓不规则颜色和泥土、植被、硬化地面混杂在一起加上水面的反光、树冠的遮挡背景复杂度比一般的地面目标检测场景高不少。这种情况下目标检测模型的价值就体现出来了。模型可以不知疲倦地处理一万张图把疑似目标框出来把“人眼盯图”变成“人审模型结果”巡检效率能提升一个量级。但模型要用起来前提是有一份和真实业务场景同分布的数据集来训练和验证。如果拿通用目标检测数据集比如日常物体检测那种公开数据直接训练效果会非常差因为无人机俯拍视角下的建筑形态、尺度、背景和普通地面视角完全是两个世界。这份数据集的价值正是补齐了“无人机视角河道场景违规建筑”这一特定组合的样本缺口。1.2 数据集规格与适用范围先看整体规格我用表格列一下核心信息项目内容图片数量1034张目标类别1类违规建筑/河道违建标注格式VOC XML YOLO TXT 双格式适用算法Faster R-CNN、SSD、YOLO系列、MMDetection等采集视角无人机俯拍/倾斜俯拍场景覆盖城市河道、乡村河段、河滩、岸边管理区单类别检测看起来比多类别简单但实际做下来会发现类别少反而让标注标准更关键。因为就一个类别漏标一个目标、多标一个误框对模型的影响都是直接的。前面说了这个数据集包含1034张图片属于中小规模数据集。训练一个基于预训练权重的YOLO模型完全够用但要达到很高的泛化能力后续还得结合数据增强和迭代扩充。适用场景上这一类模型可以直接用于无人机实时巡检的违规建筑初筛也可以部署到后端服务器做批量排查。如果你做的是“岸线占用检测”“河道违章建筑识别”这类业务这个数据集可以直接当训练集跑一轮如果你做的是更细的违建分类比如区分违建类型这个数据集可以作为负样本或基础检测的前置模型数据。2. 数据集的构建流程从原始航拍到可用训练样本2.1 数据采集与初筛视频抽帧比单张拍摄更高效无人机巡检数据的采集我强烈建议用视频录制后抽帧的方式。实际飞巡检航线时一个架次可能覆盖好几公里河道如果用连拍照片的方式存储压力大而且很容易把大量相似画面存下来浪费标注时间。视频抽帧的好处是可以按需控制抽帧密度——直飞段每隔3到5秒抽一帧在疑似违建区域悬停或减速飞行时可以更密集地抽帧。一份5分钟的4K视频按每秒1帧抽能拿到300帧挑出其中画质合格、目标有代表性的50到80帧比直接拍几百张照片要高效得多。初筛阶段必须做三件事。第一是剔除模糊帧无人机飞行中抖动、转弯、快速变焦都会导致画面模糊这类图直接删掉否则标注时边界框都没法画准。第二是剔除大面积无目标帧如果一张图里只有水面和植被完全没有建筑类目标从训练角度看价值不大保留一部分负样本让模型学“什么是背景”是必要的但比例要控制整份数据集里纯背景图我一般控制在10%以内。第三是检查色彩一致性不同无人机、不同天气拍出来的图色调差异可能很大如果数据集里全是晴天正午拍的图到了阴天部署效果就会崩初筛时要有意识地保留不同光线条件的样本。2.2 标注目标怎么定义别小看“1个类别”标注之前有个问题必须先回答清楚什么算违规建筑这个不定义清楚一百张图之后标注标准就会飘。业务上说的河道违规建筑指未经批准在河道管理范围内修建的建筑物、构筑物。但落到图像上这个定义需要转化成视觉可判别的规则。我的标注规则是这么定的凡是出现在河道管理范围内的彩钢瓦棚、活动板房、砖混房屋、简易搭建物只要不是明显作为水利设施闸房、泵站或桥梁道路结构存在的都标为违规建筑。同时对于有争议的目标——比如一半被树冠遮挡的棚子、已经明显废弃坍塌的建筑物标注时宁可不标也不要标错。这个“宁缺毋滥”的原则在单类别数据集里尤其重要因为误标一个目标会把模型的置信度判断带偏。标注矩形框时也要讲究。无人机俯拍视角下很多建筑是倾斜的矩形框应该贴着建筑主体的外轮廓把完整的建筑实体框进去但不要为了把周围散落的杂物也包进去而扩大框。扩大框本身不痛不痒但会让模型学到“违建周边包含大量背景”的错误模式在推理时框就会偏大业务上就会把很多非目标区域圈进来。标注工具我用的是LabelImg小巧直接打开图片、画框、输类别名、保存XML一天标两三百张是正常速度。如果有熟悉X-AnyLabeling的也可以用支持交互式分割辅助标注效率会高一些但对电脑配置有点要求。标注完成后还需要至少找另一个人花半天时间把全部图过一遍重点检查两类问题漏标的目标、边界框严重偏离实际轮廓的目标。这种双重复核非常必要一个人连续标注久了标准会不知不觉偏移。2.3 数据增强策略1034张的样本如何扩大有效性1034张图在深度学习项目里属于“能跑通但不够富余”的规模。要让模型训得稳数据增强是必须做的。但增强不是越多越好要贴着业务场景来。几何增强方面我个人建议做水平翻转、随机旋转10度以内小角度就行旋转太大会把矩形框的语义搞乱、随机缩放。色彩增强方面HSV色域扰动是标配。因为无人机在不同光照下拍出来的色调差异很大模型如果能对色偏鲁棒实际部署时就不容易被傍晚的暖光、雾天的灰蒙影响。Mosaic增强把四张图拼成一张训练对改善小目标检测很有帮助这个在YOLO系列里已经是内置选项了可以默认开启。不过有两点要注意。第一验证集不要做任何增强用原始图片验证否则指标虚高部署时对不上真实效果。第二增强策略里不要加入“随机裁剪”这种容易把目标切坏的增强——无人机俯拍下的建筑经常贴着图边缘随机裁剪很容易把半个建筑留在图里标签坐标倒是会自动调整但语义上你等于给模型看了大量“半截建筑”反而增加误检。切分数据集时像这种同一条河道连续帧抽出来的图片要放到同一个集里不要让训练集和验证集出现场景重叠否则验证结果会显得比真实情况好很多。3. VOC和YOLO双格式的核心差异与转换落地3.1 两种格式到底差在哪数据集的工程价值很大程度上体现在格式上。VOC格式和YOLO格式是目前目标检测领域最常见的两种标注格式它们的底层表达方式差异很大了解这个差异才能正确写转换脚本。VOC格式本质是一个XML文件里面保存着图片尺寸、目标类别、边界框的绝对像素坐标。边界框用xmin、ymin、xmax、ymax四个值表示单位是像素。好处是直观、可读性强用ET库解析或者直接打开看都能理解坏处是文件体积大、解析速度慢在训练管线里不够高效。YOLO格式则是一个纯文本TXT文件每一行描述一个目标类别ID、中心点x坐标、中心点y坐标、宽度、高度。这里的坐标全部是归一化的范围是0到1即用绝对像素坐标除以图片宽高得到。这样做的好处是模型输入图片尺寸无论怎么变标注都不需要跟着改训练管线读取效率高。坏处是普通人直接看TXT文件很难理解里面数字的含义。人工标注阶段用VOC格式因为可读性最好、工具支持最多模型训练阶段用YOLO格式因为效率和框架兼容性最高。准备一份VOCYOLO双格式数据集就是让你从标注到训练之间不需要再回头做格式适配直接可以开训。3.2 格式转换脚本的完整实现转换脚本我用Python来写核心逻辑是解析XML里的目标框坐标、归一化后写入TXT。下面是完整实现这个脚本可以直接复用到你自己的数据集上import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, output_dir, class_names): 将单个VOC XML标注文件转换为YOLO TXT格式。 class_names: 类别名称列表顺序决定类别ID。 os.makedirs(output_dir, exist_okTrue) tree ET.parse(xml_path) root tree.getroot() img_name root.find(filename).text img_w int(root.find(size).find(width).text) img_h int(root.find(size).find(height).text) yolo_lines [] for obj in root.iter(object): name obj.find(name).text.strip() if name not in class_names: continue class_id class_names.index(name) box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) # 边界保护防止坐标越界或负值 xmin max(xmin, 0) ymin max(ymin, 0) xmax min(xmax, img_w) ymax min(ymax, img_h) x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h # 过滤异常宽高避免写入无效标注 if w 0 or h 0: continue yolo_lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) txt_name os.path.splitext(img_name)[0] .txt with open(os.path.join(output_dir, txt_name), w, encodingutf-8) as f: f.write(\n.join(yolo_lines))使用时只需要准备一个类别列表比如这份数据集里就是class_names [illegal_building]然后遍历所有XML文件调用函数即可。我在批量转换之后一定会做一步自动校验写一个脚本检查转换出来的TXT文件里是否有越界坐标、目标数是否和XML一致、是否有图片文件但缺TXT或反过来有TXT但缺图片。这一步骤花不了十分钟但能过滤掉大量低级错误。代码里有两个细节我特别说明一下。第一坐标边界保护不是多此一举个别标注工具画框时鼠标稍微拖出图片边缘几像素就会产生负值坐标不修正的话YOLO训练时会遇到坐标归一化后小于0的情况轻则警告重则训练报错。第二过滤宽高为0的框很重要有些XML里存在空目标框训练脚本读到这种标注会计算出NaN损失直。3.3 目录组织与训练前的三项检查拿到双格式数据集之后目录组织方式直接影响训练脚本能不能跑通。建议按下面的结构来组织dataset/ ├── JPEGImages/ # 原始图片 ├── Annotations/ # VOC XML标注 ├── ImageSets/ │ └── Main/ │ ├── train.txt │ ├── val.txt │ └── test.txt ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/JPEGImages和Annotations是VOC格式的标准布局images和labels是YOLO格式的标准布局。ImageSets/Main下的txt文件维护训练集、验证集、测试集的图片名列表。切分比例我建议按8:1:1或者8:2来图片数量少的话验证集和测试集的绝对数量一定要够用我一般保证验证集不少于100张太少的话评估指标波动会很大。训练前有三项检查必须做。第一项用脚本统计每个图片的标注数量如果大量图片只有0个目标说明负样本偏多模型会倾向于全图输出低置信度适当剔除一些纯背景图平衡一下。第二项统计所有目标框的宽度和高度分布用一个小脚本画出来看看小目标占比。无人机视角下违规建筑经常是宽高只占图片5%以内的小目标这种目标比例高的话后面训练就要考虑用更高分辨率输入。第三项人工抽20张转换后的YOLO格式图写个可视化脚本把归一化坐标还原到图上画框确认转换没有坐标偏移。这个可视化检查永远比直接看数字靠谱。4. 用这份数据集训练模型的关键参数与评估思路4.1 模型选型小模型不一定省心基于这份1034张、1个类别的数据集我实际测试过多个YOLO系列的模型。对于这个数据规模我一向的建议是优先尝试中小型模型YOLOv8n、YOLOv8s、YOLOv5s都是比较稳的起点。推理速度上这些模型在一块普通消费级显卡上都能跑几百FPS部署到边缘设备比如机载的Jetson系列或者轻量级算力盒子也能达到实时或准实时。模型越大在数据量不变的情况下越容易在小训练集上过拟合表现就是训练损失很好看、验证集mAP也不错但一换场景就垮。不过“小模型一定好”也是误区。如果实际部署设备算力比较强或者你对检测精度要求高YOLOv8m甚至YOLOv8l也可以试。在数据规模1000张出头的场景下我建议的做法是直接用预训练权重做迁移学习然后跑一组对比同样的训练配置下分别用n、s、m三个规格训一版用相同验证集对比mAP和推理延迟。这个操作成本不高但能帮你选出一个和你的算力、业务要求最匹配的配置避免拍脑袋选型。4.2 训练参数怎么定imgsz 640还是1280训练参数里输入分辨率是第一个要决策的。默认的640x640对很多场景够用但前面统计过这份数据集里小目标占比不低640输入下一个小目标只有20x20像素左右特征很弱。我的实践经验是如果显存够8G以上训练和推理都直接用1280x1280输入检测小目标的能力提升非常明显。如果显存只有6G那就用640x640把batch size调小一点配合Mosaic增强效果也能接受千万不要在6G显存上硬开1280不然batch size只能设为1训练会慢到怀疑人生。有了预训练权重后我用YOLOv8的命令行训练方式跑配置文件里主要参数这样定yolo detect train \ datadata.yaml \ modelyolov8s.pt \ imgsz1280 \ epochs120 \ batch8 \ lr00.01 \ momentum0.937 \ weight_decay0.0005epochs设120算是保守但稳妥的起点。数据量小模型收敛快太少的epoch可能还没充分学完特征太多的epoch又容易过拟合。这个项目里我试过把epochs加到200mAP不再提升训练后期明显在拟合训练集细节了。batch大小根据显存调到能装得下为止8是个安全值。lr0用默认的0.01就行如果你用的是预训练权重初始学习率不宜太大0.01已经够激进再大很容易造成前期震荡。4.3 评估单类别模型时最容易忽视的指标很多朋友看到单类别数据集就觉得评估只看一个mAP够了。实际业务中比我更关注的是两个细分指标召回率和误检率。河道巡检场景里漏检一个违建意味着这个点没被复查到是实际管理上的漏洞而误检顶多是给审核人员多一个需要确认的框成本低得多。所以在训练目标上我会偏向把Recall拉高允许Precision稍微掉一点。训练完看混淆矩阵时我每次都会单独统计在“小目标”比如目标面积占图片面积小于3%这个子集上的召回率。这个指标在模型评估工具里不直接显示需要自己写脚本按标注面积过滤统计。如果小目标召回率低于大目标说明模型对远处、小尺寸建筑还是不敏感可以尝试更高分辨率、更多小目标增强样本或者把推理时的检测阈值调低一些。阈值调低会引入更多误检但在业务上可以用“人工复核”来兜底巡检场景里这个取舍是合理的。部署阶段我还会开一个“二次筛选”逻辑模型输出所有置信度高于0.15的框这个阈值远低于常规的0.25或0.5让这些框进入人工审核列表。实际效果是每1000张航拍图会产生30到60个待人工确认的框其中很多是误检但漏检率极低。相对于让一个人全量看图这个工作量已经降低了90%以上。5. 基于这份数据集的实战踩坑记录5.1 漏检的重灾区是“小目标”我在第一次把训练好的模型放到真实巡检数据上测试时发现一个让我很意外的现象那些相对完整的大棚子、大工棚几乎都能正确检测出来但违建中最常见的半简易建筑——河滩上那种10平米左右的小彩钢瓦棚、用铁皮和木头拼起来的临时小屋漏检率非常高。回看数据集的标注统计这类目标的框在640分辨率下只有40x40像素左右特征信息很少。解决这个问题的组合拳有三步。第一步把训练输入分辨率从640提到1280小目标对应的像素翻倍模型能学到更多纹理细节这一步效果立竿见影小目标召回率提升了约10个百分点。第二步在数据增强里增加“小块随机抠图放大”的操作这是对小目标增强比较有效的手段之一。第三步如果仍然不够就把这类小目标单独多收集一些样本补进数据集采样时特意找那些在画面里占比很小的违建图让模型对“远处小建筑”的样本量不再稀缺。5.2 误检来源往往是背景太“像”另一个常见的坑是误检。我在某次巡检数据上跑模型时发现一个很稳定的误检源河道边的排水泵站和闸房。这些合法水利设施在外观上和违规建筑太像了都是方正的小体量砖混或钢结构房屋从无人机正上方看几乎没有区别。模型把它们框出来是合理的但业务上就是误报。这类背景误检单纯加数据不一定能完全解决因为合法建筑和违规建筑的视觉差异可能真的就体现在位置管理属性上而不是图像特征上。我的处理办法是在模型后接一个位置过滤规则提前录入河道管理范围内的合法设施点位模型输出的目标如果和已知合法设施的重叠度超过一个阈值自动丢弃。说到底目标检测只能做到“视觉相似性判断”业务合规性判断需要叠加地理信息。这也是在实际项目中很重要的认知。5.3 跨区域泛化这份数据集的边界在哪里最后想聊一个很多人不会提前想到的坑。用这份数据集训练出来的模型在采集数据的同一条河段上效果不错但直接拿去给另一条不同地貌特征的河段检测效果会打折扣。原因是不同区域的河道差异很大北方一些河段两岸是硬化的堤防建筑和堤岸边界分明南方一些河段植被茂密违建可能藏在竹林后面只露出一个屋顶尖还有一些采砂堆场区域的临时建筑密集而且互相遮挡检测难度又不一样。所以这份1034张的数据集更适合作为“基线数据集”而不是“终点数据集”。项目落地时需要在新场景里补充采集一批图片做增量训练哪怕是补充一两百张新场景的标注图都能让模型在新区域表现提升一大截。针对这种情况我在实际项目里有一个经验每到一个新区块先飞一架次收集几百张图片让模型在这些图上做预测再把高置信度框导出成“预标注”人工修正后补入训练集迭代三轮左右模型在新区域的稳定表现就能达到可用水平。这个循环越跑越快数据集的规模也会从1034张慢慢长大到几千张泛化能力越来越稳。我个人在实际操作中的体会是数据集的价值不只在当前这一版更在它的格式规范和迭代机制。VOCYOLO双格式让团队里不同分工的人都能顺利接手标注的同学用VOC对着图片检查没问题训练的同学拿着YOLO直接跑脚本不用改代码。1034张、1个类别的规模看起来不起眼但把“标注标准统一、格式切换顺畅、模型选型合理、评估指标贴合业务”这几件事做扎实这套流程跑通之后后面再扩充到多类别、多区域都只是往管道里添数据而已。如果你正在做类似的项目希望这篇复盘能帮你少走几步弯路。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑