每次拿到一套CAD图纸,我脑子里第一个冒出来的念头就是:这套图纸到底有多少信息是结构化的?
图层命名规范的设计院,图层里存着完整的设计数据;图层命名混乱的图纸,连哪根线是墙哪根线是管都要靠猜。
今天聊的是CAD图纸自动识别——不是把DWG转成图片,不是OCR识别,而是 从DWG文件的底层数据结构里,把图纸信息一层层挖出来

一、CAD图纸识别的三个技术层级

很多人以为CAD识别就是"CAD转图片然后OCR识别",这是一个严重的误解。

CAD文件(DWG格式)本质上是结构化的矢量数据库,它存储了比图像多得多的信息。一个标准的DWG文件包含:

数据层

内容

可用性

图形数据

线条、弧线、多段线、填充的坐标信息

几何计算基础

图层结构

图层名称、线型、颜色、线宽

构件分类基础

图块数据

Block定义、属性值(Attribute)、扩展数据(XDATA)

规格信息提取

文字数据

单行文字、多行文字内容及位置

标注识别基础

扩展数据

设计院自定义的业务字段

高价值结构化数据

所谓CAD图纸识别,就是逐层解析这些数据,并结合AI视觉模型补充图形层面的信息。

技术实现上,分为三个层级:

 

CAD图纸识别三层架构 第一层:DWG文件结构解析 ├── 文件头解析(DWG版本、编码、对象表) ├── 实体遍历(Entity traverse,按Handle逐个读取) ├── 图层表读取(Layer table,获取所有图层及属性) ├── 图块表读取(Block table,获取所有图块定义) └── 文字表读取(Text style table,字体映射) 第二层:图形视觉识别 ├── 线条几何分类(墙体/管线/轮廓) ├── 空间关系推理(包含、相邻、平行判断) ├── 填充区域检测(房间边界、面积区域) └── 比例尺与单位解析 第三层:语义理解与结构化输出 ├── 构件语义分类(门窗/墙体/设备/管线) ├── 属性字段映射(将原始属性映射为标准字段) ├── 几何参数计算(面积/长度/高度) └── 数据校验与异常检测


二、第一层:DWG文件结构解析

2.1 从文件头开始

DWG文件不是透明的二进制格式,不同版本(DWG 2013/2018/2024)的文件结构差异很大。解析的第一步是识别版本,然后按版本对应的文件结构读取对象表。

AutoCAD的DWG文件结构大致如下:

 

DWG File Structure ├── File Header(文件头) │ ├── 版本标识(ACxxxx) │ ├── 编码信息 │ ├── 缩略图数据(可选) │ └── 预览图像偏移量 ├── Class Definitions(类定义表) ├── Object Map(对象索引表) ├── Handles Dictionary(句柄字典) └── Object Data(对象数据区) ├── Entities Section(实体区:图形对象) ├── Tables Section(表区:图层/线型/文字样式等) ├── Blocks Section(图块区:Block定义) └── Objects Section(其他对象)

解析过程中,最核心的是实体区(Entities Section)和图层表(Layer Table)。实体区存放了所有图形对象(线条、弧线、文字、填充等),图层表存放了每个图层的名称和属性。

 

# DWG实体解析示意(伪代码) def parse_entities(file): entities = [] # 读取实体区起始位置 entities_start = file.get_section_offset("ENTITIES") # 逐个读取实体对象 current_pos = entities_start while current_pos < entities_end: entity = read_entity_header(file, current_pos) if entity.type == "LINE": data = parse_line_entity(file, entity) elif entity.type == "LWPOLYLINE": data = parse_polyline_entity(file, entity) elif entity.type == "INSERT": data = parse_block_insert(file, entity) # 图块插入 elif entity.type == "MTEXT": data = parse_mtext_entity(file, entity) # 多行文字 elif entity.type == "HATCH": data = parse_hatch_entity(file, entity) # 填充区域 data.layer = entity.layer # 关联图层信息 data.handle = entity.handle # 唯一句柄 entities.append(data) current_pos = entity.next_offset return entities

2.2 图层表:信息的第一个过滤器

图层表(Layer Table / Layer Table Record)存储了所有图层的元数据。设计院在绘图时,会把不同类型的构件放到不同图层里——虽然命名规范参差不齐,但图层本身就是第一层分类依据。

 

