简介:本资源是面向计算机视觉初学者与安防、智慧城市领域开发者的室内积水检测专用数据集,聚焦真实场景下的水洼识别任务,适用于YOLO系列、Faster R-CNN等目标检测模型的训练与验证。压缩包共2000个文件,包含761张JPG图像、761份Pascal VOC格式XML标注文件(含精确矩形框坐标与类别标签)及761份YOLO格式TXT文件(归一化坐标),另有2个labelImg配置INI文件,整体体积189.23MB,结构规整、开箱即用。已有616人学习下载,数据经人工逐图标注,共902个“jishui”类别检测框,覆盖不同光照、视角与积水形态,标注工具为通用labelImg,兼容主流深度学习框架的数据加载流程。用户可直接用于模型训练、数据增强实验、mAP评估基线构建,或作为小样本检测任务的基准子集进行迁移学习研究。
1. 项目概述:一个专为室内积水检测打造的数据集
最近在整理过往项目资料时,翻出了一个自己几年前为了一个安防项目而制作的数据集——“室内积水检测数据集VOC+YOLO格式761张1类别”。这个数据集虽然规模不大,只有761张图片,且只标注了“积水”这一个类别,但在当时解决特定场景下的漏水、溢水预警问题时,却发挥了不小的作用。今天把它分享出来,一方面是给有类似需求的朋友一个现成的参考起点,另一方面也是借此机会,详细聊聊从零开始构建一个高质量、可用的自定义目标检测数据集的全过程。无论是想入门YOLO的新手,还是需要处理类似“积水检测”这种细分场景的开发者,相信都能从中获得一些实操性的启发。
这个数据集的核心价值在于其“场景特异性”。公开的通用目标检测数据集,如COCO、VOC,虽然类别丰富,但很难涵盖“室内积水”这种具体、细微且受环境光照、地面材质影响巨大的目标。自己动手制作数据集,虽然前期投入精力,但模型在实际场景中的表现会精准得多。数据集提供了VOC和YOLO两种格式,方便使用者根据自己熟悉的框架(如TensorFlow Object Detection API或PyTorch + YOLOv5/v8)快速上手。接下来,我将拆解这个数据集的构建思路、制作细节、使用技巧以及避坑指南。
2. 数据集构建的核心思路与场景定义
2.1 为什么需要专门的室内积水数据集?
在计算机视觉项目中,数据决定了模型能力的天花板。对于“积水检测”这个任务,通用数据集的不足非常明显:
- 形态多变,缺乏统一特征:积水不是像“猫”“狗”那样有固定形状的物体。它可能是一滩不规则的水渍,可能是一条细流,也可能因地面反光而呈现高亮区域。其外观严重依赖于水面面积、深度、光线角度和地面纹理(瓷砖、木地板、地毯积水看起来完全不同)。
- 背景干扰强烈:室内环境复杂,光滑地面(如大理石)的正常反光、深色地板的颜色、物品的阴影等,都极易被误判为积水。模型必须学会区分“水的反光”和“其他材质的反光”。
- 标注边界模糊:积水的边缘往往是渐变的、模糊的,不像一个边界框(Bounding Box)那样清晰。这给标注工作带来了挑战,也要求模型具备一定的抗模糊边界能力。
因此,构建一个针对性的数据集,核心思路就是最大限度地覆盖目标场景的视觉多样性,让模型见过足够多的“变体”,从而学习到“积水”的本质特征,而非偶然的视觉模式。
2.2 数据采集策略与场景覆盖
为了制作这761张图片,我主要从以下几个维度进行数据采集,以确保多样性:
- 场景多样性:涵盖了家庭(厨房、卫生间、阳台)、办公室、楼道、地下室、仓库等多种室内环境。不同场景的灯光、杂物、地面材质差异巨大。
- 积水形态多样性:
- 面积:从巴掌大的小水渍到蔓延开的大片积水。
- 形状:圆形、不规则长条形、溅射状等。
- 状态:静止积水、流动水痕、刚擦过后残留的湿痕。
- 光照条件多样性:
- 光源:自然光(白天、黄昏)、日光灯、白炽灯、射灯。
- 强度:明亮、昏暗、部分区域过曝(如阳光直射水面)。
- 角度:顶光、侧光、逆光。逆光下积水可能呈现为黑色剪影,而顺光下则反射强烈。
- 拍摄视角多样性:平视、俯视、斜视。模拟了固定摄像头(如天花板角落)和移动设备(如巡检机器人)的视角。
- 干扰项丰富性:刻意包含了容易混淆的场景,如干净反光的地板、深色地垫、玻璃倒影、塑料布反光等,并在标注时确保它们不被标为“积水”,从而让模型学会“排除法”。
实操心得:数据采集不是一蹴而就的。我采用“边训练、边分析、边补充”的策略。先用初期采集的几百张图训练一个初版模型,然后用它去检测一些新拍的或网上找到的室内图片,找出模型误检(把非积水当积水)和漏检(没认出积水)的案例。这些案例正是数据集的薄弱环节,针对性地补充这类“难例”(Hard Negative/Negative),能极大提升模型的鲁棒性。例如,初期模型总是把某种品牌的深色抛光瓷砖误认为积水,我就专门去拍了大量这种瓷砖在各种光线下的图片,作为负样本(不标注)加入训练集。
3. 数据标注详解:从工具选择到质量控制
3.1 标注工具选型:LabelImg与CVAT
对于目标检测任务,矩形框(Bounding Box)标注是基础。我主要使用了两个工具:
- LabelImg:老牌、轻量、离线的标注工具,非常适合个人或小团队起步。它直接支持输出PASCAL VOC格式的XML文件。优点是简单易上手,缺点是效率较低,缺乏团队协作和高级质检功能。
- CVAT:计算机视觉标注工具,功能强大,支持Web端使用,适合更复杂的任务和团队协作。它可以直接导出YOLO、VOC、COCO等多种格式。对于后期标注和质检,CVAT的审阅、分配任务、统计功能非常有用。
在这个项目中,前期主要使用LabelImg快速启动,后期为了统一管理和格式转换,部分数据在CVAT中进行了复核和补标。
3.2 标注规范制定:确保一致性
标注质量直接决定模型上限。我们制定了严格的标注规范:
- 框体紧密度: bounding box应尽可能紧密地包围积水区域,但不必追求像素级完美,因为积水边缘本身模糊。基本原则是:框住所有视觉上可辨识的“湿”或“反光”区域,略有余量以包容模糊边界。
- 多块积水处理:同一张图片中不相连的积水,分别用多个框标注。对于连成一片的大面积积水,仍然用一个框标注整体,而不是分割成多个小框。这有助于模型学习积水的整体形态特征。
- 模糊与不确定区域:对于非常浅、几乎不可见的水痕,或者无法确定是否是水渍的反光,遵循“存疑不标”的原则。宁愿漏标,也不要错标。错标的危害远大于漏标,它会直接“教坏”模型。
- 类别唯一:本数据集只有“water”或“accumulated_water”一个类别,在标注时统一类别名。
3.3 VOC与YOLO格式详解与转换
数据集提供了两种格式,理解它们的差异对后续使用至关重要。
PASCAL VOC格式: 每个图像对应一个XML文件,包含图片尺寸、通道、以及每个目标的对象名称和边界框坐标(xmin, ymin, xmax, ymax)。坐标是绝对像素值。
<annotation> <size> <width>1920</width> <height>1080</height> <depth>3</depth> </size> <object> <name>water</name> <bndbox> <xmin>500</xmin> <ymin>300</ymin> <xmax>800</xmax> <ymax>600</ymax> </bndbox> </object> </annotation>YOLO格式: 每个图像对应一个同名的.txt文件。每行代表一个目标,格式为:<class_id> <x_center> <y_center> <width> <height>。这里的坐标是归一化后的值(0到1之间),即相对于图片宽度和高度的比例。
0 0.40625 0.416667 0.15625 0.166667class_id: 类别索引,本例中只有0。x_center, y_center: 边界框中心点的x、y坐标除以图片宽高。width, height: 边界框的宽度和高度除以图片宽高。
格式转换脚本: 从VOC转换到YOLO格式是常见需求。以下是一个Python脚本的核心逻辑:
import xml.etree.ElementTree as ET import os def convert_voc_to_yolo(voc_annotation_path, output_txt_path, classes_list): tree = ET.parse(voc_annotation_path) root = tree.getroot() size = root.find('size') img_w = int(size.find('width').text) img_h = int(size.find('height').text) with open(output_txt_path, 'w') as f: for obj in root.iter('object'): cls_name = obj.find('name').text if cls_name not in classes_list: continue cls_id = classes_list.index(cls_name) xmlbox = obj.find('bndbox') x1 = float(xmlbox.find('xmin').text) y1 = float(xmlbox.find('ymin').text) x2 = float(xmlbox.find('xmax').text) y2 = float(xmlbox.find('ymax').text) # 计算归一化后的中心点和宽高 x_center = (x1 + x2) / 2.0 / img_w y_center = (y1 + y2) / 2.0 / img_h width = (x2 - x1) / img_w height = (y2 - y1) / img_h # 写入YOLO格式 f.write(f"{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}\n") # 使用示例 classes = ["water"] # 类别列表,顺序决定class_id convert_voc_to_yolo("000001.xml", "000001.txt", classes)注意事项:转换时务必确保图片宽高读取正确。有时XML里的尺寸信息可能错误(如为0),更可靠的做法是直接用OpenCV读取对应图片获取
img_h, img_w。另外,YOLO格式要求坐标值在[0,1]区间,计算后最好做一次clip操作,防止越界。
4. 数据集划分、增强与YOLO训练配置
4.1 数据集划分与目录结构
761张图片的划分比例通常为:训练集(Train): 验证集(Val): 测试集(Test) = 70% : 20% : 10%。这是一个在数据量不大时比较稳妥的比例,确保验证集和测试集有足够的样本进行评估。
最终的目录结构应清晰,这是YOLO等框架所要求的:
indoor_water_dataset/ ├── images/ │ ├── train/ # 训练集图片 (e.g., 533张) │ ├── val/ # 验证集图片 (e.g., 152张) │ └── test/ # 测试集图片 (e.g., 76张,可留作最终评估) └── labels/ ├── train/ # 对应训练集的YOLO格式标签 ├── val/ # 对应验证集的YOLO格式标签 └── test/ # 对应测试集的YOLO格式标签重要:images和labels下的子目录名称(train,val,test)必须对应,且图片和标签文件除后缀名外,主文件名必须严格一致(如001.jpg对应001.txt)。
4.2 数据增强策略:针对积水检测的“特效药”
数据增强是提升模型泛化能力、防止过拟合的利器。对于积水检测,我采用了以下有针对性的增强组合(使用Albumentations或YOLO内置增强):
- 色彩与对比度扰动:
- HSV增强:随机调整图像的色调(H)、饱和度(S)、明度(V)。积水在不同色温灯光下颜色不同,此增强模拟了这种变化。
- 亮度对比度:随机调整亮度和对比度。模拟不同光照强度下的场景,特别是昏暗环境。
- 几何变换:
- 随机旋转(小角度):如±15度。因为摄像头可能略有倾斜。
- 随机平移、缩放、裁剪:模拟不同视角和距离。
- 水平翻转:一个简单但有效的增强,因为积水形态没有固定的左右方向。
- 模拟水渍特性增强:
- 模糊:添加轻微的高斯模糊或运动模糊。模拟摄像头对焦不准或快速移动时的情况,也能让模型不过度依赖清晰的纹理边缘。
- 模拟反光:在图像随机位置添加高光或光斑(需谨慎使用,强度不宜过大),让模型适应强烈的镜面反射。
- Mosaic增强:YOLOv5/v8等框架自带。将四张图片拼成一张进行训练,极大地提升了模型在一个批次内看到不同场景和小目标的能力,对于学习积水这种形态多变的物体非常有效。
避坑技巧:谨慎使用Cutout/RandomErasing(随机擦除)。这类增强会随机遮挡图片的一部分。如果遮挡区域恰好是积水,而标签没有相应调整,模型会学到“积水可以突然消失”的错误关联。如果要用,必须确保数据加载管道能同步处理标签,或者使用更安全的增强方式。
4.3 YOLO模型训练配置要点
以YOLOv8为例,其训练配置非常简洁。核心在于准备一个data.yaml文件和一个model.yaml(或选择预训练模型)。
data.yaml文件示例:
# 数据集路径 path: /path/to/indoor_water_dataset # 数据集根目录 train: images/train # 训练集相对路径(相对于path) val: images/val # 验证集相对路径 # 类别数 nc: 1 # number of classes,我们只有1类 # 类别名称列表 names: ['water'] # 类别名称,顺序与标注时的class_id对应启动训练命令:
yolo task=detect mode=train model=yolov8n.pt data=data.yaml epochs=100 imgsz=640 batch=16model=yolov8n.pt: 使用预训练的YOLOv8nano模型进行迁移学习,这是在小数据集上取得好效果的关键。epochs=100: 对于700多张图,100-150个epoch通常足够,具体看验证集损失是否收敛。imgsz=640: 输入图像尺寸。可根据原始图片分辨率调整,但640是速度和精度的良好平衡点。batch=16: 批次大小,取决于你的GPU显存。如果出现CUDA out of memory错误,就减小batch或imgsz。
关键参数解析:
- 预训练权重:务必使用
model=*.pt。从零训练(model=yolov8n.yaml)在小数据集上几乎必然过拟合,效果很差。 - 图像尺寸:训练和验证的尺寸应保持一致。推理时可以用不同尺寸,但可能会影响精度。
- 早停(Early Stopping):YOLOv8内置了早停机制。当验证集指标在指定epoch内不再提升时,会自动停止训练,防止过拟合。你可以通过
patience=50参数来调整耐心值。
5. 模型训练过程监控与性能调优
5.1 训练日志解读与关键指标
训练开始后,监控以下指标至关重要:
损失函数(Loss):
train/box_loss: 边界框定位损失。下降并趋于平稳为好。train/cls_loss: 分类损失。对于单类别问题,此项通常很低。train/dfl_loss: YOLOv8使用的分布焦点损失(Distribution Focal Loss),与框的精确度有关。- 最重要的是
val/box_loss: 验证集定位损失。它是判断模型是否过拟合的“金标准”。理想情况是训练损失和验证损失同步下降,最后都稳定在一个较低值。如果训练损失持续下降而验证损失先降后升,就是典型的过拟合。
性能指标(Metrics):
metrics/mAP50(B): 在IoU阈值为0.5时的平均精度(mAP)。这是最常用的综合指标。值在0到1之间,越高越好。对于积水检测,如果能稳定在0.85以上,说明模型已经相当不错。metrics/mAP50-95(B): IoU阈值从0.5到0.95(步长0.05)的平均mAP。这是一个更严格的指标,要求边界框预测得更精确。metrics/precision(B): 查准率。预测为积水的框里,有多少是真的积水。高精度意味着误报少。metrics/recall(B): 查全率。所有真实的积水框里,有多少被预测出来了。高召回意味着漏报少。
5.2 过拟合的诊断与应对策略
在小数据集(761张)上训练,过拟合是头号敌人。迹象包括:验证集损失上升、验证集mAP远低于训练集mAP、模型在没见过的测试图片上表现糟糕。
应对策略:
- 强化数据增强:这是最有效的手段。增加前面提到的各种增强的强度或概率,尤其是Mosaic、MixUp等“重型”增强,能强制模型学习更泛化的特征,而不是记住训练图片的细节。
- 降低模型复杂度:如果使用YOLOv8m或YOLOv8l过拟合严重,可以换回更小的模型如YOLOv8n或YOLOv8s。
- 增加正则化:
- 权重衰减(Weight Decay): 在训练命令中添加
weight_decay=0.0005(或更大),惩罚大的权重,使模型更平滑。 - DropOut: 虽然YOLO主干网络一般不直接用DropOut,但可以在分类头等全连接层尝试。
- 权重衰减(Weight Decay): 在训练命令中添加
- 早停(Early Stopping): 充分利用YOLOv8的早停功能,保存验证集性能最好的那个模型权重,而不是最后一个epoch的权重。
- 减少训练周期: 如果早停触发得很早(比如50个epoch就停了),说明可能不需要训练那么久,可以适当减少
epochs。
5.3 学习率调整与优化器选择
YOLOv8默认使用SGD优化器,并带有余弦退火学习率调度器。对于小数据集,默认设置通常工作良好。但如果训练不稳定(损失剧烈震荡),可以尝试:
- 降低初始学习率(lr0): 使用
lr0=0.01(默认是0.01)或更小。学习率太大容易在损失盆地周围震荡,无法收敛到最优点。 - 使用AdamW优化器: 在某些情况下,AdamW可能比SGD收敛更快、更稳定。可以通过修改YOLO的源代码或使用其高级API进行尝试,但这需要更深入的调试。
- 预热(Warmup): YOLOv8默认有预热。在训练初期,学习率从一个很小的值线性增加到设定值,有助于训练稳定性。
实操心得:不要盲目调参。首先确保数据质量(标注准确、划分合理)、数据增强足够,并使用合适的预训练模型。在默认参数下先跑一个基线(Baseline),记录其性能。然后每次只调整一个超参数(如学习率),看验证集指标的变化。调参是一个系统性的实验过程,需要耐心和记录。
6. 模型评估、部署与常见问题排查
6.1 模型评估与测试集验证
训练完成后,使用最佳模型(通常是保存在runs/detect/train/weights/best.pt)在从未参与训练和验证的测试集上进行最终评估。
yolo task=detect mode=val model=runs/detect/train/weights/best.pt data=data.yaml这会输出测试集上的详细指标,这是对模型泛化能力的最终检验。
可视化检查:数字指标好,不代表视觉效果好。一定要用模型对测试集图片进行推理,并人工检查结果。
yolo task=detect mode=predict model=best.pt source=path/to/test_images save=True重点关注:
- 误检(False Positive): 哪些东西被错误地当成了积水?是反光、阴影还是特殊纹理?这些是下一步补充“难例”数据的关键。
- 漏检(False Negative): 哪些积水没有被检测出来?是因为面积太小、颜色太浅、光线太暗还是形态太特殊?
- 定位精度: 预测框和真实框的重合度(IoU)如何?框的位置是否合理?
6.2 模型部署与优化
得到满意的模型后,可以将其部署到实际应用场景,如服务器、边缘设备或移动端。
- 模型导出: YOLOv8支持导出多种格式。
yolo export model=best.pt format=onnx # 导出为ONNX,用于OpenCV DNN、TensorRT等 yolo export model=best.pt format=torchscript # 导出为TorchScript,用于PyTorch移动端 yolo export model=best.pt format=engine # 需要TensorRT环境,导出为TensorRT引擎,极大提升推理速度 - 推理优化:
- 批量推理: 如果一次处理多张图片,使用批量推理可以显著提升吞吐量。
- 半精度(FP16)推理: 在支持TensorRT或GPU上,使用FP16精度可以在几乎不损失精度的情况下,提升速度并减少显存占用。
- 图像尺寸: 部署时,可以根据摄像头输入分辨率调整推理尺寸。不一定非要和训练时的
imgsz一致,但改变尺寸可能会影响精度,需要测试。
6.3 常见问题与排查技巧实录
以下是在构建和训练这个积水检测数据集过程中遇到的一些典型问题及解决方法:
| 问题现象 | 可能原因 | 排查与解决思路 |
|---|---|---|
| 训练损失不下降或震荡剧烈 | 1. 学习率过大。 2. 数据标注存在大量错误。 3. 数据集中存在大量无效或损坏图片。 | 1. 大幅降低lr0(如设为1e-4)再试。2. 随机抽查训练集标注,检查框是否错标、漏标。 3. 检查图片是否能正常打开,格式是否正确。 |
| 验证集mAP很低,但训练集mAP很高 | 严重过拟合。模型记住了训练集噪声,而非一般特征。 | 1.加强数据增强(首要)。 2. 使用更小的模型(YOLOv8n)。 3. 增加权重衰减参数 weight_decay。4. 收集更多样化的训练数据。 |
| 模型对某种特定场景(如某种瓷砖)误检率高 | 数据集中该类“难例”负样本不足。 | 针对性采集该场景下非积水的图片,加入训练集(不标注任何框,作为负样本)。 |
| 小面积积水漏检严重 | 1. 训练时输入图片尺寸imgsz太小,小目标信息丢失。2. 数据集中小目标样本少。 | 1. 尝试增大imgsz(如从640到960),但会增加计算量。2. 在数据增强中增加“小目标复制粘贴”增强。 3. 专门采集并标注更多小积水样本。 |
| 推理速度慢 | 1. 模型太大(如用了YOLOv8l)。 2. 推理图片尺寸过大。 3. 未使用优化后的运行时(如TensorRT)。 | 1. 换用更轻量模型(YOLOv8n/s)。 2. 在不显著影响精度前提下,减小推理尺寸。 3. 将模型导出为TensorRT或ONNX,并使用对应加速库推理。 |
| 标注文件读取错误 | 1. YOLO格式标签文件坐标值超出[0,1]范围。 2. 图片路径或标签路径错误。 3. 图片与标签文件名不匹配。 | 1. 编写脚本检查所有标签文件,修复越界坐标。 2. 检查 data.yaml中的路径是否正确,是否为绝对路径或正确的相对路径。3. 确保 images/train和labels/train下的文件一一对应。 |
最后一点个人体会:做一个可用的自定义数据集,其工作量和技术要点常常被低估。它远不止是“拍些照片、画些框”那么简单。从场景规划、数据采集的多样性设计,到标注规范的制定与质检,再到数据增强策略的针对性调整,每一步都需要基于对业务场景(这里是“室内积水”)的深刻理解。这个761张的数据集,虽然看起来不大,但其中覆盖的灯光、角度、干扰项,都是经过思考和设计的。对于希望入门AI应用开发的朋友,我强烈建议从这样一个完整的、小规模的数据集项目开始,它能让你系统地走完从数据到模型再到评估的完整闭环,其中的经验和教训,比单纯调参跑通一个公开数据集模型要宝贵得多。在实际项目中,当你发现模型在某个角落表现不佳时,你立刻能想到该去补充哪种类型的数据,这种“数据驱动”的思维,才是解决实际问题的核心能力。
本文还有配套的精品资源,点击获取