ARTICLE DETAIL

资讯详情

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

家庭场景分割实战:PNG掩码转YOLO分割标签与训练调优

家庭场景分割实战:PNG掩码转YOLO分割标签与训练调优 简介这套家庭场景全景分割数据集面向计算机视觉与深度学习学习者适合做家具细粒度分割、全景分割模型训练以及YOLOv5分割实战项目。图像分辨率统一为640×640jpg原图配png掩膜标注覆盖床、椅子、橱柜、门、灯、地毯、桌子、窗户等19类目标具体类别可在txt标签文件中查看。数据按训练集与验证集划分训练集309张图片及对应掩膜验证集53张运行show脚本即可可视化掩膜叠加效果便于快速检查标注质量。资源打包为7z压缩包共727个文件其中363个png掩膜、362个jpg原图另有1个txt类别标签和1个可视化py脚本整体约14.74MB体量轻巧、结构清晰。目前已有147人学习下载。除了可直接用于训练的标注数据集还附带mask可视化代码与类别文本省去自行整理标签的麻烦搭配作者博客中的网络分割、YOLOv5分割实战教程可快速上手训练与评估流程。1. 家庭场景全景分割为什么矩形框不够用矩形框能告诉你“床在图像哪个区域”但框里通常带着半个床头柜和一段墙要做家具换色、空间测量、AR 摆放这些细粒度任务框里的背景反而成了噪音。这个数据集把家庭场景里的家具全部做到了像素级掩码标注共 19 个语义类图像统一为 640×640训练集 309 张、验证集 53 张每张图像对应一张 PNG 格式的 mask。mask 里每个像素存的是类别 ID不是 RGB 颜色。压缩包还带上可视化脚本和 classes.txt解压后可以直接看标注和原图的叠加效果。适合刚入门分割、想快速跑通 U-Net 或 YOLOv8-seg 的工程师已经熟悉检测的人重点则放在第 4 章怎么把这份语义掩码转成能喂给 YOLO 的实例分割标签。2. 数据集目录与 PNG 掩码的类别编码2.1 images 和 masks 双层目录同名一一对应解压后目录结构是典型的“图像 掩码”双目录形式。训练集与验证集各自维护一份 images 和 masks文件名称完全一致只是扩展名不同。home_furniture_dataset/ ├── train/ │ ├── images/ │ │ ├── 95725a287808df0df79b3a7679ea550e_jpg.rf.215366b7db7c01b96bef097207cad1da.jpg │ │ └── ... │ └── masks/ │ ├── 95725a287808df0df79b3a7679ea550e_jpg.rf.215366b7db7c01b96bef097207cad1da.png │ └── ... ├── valid/ │ ├── images/ │ └── masks/ ├── classes.txt └── show.py文件名里的_jpg.rf.后缀是导出工具留下的历史标记对训练没有影响只要保证同一 basename 下 jpg 和 png 配对即可。训练集和验证集数量分别是 309 和 53总计 362 张图。对小样本分割实验来说这个规模不适合直接冲击高精度但很适合验证损失函数设计、数据增强策略和掩码后处理流程。2.2 classes.txt 里类别 ID 跳号不能直接当连续索引用摘要里给出了部分类别映射0 背景、1 床、2 椅子、3 橱柜、5 门、10 灯、14 地毯、15 桌子、18 窗户剩下类别在 classes.txt 里查看。常见格式是每行一个ID 名称0 background 1 bed 2 chair 3 cabinet 5 door 10 lamp 14 carpet 15 table 18 window ...这里有个容易踩的坑类别 ID 不是连续的4、6、7、8、9 等 ID 直接跳过。原始标注体系可能来自某个固定 id 定义表导出时没有重映射。如果你打算直接用这张 mask 训练 U-Net 这类逐像素分类模型直接保留 0–18 的 ID 没问题但 YOLO 系列分割模型要求类别索引从 0 连续递增。因此第 4 章转换时我做了显式的 id_map而不是直接取unique(mask)。2.3 读 mask 不要用 cv2.imread 默认参数PNG 掩码有两种常见存储方式单通道灰度索引或者带调色板的索引 PNG。两种方式在文件系统里都是*.png直接用cv2.imread(path)读取时OpenCV 会把调色板自动展开成三通道 BGR导致 mask.shape 变成(640, 640, 3)再想拿它当类别索引就会出错。我在处理这类数据集时统一用 PIL 读取from PIL import Image import numpy as np mask np.array(Image.open(train/masks/xxx.png)) print(mask.shape) # (640, 640) print(np.unique(mask)) # [ 0 1 2 3 5 10 14 15 18 ...]用Image.open后转np.array如果 PNG 是调色板模式数组里保存的是调色板索引如果是灰度模式保存的是灰度值。对标注掩码来说这两种情况读出来的都是真实类别 ID。图像侧仍用cv2.imread或 PIL 皆可注意 OpenCV 是 BGR 通道顺序做可视化叠加时需要转成 RGB 再显示。3. 可视化脚本与掩码叠加验证3.1 show.py 的工作方式压缩包里自带 show.py运行后会把 mask 以半透明彩色层叠到原图上。脚本内部逻辑通常包含三件事读图像、读 mask、生成 colormap 并做 alpha 混合。直接在数据集根目录下执行python show.py --data valid --save output如果脚本没带参数也可能硬编码了路径这时需要在根目录运行才不会报文件不存在。建议先跑一次确认每张图的类别边界和物体轮廓是否对齐。3.2 自建一个更可控的叠加工具自己写可视化脚本的好处是可以顺手统计类别像素占比发现空标注和错标。下面这个脚本同时完成叠加和统计from pathlib import Path import numpy as np import cv2 from PIL import Image rng np.random.RandomState(42) colors rng.randint(0, 255, (19, 3), dtypenp.uint8) def overlay_and_stats(image_path, mask_path): img cv2.imread(str(image_path)) img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) mask np.array(Image.open(mask_path)) h, w mask.shape rgb np.zeros_like(img) for cid in range(19): rgb[mask cid] colors[cid] blend cv2.addWeighted(img, 0.6, rgb, 0.4, 0) total mask.size stats {} for cid in np.unique(mask): cnt int((mask cid).sum()) stats[int(cid)] (cnt, cnt / total * 100) return blend, stats for png in Path(valid/masks).glob(*.png): jpg Path(valid/images) / (png.stem .jpg) if not jpg.exists(): continue overlay, stats overlay_and_stats(jpg, png) print(png.name, stats)参数说明RandomState(42)固定随机种子保证每次生成相同调色板方便多张图比较alpha0.4控制 mask 透明度验证边界时越大越容易看到锯齿stats里类别 ID 是 mask 中原生 ID不是连续索引。验证时可以重点关注三类问题同一物体边缘是否平滑、小物体是否漏标、相近类别如地毯和地板是否混淆。3.3 从统计里判断类别平衡性一份 309 张的训练集背景像素通常占绝对多数。如果某张图只有背景 ID说明该样本的 mask 可能是空的训练前应剔除或排查。常见做法是把统计结果按像素占比降序排列背景超过 60% 的样本减少采样权重避免模型偏向背景。4. 把 PNG 语义掩码转换成 YOLO 分割标签4.1 为什么 YOLO 分割不直接消费 PNGYOLOv5-seg 和 YOLOv8-seg 的训练标签是 txt 文本每行表示一个实例第一个数字是类别 ID后面跟着多边形顶点坐标坐标值统一归一化到 0–1。这个格式的设计目标是承载“实例级”掩码而语义分割 mask 只区分了“像素属于哪类”没有区分同一类里的多个对象。转换时需要把每个语义类的连通区域单独提取出来转成多边形再写进 txt。对于家庭场景床、桌子、椅子这类物体通常不重叠cv2.findContours外加RETR_EXTERNAL就能拿到合理的外轮廓。真正将两组家具贴在一起的情况一个连通块里包含两把相邻椅子这类 mask 需要手动拆分转换脚本只能尽量保留轮廓。4.2 掩码转多边形并重映射类别 ID下面是我常用的转换脚本。先建立旧 ID 到新连续 ID 的映射表再对每个旧 ID 生成二值图提取外轮廓并用approxPolyDP简化坐标点。import cv2 import numpy as np from pathlib import Path from PIL import Image id_map {1: 0, 2: 1, 3: 2, 5: 3, 10: 4, 14: 5, 15: 6, 18: 7} src_masks Path(train/masks) dst_labels Path(train/labels) dst_labels.mkdir(exist_okTrue) for png_path in src_masks.glob(*.png): mask np.array(Image.open(png_path)) h, w mask.shape[:2] lines [] for old_id, new_id in id_map.items(): binary (mask old_id).astype(np.uint8) contours, _ cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for contour in contours: epsilon 0.003 * cv2.arcLength(contour, True) approx cv2.approxPolyDP(contour, epsilon, True) point_list approx.reshape(-1, 2).astype(np.float32) if len(point_list) 3: continue point_list[:, 0] / w point_list[:, 1] / h coord_str .join(f{v:.6f} for v in point_list.flatten()) lines.append(f{new_id} {coord_str}) label_path dst_labels / (png_path.stem .txt) label_path.write_text(\n.join(lines))脚本逻辑说明RETR_EXTERNAL只取最外层轮廓避免把椅子镂空部分也当成独立多边形approxPolyDP的epsilon表示最大逼近误差与原轮廓周长的比例值越大顶点越少文件越精简但边界拟合也会变粗。对 640×640 的家具轮廓我一般取 0.002–0.005太小会保留几百个点太大则会把椅背直线化。归一化时把坐标除以w和h能保证不同分辨率下训练通用性。4.3 dataset.yaml 与训练启动转换完文本标签后需要新建 YAML 数据配置。由于原类别 ID 有跳号这里的 names 必须和 id_map 顺序一致不能用原 ID 直接当索引。path: home_furniture_dataset train: train/images val: valid/images nc: 8 names: 0: bed 1: chair 2: cabinet 3: door 4: lamp 5: carpet 6: table 7: window注意这里没有把背景作为单独类别。YOLO 分割训练时前景物体之外的部分天然是背景无需显式标注保留背景类反而会让模型在背景区域产生很多冗余框。训练命令用 YOLOv8 为例yolo segment train \ datahome_furniture.yaml \ modelyolov8s-seg.pt \ epochs100 \ imgsz640 \ batch16 \ cacheTrue参数说明cacheTrue把图像和标签提前加载进内存362 张图总量不大能明显减少训练时磁盘 IOyolov8s-seg.pt使用 COCO 预训练权重迁移收敛速度远快于随机初始化imgsz640与数据集原始分辨率一致避免二次缩放造成掩码精度损失。5. 640×640 小样本分割的训练调优与验证转换出标签只是第一步。309 张训练图在 640×640 下属于小样本模型很容易在 30 个 epoch 左右过拟合。我一般先把数据增强强度提上去mosaic1.0、mixup0.2、fliplr0.5。YOLOv8 默认 hyp 偏保守训练时可以在命令行覆盖yolo segment train \ datahome_furniture.yaml \ modelyolov8s-seg.pt \ epochs200 \ imgsz640 \ batch16 \ mosaic1.0 \ mixup0.2 \ close_mosaic10close_mosaic10表示最后 10 个 epoch 关闭 mosaic避免过度增强影响细粒度轮廓收敛。若发现 loss 出现 NaN优先关闭 AMPampFalse。类别数量少于 19 时建议检查重映射后的类别分布比如灯和地毯可能只出现在十几张图里这类样本在 mosaic 中参与度低模型对它的 mask 预测会明显偏弱可以对这些图做重复采样或把flipud打开增加几何变化。验证阶段不要只看mAP50这一个值还要看 mask 指标。预测一批验证图yolo segment predict \ modelruns/segment/train/weights/best.pt \ sourcevalid/images \ save_txtTrue \ save_confTrue输出目录里会同时保存图像上的掩码叠加结果和 txt 多边形。重点检查三类误差小物体如灯的轮廓是否被吞并桌腿与地毯边界是否粘连椅背镂空区域是否被填充。对于粘连问题通常是因为轮廓简化 epsilon 偏大导致多边形凸出重新把转换脚本里的 epsilon 从 0.003 降到 0.001 并重训即可。本文还有配套的精品资源点击获取
返回列表