# 图层表读取示意(伪代码) def parse_layer_table(file): layers = {} # 获取图层表在文件中的位置 layer_table_handle = file.header.layer_table_handle # 读取图层表对象 layer_table = file.resolve_handle(layer_table_handle) for record in layer_table.records: layer_name = record.name.decode("utf-8", errors="ignore") layer_color = record.color # ACI颜色索引 layer_linetype = record.linetype # 线型 layer_lineweight = record.lineweight # 线宽 layer_flags = record.flags # 图层状态标志 layers[layer_name] = { "name": layer_name, "color": layer_color, "linetype": layer_linetype, "lineweight": layer_lineweight, "is_off": bool(layer_flags & 0x01), # 是否隐藏 "is_frozen": bool(layer_flags & 0x02) # 是否冻结 } return layers

这一步的价值在于:即便设计院的图层命名不规范,也能通过图层颜色+线型+线宽的组合特征,对图层进行语义分类。

2.3 图块属性:图纸里藏着的结构化数据

很多设计院在绘图时,会用**属性图块(Attribute Block)**来标注构件规格。比如门窗图块里会包含:

  • 门窗编号(如"M0921")

  • 门窗类型(如"推拉门")

  • 洞口尺寸(如"900×2100")

  • 材质信息(如"铝合金")

这些信息在图块属性里存着,但肉眼打开CAD时往往只看到图块图形,看不到属性值——而属性值往往就是你要提取的数据。

 

# 图块属性提取示意(伪代码) def extract_block_attributes(file, block_ref): # block_ref 是图块插入点(INSERT entity) block_name = block_ref.block_name # 图块名称,如"WINDOW_铝合金推拉门" # 获取图块定义 block_def = file.get_block_definition(block_name) attributes = {} # 遍历图块内的属性定义(Attribute Definition) for attr_def in block_def.attribute_definitions: field_name = attr_def.tag # 属性标签,如"WIDTH"、"HEIGHT" prompt = attr_def.prompt # 属性提示,如"请输入宽度" # 找到图块引用中对应的属性值 attr_value = block_ref.get_attribute_value(field_name) if attr_value: attributes[field_name] = { "value": attr_value, "prompt": prompt, "position": attr_def.position, "style": attr_def.text_style } return { "block_name": block_name, "position": block_ref.position, "rotation": block_ref.rotation, "scale": block_ref.scale, "attributes": attributes }

这一步是CAD图纸识别里信息密度最高的一步——设计院通过属性图块存的规格数据,往往比图纸上的标注文字更准确、更结构化。


三、第二层:图形视觉识别

3.1 线条分类:从几何到语义

有些图纸里,图块用得不多,大量构件还是用普通线条画的。这种情况下,需要通过几何特征来判断线条是什么构件。

 

# 线条构件分类示意(伪代码) def classify_entity(entity, layers, context): layer_name = entity.layer geometry = analyze_geometry(entity) # 规则一:图层名语义映射 if is_architectural_layer(layer_name): return classify_by_architectural_rules(entity, geometry) # 规则二:几何特征判断 if is_closed_loop(entity) and has_parallel_pairs(entity): # 封闭图形+有平行边对 → 可能是门窗洞口 return classify_door_window(entity, geometry) if is_filled_region(entity) and is_large_area(entity): # 大面积填充 → 可能是房间或功能区域 return classify_room(entity, geometry) # 规则三:空间上下文推理 nearby_entities = context.get_nearby(entity, radius=100) for nearby in nearby_entities: if nearby.is_window() and entity.near(nearby): return "窗台下墙" return classify_by_geometry(geometry)

3.2 填充区域:房间边界的识别

建筑CAD图纸里,房间边界通常用填充(Hatch)来表示。识别填充区域的边界,可以提取房间面积、功能分区等关键数据。

填充识别有两个难点:

  1. 填充边界可能由多段线条组成,需要追踪每段线条的端点,构建完整的多边形

  2. 嵌套填充(填充里套着另一个填充)需要分层处理

 

