ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

7820张labelme建筑墙面缺陷分割数据集:从polygon转mask到训练落地

7820张labelme建筑墙面缺陷分割数据集:从polygon转mask到训练落地 简介建筑墙壁损伤缺陷分割数据集以docx文档形式提供面向从事建筑视觉检测、结构健康监测及机器学习图像分割研究的工程师与开发者旨在帮助读者快速理解裂缝、剥落、锈蚀等20类墙面缺陷数据的标注标准与使用方法。文档共1个文件压缩包仅2.1MB集中整理了该数据集的完整说明包括7820张jpg图片与对应json标注的总体结构、每类标注框数统计、640×640分辨率及多边形标注规则同时给出各标注类别的中英文对照、labelme 5.5.0查看编辑方法以及自行转换mask/YOLO/COCO格式的建议。已有102人学习下载适合正在开展建筑缺陷分割实验或需要快速了解firc-dataset结构的研究者与初学者。通过这份说明读者可先掌握数据集的类别构成与数量分布再决定如何使用该数据训练语义分割或实例分割模型从而减少摸索数据格式的时间提升后续实验效率。1. 建筑墙壁损伤缺陷分割为什么非要一份打包好的labelme数据集拿到7820张建筑墙壁损伤缺陷图像、20类缺陷标注、统一封装成labelme格式时我第一反应是这省掉了一个团队两周的标注协调成本。过去做外墙缺陷检测项目标注员用不同工具导出不同格式有人画矩形框有人画多边形还有人把裂缝描成一条线存成别的格式到算法那边全要人工清洗。这个标题里最值钱的信息不是“7820张”这个数量而是“labelme格式”这五个字——它意味着每个标注文件都带着可编辑的多边形坐标缺陷的位置、形状、类别信息没有被压扁成黑盒掩码方案能直接进分割模型训练流程。要做建筑墙面裂缝、渗水、空鼓、剥落这类像素级定位任务或者想验证分割数据集如何落地到实际检测项目的人这份数据给的是一条清晰可走的路。这篇笔记会从labelme文件结构讲起一路写到polygon转mask、类别不均衡处理和可用性验证让你拿到这份文档就能判断它值不值得投入。2. 认识labelme的真实结构一份JSON里藏着分割集的全部秘密2.1 拆分一个labelme标注文件核心字段与polygon的存储方式labelme格式之所以是缺陷分割数据集的“通用语”在于它把标注信息完整地保存在JSON里而不是直接输出一张和原图一样大的PNG掩码。每张墙壁图像对应一个同名JSON文件打开后能看到几个关键字段。下面这个结构是从典型labelme标注中抽取的示意字段名和labelme 5.x保持一致{ version: 5.2.1, flags: {}, shapes: [ { label: crack, points: [[324, 511], [328, 480], [335, 442]], group_id: null, shape_type: polygon, flags: {} }, { label: spalling, points: [[102, 305], [150, 301], [188, 330], [160, 380]], group_id: 1, shape_type: polygon, flags: {} } ], imagePath: img_0001.jpg, imageData: null, imageHeight: 1024, imageWidth: 768 }这里最重要的字段是shapes。它是一个列表每一行对应图像中的一个缺陷实例points按顺序记录多边形顶点的像素坐标label是缺陷类别名shape_type标记这个标注是多边形还是矩形。imageData在大多数实际导出时被置为null以减小文件体积图像本身和JSON放在同一目录下通过imagePath关联。数据集的目录通常长这样images/放JPG原图annotations/放同名JSON二者靠文件名一一对应。基于polygon的分割标注有一个天然优势标注员只需要点出缺陷的边缘顶点不需要像语义分割那样逐像素涂色一道2米长的裂缝可能只需要十几个点就能圈定。代价是后续要把多边形“栅格化”成像素掩码这一步我会在第三章展开。当你要批量检查数据集是否有问题第一步永远是遍历所有JSON统计每个label出现的次数。以下是读取和统计类别的脚本骨架import json import glob from collections import Counter json_files sorted(glob.glob(annotations/*.json)) label_counter Counter() empty_files [] for jf in json_files: with open(jf, r, encodingutf-8) as f: data json.load(f) shapes data.get(shapes, []) if len(shapes) 0: empty_files.append(jf) continue for s in shapes: label_counter[s[label]] 1 print(类别总数:, len(label_counter)) for label, cnt in label_counter.most_common(): print(f{label}: {cnt}) print(空标注文件数:, len(empty_files))这段脚本的输出直接决定后面怎么做类别平衡。glob.glob按字母序收集文件Counter统计每个类别出现的次数顺带把shapes为空的文件单独记下来——空标注文件通常在后续训练中被当成无目标样本但如果数量异常多说明标注流程在某个环节漏存了文件。empty_files列表要导出到日志里人工抽查不能只打印一个数字就略过。2.2 为什么用labelme而不是COCO或VOC三种分割格式的选型对比做分割数据集业界常见格式有labelme JSON、COCO JSON和VOC格式的PNG掩码三套方案。它们之间可以相互转换但选型时看的是标注阶段和算法阶段的衔接成本。格式标注存储方式视觉可读性转换成本适用阶段labelme每图一个JSON多边形坐标高可加载回labelme复核低天然便于人工修正数据采集与标注验收COCO所有图一个JSONsegmentation存坐标中需借助工具可视化中解析嵌套结构麻烦Mask R-CNN、Detectron2训练VOCPASCAL VOC格式PNG掩码类别存调色板低肉眼难分辨类别值高丢失original标注转回坐标困难老版语义分割模型我在实际项目里的选择标准很直接凡是标注还在迭代、需要反复和标注员对齐的一律用labelme保存原始标注只有当训练框架明确要求COCO格式时才写脚本转换。VOC格式的PNG掩码最大的问题是“不可逆”——从PNG里找不回多边形的顶点坐标如果标注员画错了边框只能重新找原图再画一遍。labelme JSON则保留了完整的编辑痕迹points变了什么、label改了什么git diff都能看出来这对团队协作是质的差别。标题里的这份数据集既然明确标了“labelme格式”说明数据生产方已经把最费人工的标注阶段做好了。算法工程师拿到手第一件事不是转格式而是先用labelme自带的可视化看一眼标注叠加效果。2.3 用labelme打开一张标注复核数据质量的第一动作任何数据集进入流程前我都会花一小时做抽样人工检查而不是直接写训练脚本。安装labelme最顺的路径是用conda建一个干净环境然后用pip安装conda create -n labelme python3.9 -y conda activate labelme pip install labelme启动后在labelme命令行里直接指定图像目录它会自动加载同名的JSON标注并叠加显示labelme images/复核时重点看三件事缺陷边缘和墙面图像边界是否贴合类别名是否和标注规范一致以及是否有明显的大块误标注。polygon标注的视觉可读性在此时体现出来裂缝、空鼓、剥落的边界都能看清比盯着PNG掩码里的像素值判断直观得多。抽样30-50张看完这个数据集能不能信心里基本有数。3. 把7820张labelme标注转成可训练数据polygon到mask的完整管线3.1 数据集的目录组织与文件命名训练验证划分前必须确认的细节拿到一个分割数据集我习惯先看它的目录组织这决定了后续划分脚本怎么写。常见的有两种布局一种是images/和annotations/平级JSON按同名关联另一种是每张图连同它的JSON放在同一个子目录里。这份数据集如果是按前一种组织划分时直接对文件名列表做split即可如果是后一种要先整理平铺再划分。这里有一个容易翻车的细节随机划分的时候如果直接按单个图像文件随机分到train/val/test同一栋楼不同角度的照片可能同时出现在训练集和验证集里。对建筑墙面缺陷来说同一面墙的采光、拍摄角度、缺陷形态高度相似模型在验证集上的表现会被虚高。我一般会在数据集根目录记录每张图来自哪栋楼、哪面墙然后按“楼栋”为单位划分。实在没有这类元信息就退而求其次按文件名前缀分组至少保证同一拍摄批次不要横跨训练集和验证集。划分脚本不复杂但比例要按缺陷难度调整。缺陷分割不像分类任务那样按9:1划分就够因为某些类别的正样本本来就少验证集切多了这些类别可能一张都分不到。常见做法是先在类别维度统计每张图包含哪些缺陷再按缺陷类别做分层采样。这个脚本在第四章会给到这里先记住结论别用纯随机划分墙面数据的场景相关性太强。3.2 polygon转二值mask基于OpenCV的填充方案与参数细节labelme的多边形要变成模型能吃的掩码核心操作是“栅格化”——把多边形顶点坐标填充到一张和原图同尺寸的单通道图上。大多数框架要求的是二值掩码缺陷为255背景为0如果有多个缺陷实例要么每个实例一张mask用于实例分割要么把同类别缺陷合并到一张mask里用于语义分割。以下是转换脚本的核心片段import json import numpy as np import cv2 def polygon_to_mask(json_path, img_width, img_height, class_map): with open(json_path, r, encodingutf-8) as f: data json.load(f) mask np.zeros((img_height, img_width), dtypenp.uint8) for shape in data[shapes]: label shape[label] if label not in class_map: continue pts np.array(shape[points], dtypenp.int32) # 用fillPoly填充注意顶点顺序需要闭合 cv2.fillPoly(mask, [pts], colorclass_map[label]) return mask这段脚本里有两个参数最容易踩坑。第一个是dtype必须设为uint8而不是bool因为后续很多增强库比如albumentations要求mask是uint8类型bool数组会导致输出维度报错或者可视化时整体发黑。第二个是cv2.fillPoly的第二个参数它接受的是一个“多边形数组的列表”所以pts外面要加方括号如果直接传ptsOpenCV会把每个顶点当成长度为1的多边形填充出来只有零散的像素点这是常见的低级错误。另外注意class_map的编码方式。语义分割里常见的做法是把20个类别映射到1-20的整数背景保持0。裂缝、渗水这些类别之间没有重叠用单一整数编码没问题。但如果两个缺陷在图像上有交叉例如裂缝穿过了剥落区域同一像素只能属于一个类别此时要么在标注层就约定层级优先级要么在编码时做“后台覆盖前台”的策略。实际建筑缺陷很少大面积重叠用整数编码基本够用。3.3 转成COCO或YOLO-seg主流训练框架的两种输入格式如果要用Mask R-CNN或Detectron2就得把labelme转成COCO JSON。COCO格式里每个标注对象是一个annotation条目segmentation字段存的是多边形顶点的展平坐标序列同时需要给每个实例分配一个唯一的id。转换的关键是遍历所有JSON、收集图像元信息和实例信息最后汇总成一个大JSON。下面是转换时最重要的坐标处理片段def polygon_to_coco_seg(points): # points: [[x1, y1], [x2, y2], ...] # COCO要求坐标展平为 [x1, y1, x2, y2, ...] flattened [] for x, y in points: flattened.extend([float(x), float(y)]) return [flattened]这里有一个必须注意的参数细节COCO的segmentation要求坐标是浮点数列表且一个对象可能有多段多边形比如缺陷被柱子遮挡成两段所以外层用了列表嵌套。如果你的框架接受的是RLE编码比如某些检测框架会要求稠密mask那就要先按3.2的方式生成二值mask再调用pycocotools.mask.encode做压缩这个后续步骤不要和polygon直接转换混淆。另一个主流的输入格式是YOLO-segUltralytics YOLOv8-seg系列就是用它。每张图对应一个txt文件每行格式是class_id x1 y1 x2 y2 ...坐标是相对于图像宽高的归一化值。polygon转换时先按原始坐标取浮点数再除以imageWidth和imageHeight。这里有个常见问题归一化坐标如果写到txt里丢失精度训练时掩码边缘会出现锯齿。解决方案是保留6位小数不要用整数坐标归一化。取舍上如果你想快速验证模型效果YOLO-seg的收敛速度比Mask R-CNN快得多如果要追求mAP的极致指标COCO格式仍然是生态兼容性最好的。4. 20个类别的分布陷阱与四个排坑记录样本不均、错标漏标这样处理4.1 类别频次统计与长尾分布哪些缺陷才是这张数据集的“少数派”20个类别听起来很全但真实缺陷数据的通病是类别分布极度不均衡。墙面裂缝、涂层剥落、渗水痕迹通常是高频类别加起来可能占掉七八成样本而空鼓、钢筋外露、砖缝破损这类缺陷数量稀少甚至某些类别在整个数据集里就只有几十个实例。直接把7820张图喂进模型模型会对低频类别“视而不见”验证时它们的mAP会惨不忍睹。要量化这个分布最直接的办法是统计每个类别的“实例数”和“包含该类别的图像数”。这两个数不一样一张图上可能同时有5处裂缝裂缝实例数是5但包含裂缝的图像只有1张。训练时更关心的是图像数因为增强单位是图像。我常用的统计脚本会输出这两列并排序随后用柱状图可视化低频类别的短板一目了然。处理低频类别的常见方案有三个一是对低频类别的图像做重度离线增强旋转、亮度扰动、随机裁剪让模型多看几个变体二是对低频类别设置更高的损失权重常见做法是weight 1 / sqrt(freq)给稀有类别更大的梯度贡献三是直接按实例数做类别均衡采样每张图的采样概率和它包含的稀有类别数成正比。第一种做法最直接实施成本也最低我现在会优先做离线增强而不是硬调权重。4.2 标注质量问题的现象、原因、解决四个实际排坑记录labelme数据集的标注是人画的人就会犯错。以下是转换和训练过程中最常见的四类问题按“现象→原因→解决”的顺序记录都是踩过坑后沉淀下来的处理流程。现象原因解决方式mask里出现面积巨大的全黑/全白噪块JSON的points坐标超出图像边界转换前做边界裁剪非法顶点用np.clip限制到图像范围内训练时loss不下降验证mAP接近0类别名拼写不一致同一个类别出现两种写法从所有JSON里提取label集合用相似度比对合并多边形的mask内部出现空洞标注时顶点顺序是逆时针fillPoly默认按顺时针逆时针混合处理统一规范顶点方向或改用cv2.fillConvexPoly并检查顶点数量验证集正常但实测泛化差部分缺陷被标注为整面墙模型学到的是墙面纹理而非缺陷人工抽检时删除面积占比超过图像面积50%的疑似错误标注第一类问题的根源是标注员在放大图像画多边形时顶点被拖出了画布边缘JSON里存了负坐标或者超过宽高的坐标。解决起来不复杂转换脚本里加一行pts[:, 0] np.clip(pts[:, 0], 0, img_width - 1)就能兜住但如果不加fillPoly的边界行为不可控。第二类问题最隐蔽比如“crack”和“cracks”同时存在模型把两个标签当成不同类别输出维度立刻变成21类而评估脚本还在按20类计算。每次拿到新数据集我第一件事都是打印全部类别名清单人工扫一遍拼写。第三类问题里fillConvexPoly只适用于凸多边形裂缝这种细长形状大概率是凹的所以它不是通用解最多是排查时用来对照。4.3 被忽略的图像尺寸差异分辨率不对齐如何影响模型效果墙面缺陷照片的采集设备不统一有的来自单反相机有的是手机拍摄还有的是无人机挂载。这导致数据集里图像宽度可能从512到4000像素不等。训练时如果统一resize到固定尺寸比如640×640小图里的细小裂缝会被压成一个模糊的灰色带模型基本学不到裂缝边缘特征大图缩小后细微的网状裂缝更是直接被抹平。处理这个问题的常见做法是分桶resize把图像按短边长度分成几个区间例如短边小于700、700到1200、大于1200每个桶分别缩放到目标尺寸而不是一刀切。另一个思路是训练时不分桶直接使用多尺度训练让模型每轮看到不同分辨率的图像增强对缺陷尺度变化的鲁棒性。具体选用哪种取决于显存大小和训练时间预算。我一般会在数据预处理环节记录每张图的原始分辨率直方图如果分布跨度超过3倍就用分桶方案如果比较集中直接统一到640训练即可。这个判断在验证集mAP提升上往往比调模型结构更有效。5. 用最小闭环验证这份数据集的可用性从安装到训练的半天落地路径验证一个分割数据集能不能用不需要一开始就跑完整的训练。我的习惯是先跑一个最小闭环把“数据集可用性”和“模型训练效果”分开验证半天内就能得出结论。第一步是安装labelme并抽样查看标注。用conda建环境、pip安装后随机挑20张图人工检查标注贴合度。这一步如果发现大面积错标直接止损不必浪费时间进入训练。第二步是写一个精简转换脚本把抽查通过的图像转出20张mask用cv2.addWeighted把mask按半透明叠加到原图上保存肉眼确认polygon到mask的转换没有明显失真。第三步是挑一个小模型训练几十轮不追求精度只看loss曲线能否稳定下降。# 以YOLOv8-seg为例训练前先做一次语法级数据检查 from ultralytics import YOLO model YOLO(yolov8n-seg.pt) # 只需要少量数据验证数据管线 results model.train(datadefect.yaml, epochs30, imgsz640, batch8)如果loss在10轮内明显下降说明数据格式和模型接口是通的如果loss卡住不动优先检查mask是否全黑、类别映射是否错位、以及数据加载有没有报错。最后一轮验证是看预测叠加图把模型在验证集上的预测mask画到原图上裂缝边界是否光滑连续。这个验证脚本很便宜却能过滤掉大量玄学调参。我现在的习惯是任何分割数据集进项目第一晚只做这三步第二晚才决定要不要投入完整训练。这套流程帮我挡掉过不少“看似精美但格式有毒”的数据集也筛选出过真正的优质数据。缺陷分割的坑大多埋在数据里模型结构反而不是瓶颈。希望这篇笔记能帮你把7820张和20个类别的硬指标变成一条真正能落地的检测管线少走几步弯路。本文还有配套的精品资源点击获取
返回列表