资讯动态

平面图元素识别数据集详解:从标注到YOLO/COCO/VOC训练调优

发布时间:2026/10/19 7:39:42 来源:尧图企业网站定制
做平面图元素识别最让人头疼的往往不是跑通一个模型而是手里没有一批靠谱的数据。我之前做过一个室内设计自动化的探索项目前前后后花在整理数据上的时间比调模型多得多。所以当我看到一套标注好的平面图元素识别数据集时第一反应就是把它拆开研究了个遍。这套数据覆盖24类常见要素冰箱、洗手台、窗户、餐桌、门、床都在其中模型识别率能做到97.4%并且同时导出了YOLO txt、COCO JSON、Pascal VOC XML三种主流标注格式。这意味着不管你是习惯YOLO系训练脚本还是用MMDetection这类开源训练框架甚至是用更传统的Faster R-CNN流程都能把这套数据直接接进自己的训练管线。这篇文章我会把数据集的标注逻辑、三种格式的转换细节、训练到97.4%识别率的调优过程以及落地时踩过的坑完整复盘给正在做户型图解析、智能家居、房产信息结构化的朋友一条可以直接照着走的路线。1. 平面图元素识别一张户型图上的目标检测博弈1.1 为什么通用目标检测模型搬到平面图上会失灵平面图元素识别从任务定义上就是标准的目标检测把户型图里的冰箱、床、洗手台、窗户等元素用矩形框或多边形框出来并给出类别标签。但真正上手后你会发现用现成目标检测模型跑一下这个思路基本走不通原因主要有三层。第一层是图像风格差异。日常生活中的照片是连续像素构成的有光影、纹理、材质信息而CAD导出的平面图是矢量风格背景是纯白家具和墙体靠线条和填充图案表示。模型在照片数据集上学到的纹理特征、边缘特征在平面图上完全对不上。这叫域偏移domain shift也是几乎所有跨场景目标检测任务的第一道坎。第二层是尺度极度不平衡。客厅里的双人沙发可能占整张图的10%以上而洗手台、马桶这些符号通常只有几十个像素有的小图标在整张图里不到0.5%。目标检测里的小目标问题在平面图上被放大得很明显用默认的训练配置小目标漏检率会非常高。第三层是类间语义歧义。门和窗户在很多图纸上都用矩形图例表示只是内部线条和位置不同冰箱和衣柜在平面图俯视图上也很像都是矩形加一点内部纹理。如果标注时框选范围不统一模型学到的基本就是矩形加矩形自然分不清。所以真正可用的平面图识别模型必须依赖专门标注的数据集且标注规范必须统一。这也是为什么一套高质量标注数据本身就是核心资产——算法架构可以抄数据只能自己一点一点攒。1.2 24类元素的选择工程上的黄金平衡点有人会问为什么是24类而不是20类或40类这个数字并不是拍脑袋定的而是综合标注成本、模型复杂度和下游需求之后的折中结果。从下游场景看室内设计自动化和房产信息结构化需要的最核心元素集中在床、沙发、餐桌、冰箱、洗衣机、马桶、洗手台、灶台、门窗、衣柜这个范围内。再往下细化比如区分双人床、单人床、子母床当然可以做但每种细分都需要成比例的训练样本否则类别一多类间混淆和样本不均衡的问题立刻爆发模型识别率会被拖下去。以我见过的一套完整标注体系为例24类标签大概会覆盖以下对象大类具体类别家具床、沙发、餐桌、椅子、衣柜、床头柜、电视柜、书桌、茶几家电与设备冰箱、洗衣机、空调、电视、灶台、水槽门窗结构门、窗户、飘窗、推拉门洁具马桶、洗手台、浴缸、淋浴房户型区域洗手间、厨房、阳台这套标签体系的取舍思路很实用把洗手间同时作为区域级类别保留和马桶、洗手台等物体级类别共存。这样做的好处是下游在做空间划分时可以直接利用区域框而做家具统计时再用物体框一套数据两处使用。1.3 拿到数据集后先把目录结构摸清楚数据集拿到手别急着开训先把目录结构摸清楚。一套规范的平面图元素识别数据集通常长这样floor_plan_dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── yolo/ │ │ ├── train/ │ │ ├── val/ │ │ └── test/ │ ├── coco/ │ │ └── annotations/ │ └── voc/ │ ├── train/ │ ├── val/ │ └── test/ ├── classes.txt └── data.yaml不同的训练框架对目录结构的要求差异很大。YOLO系要求images与labels同名对应、目录层级一致COCO格式则需要一个统一的json文件把train或val的图片和标注串起来Pascal VOC则是每张图对应一个xml文件。如果这些结构不一致最直接的后果就是训练时疯狂报错或者更隐蔽的数据一直没被正确加载模型看着训练指标在下降实际学到的全是噪声。我个人的习惯是拿到任何数据集都先用脚本统计每类的样本数、平均框尺寸和图片分辨率分布这三个指标能直接告诉你后面训练要重点处理什么问题。2. 数据准备阶段真正决定识别率上限的地方2.1 数据清洗先把脏乱差干掉标注数据集不是画框那么简单原始数据里什么问题都有。我们之前处理一批平面图时常见的情况包括重复图片、模糊的扫描件、缺少墙体线的残缺户型图、图片里混入了设计院的图签和标题栏。如果这些图不清理就直接进训练集轻则浪费算力重则让模型学到错误特征。一个可落地的清洗流程大概是这样的用脚本计算全量图片的感知哈希perceptual hash把重复图片找出来并保留质量最高的一份。对图片做尺寸和直方图分布统计找出模糊或异常曝光的图。平面图虽然是线条图但扫描进来的老图纸会有大量噪点这些噪点会被当成假边缘严重影响小目标检测效果。裁掉图签、标题栏等干扰区域。很多户型图右下角有设计院图签如果保留在训练图里模型可能会把图签误学成一种类别。最终的人工抽检至少看20%的清洗结果确认没有误删重要图纸。清洗这步没有太多算法含量但恰恰是它决定了数据集的干净程度。我见过不少团队忽略这一步结果训练出来模型在测试集上mAP看起来不低换到真实图纸上立刻崩原因就是训练集里混了太多带病样本。2.2 标注规范边界、遮挡和难例的取舍标注规范是数据集质量的命门。同一个元素两个人标注的结果可能差很远。比如窗户的框有人习惯框整扇窗的轮廓有人只框其中一侧的活动扇这两种框法喂给模型学习目标就不一致模型自然学不好。一套工程可行的标注规范至少要统一以下几点框选边界一律紧贴元素的可见外轮廓不允许把墙面、地面等背景大片包进来遮挡关系元素被家具遮挡时按最完整的可见部分来框不臆测缺失部分最小框尺寸小于一定像素比如10x10的标注框直接丢弃避免给模型输送过高噪声类别归属争议门和窗外观相近时以及推拉门和普通门难以区分时要预先定义好判定规则在数据集构建阶段我强烈建议做双人标注加交叉检查同一个批次让两个人分别标然后计算标注框的IoU一致性。常规做法是IoU大于0.7才算合格低于这个值的框重新标。这个成本虽然高但对识别率的提升远比换一个更大模型来得明显。2.3 类别不均衡小样本类别怎么办24类元素里床、沙发、餐桌这类样本量往往充足但浴缸、飘窗、淋浴房这些冷门类别的样本可能只有前者的十分之一。类别不均衡直接导致模型对少数类走向欠拟合预测时大多数都被宁可错杀也不识别。处理手段可以从数据侧和训练侧两头走。数据侧优先做少有类的复制增强对包含浴缸、飘窗这些类别的图片做左右翻转、小幅旋转、对比度扰动再重新生成标注文件。这个方法实现简单、见效快。训练侧则可以调整每个batch的采样权重让包含少数类的图片以更高概率被抽中或者给少数类的loss加一个更高的权重系数。需要注意一点如果平面图本身有明确的建筑方向比如指北针标注那么左右翻转这种增强要谨慎使用。因为镜像后的图纸可能不符合真实建筑朝向模型学出来的语义会受影响。折中方案是只做90度、180度的旋转少做镜像翻转。3. YOLO、COCO JSON、Pascal VOC XML三种标注格式转换实操3.1 三种格式的核心区别一张表说清楚一套数据同时提供YOLO txt、COCO JSON、VOC XML三种格式本质上是为了适配不同训练框架。要熟练使用先得把它们的字段结构记牢格式存储方式核心字段主流适配框架YOLO txt每张图对应一个txtclass_id center_x center_y width height归一化YOLO各版本、部分自定义训练脚本COCO JSON一个json文件描述整套标注images、annotations、categoriesMMDetection、Detectron2等Pascal VOC XML每张图对应一个xmlfolder、filename、object/name、object/bndbox传统检测流程、部分框架的VOC模式关键点在YOLO的坐标是归一化值取值0到1而VOC里是绝对像素坐标xmin、ymin、xmax、ymaxCOCO的bbox则是左上角x、左上角y、宽、高的绝对像素表示。格式之间的转换核心就是这三套坐标系之间的换算。3.2 一套可复用的格式转换脚本思路标完一组数据最终都会落到不同训练管线里所以格式转换脚本是刚需。以最常见的VOC格式转YOLO格式为例思路是把XML里的bndbox绝对坐标读出来再根据图片实际宽高换算成归一化坐标import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, output_dir, class_to_id, img_width, img_height): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_to_id: continue xmin float(obj.find(bndbox/xmin).text) ymin float(obj.find(bndbox/ymin).text) xmax float(obj.find(bndbox/xmax).text) ymax float(obj.find(bndbox/ymax).text) center_x ((xmin xmax) / 2) / img_width center_y ((ymin ymax) / 2) / img_height w (xmax - xmin) / img_width h (ymax - ymin) / img_height lines.append(f{class_to_id[name]} {center_x:.6f} {center_y:.6f} {w:.6f} {h:.6f}) out_path os.path.join(output_dir, os.path.splitext(os.path.basename(xml_path))[0] .txt) with open(out_path, w) as f: f.write(\n.join(lines))用的时候要传入每张图真实的宽高。这一步有个细节平面图扫描件在预处理时可能被resize过resize前后的宽高不一样一定要以标注工具里看到的实际显示尺寸为准。如果拿原始大图的宽高去归一化所有框的坐标都会整体偏移。COCO格式转YOLO也类似核心是从annotations里取image_id对应的图片宽高再把annotation中的bbox从(x, y, w, h)换算成归一化的中心点表示。反过来YOLO转VOC则要把归一化坐标乘回图片宽高再转成xmin、ymin、xmax、ymax。平时建议把这三套转换脚本写成一个小工具库以后换数据集直接用。3.3 转换中最容易翻车的三件事第一件坐标归一化时除以错误的图片尺寸。有些平面图扫描件导入标注工具后会被自动resize标注坐标基于的是resize后的尺寸而不是原图的尺寸。如果转换脚本里用了原图尺寸所有框的坐标都会漂移。第二件类别ID不一致。YOLO用的是classes.txt里的行号VOC用的是XML里的name字符串。从VOC转YOLO时如果class_to_id没有对齐等于把所有框都标成了错误类别训练时loss照样下降但识别结果全乱。这属于最难发现的故障之一。第三件图片和标注文件命名对不上。YOLO和VOC都是同名对应一旦文件名多了空格、后缀大小写不一致训练时图片被忽略也不报错。排查的最快方式是脚本对比images目录和labels目录的文件集合看有没有缺失。4. 从0到97.4%模型训练与调优全过程4.1 模型选型为什么优先看YOLO系列数据准备的充分程度决定了模型识别的上限模型选型决定的是离上限有多近。在平面图元素识别这个场景里我首推YOLO系列原因很实际训练链路短、部署方便、社区方案多且小目标表现相对均衡。如果项目对精度要求更高也可以选择基于检测框架的Faster R-CNN或Mask R-CNN——后者还能顺便输出分割掩码在做平面图区域划分时非常有用。但要注意高精度模型的训练成本和推理速度都要上一个台阶。以YOLO系模型为例面对24类平面图元素我常规的选型顺序是先拿YOLOv8s做基线跑通全流程并拿到一个可对比的mAP如果速度有余量、精度不足再换YOLOv8m或放大输入分辨率如果精度满意但速度不达标再退回更小的模型并配合推理优化。4.2 训练参数不同配置怎么定训练参数没有统一的神奇组合但有几组基础配置是经过大量项目检验的输入尺寸imgsz默认640但如果平面图分辨率普遍较大、小目标较多可以尝试960或1280。输入尺寸变大小目标检测效果立竿见影代价是显存占用和训练时间上升。batch size通常8或16显存不够就梯度累积。batch对最终精度的影响没有想象中大但会明显影响训练稳定性和收敛速度。训练轮数epochs前100轮大概能看到模型收敛趋势一般200到300轮比较稳。具体以验证集mAP不再上升且验证loss开始反弹为准。优化器与学习率SGD配线性warmup是稳妥的组合AdamW则收敛更快。学习率不需要单独精调用默认值配合warmup即可。data.yaml的核心配置是类别数和路径映射。如果数据集目录结构和训练脚本预期不一致即使模型代码完全没改也可能在训练时静默地只加载了部分数据。判断方法很简单训练第一个epoch时打印每个batch里图片的路径确认路径中都包含train目录而不是误加载了val的图片。4.3 从90%到97.4%最难啃的往往是准确率上限很多人以为97.4%的识别率是换个大模型换出来的实际并不是。从我的经验看从90%提升到97.4%主要靠的是以下三件小事第一件是精细化标注复查。精度卡在90%左右时去看错误的预测结果会发现很大一部分是标注本身的问题某个窗户只有半个框被标了、某张图的冰箱类别标错成了衣柜。把标注错误修正一遍后mAP往往能直接提升2到3个百分点。第二件是难例挖掘。把当前模型预测出错最多的图片挑出来人工分析模型到底在哪些元素上犯错。如果是把门预测成窗户就重点检查门和窗户的标注边界如果是洗手台预测成灶台就要考虑这两个类别是否在俯视图上严重相似必要时合并或增加更细的子类规则。第三件是测试集统计口径的保持。训练过程中的mAP要始终在相同的验证集上算不要随意增删验证集图片。如果验证集换来换去模型明明在变好mAP却在下降这种假退步会浪费大量调参时间。97.4%这个数字之所以有参考价值是因为它大概率是在一个难度适中、样本分布合理的验证集上获得的。如果验证集里都是相似风格的图纸识别率做到99%也不奇怪但这些数字放到真实多样图纸上会立刻缩水。所以在评估数据集的识别率时一定要搞清楚验证集构成看它是否覆盖了多种户型图风格、多种分辨率、多种年代图纸。5. 落地场景与高频问题排查实录5.1 室内设计自动化户型图解析是第一环节平面图元素识别最直接的应用场景是室内设计自动化。传统室内设计流程里设计师拿到一张户型图后需要手动量尺寸、识别门窗位置、规划家具摆放。这个环节耗时且容易出错。接入元素识别模型后系统可以自动完成第一轮解析床的位置、沙发的位置、门窗的开口方向都直接变成结构化数据设计师只需要在自动解析结果上做修改。我做过的一个模拟项目里整个流程是这样的输入一张JPG户型图调用模型推理得到所有元素的bbox和类别把类别为门窗户的框提取出来结合墙体线算法判断开口方向和空间连通性再把床沙发餐桌这些家具框映射到预设的家具库自动生成一个带尺寸的布局草稿。这个流程里元素识别的精度直接决定了后续所有步骤的质量。5.2 房产信息结构化与智能家居的联动另一个很典型的场景是房产平台的信息结构化。房源描述里的户型图大多是图片无法直接搜索三居室、南北通透、有浴缸这种条件。如果先把户型图自动解析成结构化数据就可以支持按户型特征搜索房源甚至把户型图和房价数据做关联分析。智能家居方向也很有意思。拿到户型的自动识别结果后可以自动规划扫地机器人的清扫区域、判断哪些墙面适合安装传感器、或者估算铺地板和刷墙的面积。这些下游应用本质上都依赖同一件事模型能从平面图上稳定识别出正确的元素及其位置。需要注意上面这些场景里单纯识别出冰箱在图片左上角是不够的还需要把像素坐标换算成真实世界的相对位置。如果数据集标注时没有保存图片的DPI或比例尺信息这一步会比较痛苦。所以我在标注平面图数据集时会额外为每张图记录一个像素与真实厘米的换算比例哪怕只是粗略估算也能让下游空间计算变得可行。5.3 高频问题速查表最后整理一个高频问题速查表都是我实际踩过或帮别人排查过的可以直接对照使用问题现象可能原因排查与解决训练正常但识别率低标注框坐标漂移抽查标注可视化对比原图门和窗户互相误判类别标注边界不统一统一标注规则检查难例小目标元素完全漏检输入分辨率过低提高imgsz切图训练验证loss下降但mAP不升验证集过难或标注不干净复查验证集标注统一统计口径冰箱和衣柜混淆俯视图外观相似增加子类或合并类别推理速度不够模型过大或输入过大用更小模型加量化推理换机后验证集mAP骤降数据加载顺序或增强随机性固定随机种子校验数据路径排查时一定要记住先查数据再查代码最后才动模型。大多数识别率不达标的问题最终都会定位到数据上而不是算法上。这套标注好、且同时兼容三种格式的平面图元素识别数据集对我来说最大的价值不是直接拿去训练而是提供了一个可以对照的标杆类别体系怎么定、标注规范怎么写、坐标换算要注意什么、调优该往哪个方向使劲。我个人的体会是平面图元素识别这个方向真正拉开差距的从来不是模型结构而是数据准备的工程细节。如果你手头也有一批平面图建议先按这套思路把类别体系和标注规范定下来然后跑通一次完整的格式转换加训练流程之后再谈精度优化。最后分享一个小技巧标注完成的平面图数据集一定要随机抽出10%左右的图逐一可视化预测结果并人工复核这一步看着笨但它是阻止训练集脏数据悄悄污染模型的最有效防线。

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

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

免费获取报价 →
↑