# 房间填充区域提取(伪代码) def extract_room_boundaries(file): rooms = [] for hatch_entity in file.entities.filter(type="HATCH"): # 获取填充的边界路径 boundary_paths = hatch_entity.get_boundary_paths() # 每一层边界路径构成一个闭合多边形 for path in boundary_paths: if path.is_outer(): # 外边界 = 房间轮廓 vertices = trace_boundary(path) area = calculate_polygon_area(vertices) # 获取房间名称(通常在填充中心有文字标注) center = calculate_centroid(vertices) room_label = find_text_at(file, center, radius=50) rooms.append({ "boundary": vertices, "area": area, "label": room_label, "layer": hatch_entity.layer }) return rooms


四、第三层:语义理解与结构化输出

4.1 构件语义分类

几何识别解决的是"这根线条是什么形状",语义分类解决的是"这个形状代表什么构件"。

建筑图纸里的构件分类体系,参考《房屋建筑制图统一标准》GB/T 50001-2017:

构件类别

常见图层名关键词

几何特征

墙体

WALL, Q, Q_*, 砌体

连续平行线对,间距60-400mm

门窗

DOOR, WINDOW, M, C, MC

封闭矩形,内部门窗线

柱子

COLUMN, Z, ZH

矩形或圆形封闭图形

BEAM, L, GL

与墙体平行或垂直

楼梯

STAIR, LT

踏步等距线+箭头

设备

EQUIP, EQ, SB

图块,规格在属性里

4.2 数据标准化与输出

提取的原始数据需要映射到标准字段,才能被下游系统使用。

 

# 构件数据标准化输出(伪代码) def normalize_to_standard_format(raw_data): output = [] for entity in raw_data: normalized = { "id": generate_uuid(), "category": map_to_standard_category(entity.type), "layer": entity.layer_original, "position": { "x": entity.position.x, "y": entity.position.y, "z": entity.position.z or 0 }, "geometry": { "type": entity.geometry_type, "area": entity.area if hasattr(entity, 'area') else None, "length": entity.length if hasattr(entity, 'length') else None, "dimensions": entity.dimensions }, "attributes": normalize_attributes(entity.attributes), "confidence": entity.classification_confidence, "source_file": entity.source_file } output.append(normalized) # 导出为结构化格式 return { "version": "1.0", "export_time": get_current_timestamp(), "total_entities": len(output), "categories": group_by_category(output), "data": output }


五、真实项目数据

项目背景:某机电安装工程,工程量清单编制阶段需要从设计院提供的暖通CAD图纸中提取设备型号、数量、安装位置,共约60张系统图和平面图。

处理结果

指标

传统方式(人工读取)

BeesFPD CAD解析

60张图纸耗时

约8-10小时

约40分钟

数据格式

人工录入,格式不统一

标准化构件清单

错误率

约3-5%

低于1%

数据可用性

整理后才能使用

可直接导入算量软件

周期节省

约7小时/批次


六、技术边界说明

能做:

  • 标准图层命名图纸的批量结构化解析

  • 属性图块(Attribute Block)规格信息提取

  • 填充区域(房间面积)自动计算

  • 多图层、多比例图纸批量处理

  • 数据导出为Excel、CSV、JSON格式

不能(目前阶段):

  • 非标准图层命名图纸的完全自动分类(需要人工辅助映射)

  • 复杂曲线构件(如渐变曲线、参数化构件)的精确提取

  • 直接生成完整的BIM模型(这是Revit的工作,不是CAD解析的工作)


七、工具与规范参考

工具:元启数宇BeesFPD图纸解析系统

在线使用,无需安装:www.beesfpd.com

支持DWG 2013及以上版本,支持批量上传和结构化数据导出。

参考规范

  • GB/T 50001-2017《房屋建筑制图统一标准》

  • GB/T 50104-2010《建筑制图标准》

  • GB/T 50106-2010《建筑给水排水制图标准》

  • JGJ/T 244-2011《房屋建筑修缮工程图纸数字化标准》


结语

CAD图纸识别这件事,真正的价值不在于"识别"本身,而在于把散落在DWG文件里的结构化数据提取出来——属性图块里的规格信息、图层里的设计意图、填充区域里的面积数据。

这些数据本来就在图纸里,只是以前要靠人眼去找、人手去录。AI做的是把这件事变成批量自动化的。

下次拿到一套CAD图纸,别急着打开AutoCAD,让解析引擎先跑一遍,看看能挖出多少你不知道的数据。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