本文是前三个文档(图形识别、线框图识别、三维识别)的「极简入门版」: 讲原理、看图表、只给难点核心代码、附开源基线链接,目标是 30 分钟内建立整体认知。 完整代码与图见各分册;本文聚焦「一看就懂」。


1. 一张图看懂整体流水线

图形识别的本质:把"看形状"变成"数学参数匹配 + 断点缝合 + 拓扑推理"。 从 2D 到 3D,一条流水线贯穿五个环节:

从2D到3D的图形理解流水线
从2D到3D的图形理解流水线

环节输入干的事核心算法
拆线二值图像提取顶点坐标Douglas-Peucker
分类顶点序列判定几何类型边数、夹角、曲率
识别含噪/断裂点集检出目标并还原参数霍夫投票、RANSAC
拓扑基本图元理解结构(房间/符号)最小环、子图同构
3D 重建一张或多张图恢复深度与实体三角测量、消失点、B-rep

一句话记住:拆线 → 分类 → 识别解决"看到什么",拓扑 → 3D 解决"是什么结构、在空间里怎样"。


2. 霍夫变换:断裂线怎么「缝合」

要解决的问题:一条直线断成 10 段,连通域方法会认成 10 个碎片。

核心思想(投票):每个像素点向"可能经过它的所有直线"投票,投到参数空间 (角度 θ × 距离 ρ)。同一条直线的碎片,会投到同一个参数格子——那里出现一个 投票峰值。检测峰值 = 找回这条直线,无视断裂。

霍夫变换原理: 从断裂碎片到参数空间峰值
霍夫变换原理: 从断裂碎片到参数空间峰值

难点核心代码(原理 5 行,实际用 OpenCV 一行):

Python
# OpenCV 概率霍夫变换: 输入边缘图, 输出线段
lines = cv2.HoughLinesP(edges, rho=1, theta=np.pi/180, threshold=100,
                        minLineLength=50, maxLineGap=10)   # maxLineGap=缝合断口
参数含义调大/调小
threshold投票阈值大→只留强直线;小→碎片也保留
minLineLength最小线段长度过滤短噪声线
maxLineGap允许的最大断口缝合断裂的关键

圆检测用 cv2.HoughCircles(霍夫梯度法),思路相同:梯度方向 → 圆心空间投票。


3. RANSAC:怎么无视离群点

要解决的问题:图纸上有大量无关交叉线/噪点,最小二乘会被它们带偏。

核心思想(采样 + 一致性检验):反复随机抽最少点数(直线 2 点、圆 3 点)拟合 候选模型,统计"有多少点落在容差带内"(内点数),保留内点最多的模型。离群点 再怎么多,也形不成一致的模型。

RANSAC 思想: 采样-拟合-内点计数
RANSAC 思想: 采样-拟合-内点计数

难点核心代码(sklearn 一行搞定):

Python
ransac = linear_model.RANSACRegressor(random_state=42)
ransac.fit(X, y)                      # X 含 25% 离群点也能稳
mask = ransac.inlier_mask_            # 自动分出内点/外点

圆拟合同理:skimage.measure.ransac(points, CircleModel, 3, residual_threshold=10)。

工业惯例:霍夫粗检测定位候选区域 → RANSAC 在区域内精拟合,得到亚像素级参数。


4. 拓扑识别:怎么从边认出「面」和「房间」

要解决的问题:复杂图形(法兰盘、建筑平面图)是组合图形,单靠几何不够。

核心思想(图论): 1. 提取线段 = 图的「边」,求交点 = 图的「顶点」; 2. 在线段途径的所有顶点处打断成多条边,构建属性邻接图; 3. 最小环基 / 四边形环 = 围成的"房间"或"面"; 4. 子图同构 = 在图中查找与标准符号模板一致的局部结构。

难点核心代码(两个关键片段):

Python
import networkx as nx
# (a) 识别"面/房间": 枚举四边形环
quad_cycles = {frozenset(c) for c in nx.simple_cycles(DG) if len(c) == 4}

# (b) 子图同构匹配标准符号(带边长比例校验)
matcher = nx.algorithms.isomorphism.GraphMatcher(G_img, template, edge_match=edge_match)
matches = list(matcher.subgraph_isomorphisms_iter())

验证常识:一个长方体(12 边 8 顶点)恰好有 6 个四边形环 = 6 个面。


5. 三维识别:怎么从 2D 变 3D

要解决的问题:平面线框是 3D 物体的投影,丢掉了 Z 轴深度,还产生大量 "视觉伪交点"(2D 交叉、3D 并不相交)。

核心思想(点→线→面→体):

层次从 2D 到 3D 的方法
点多视图三角测量(对极几何/视差)或单目深度估计(Depth Anything)
线消失点反向投影;拓扑一致性校验破除伪交点
面图论找闭合环 + 最小二乘平面拟合校验共面性
体法向朝外的封闭面组合为 B-rep;或深度学习直接生成体素/隐式 SDF

难点核心代码(DLT 三角化,这是 3D 中最值得记的 6 行):

Python
def triangulate(P1, P2, u1, u2):          # P=投影矩阵, u=两视图同名点
    A = np.array([u1[0]*P1[2]-P1[0], u1[1]*P1[2]-P1[1],
                  u2[0]*P2[2]-P2[0], u2[1]*P2[2]-P2[1]])
    _, _, Vt = np.linalg.svd(A)           # 解 AX=0
    X = Vt[-1]
    return X[:3] / X[3]                   # 齐次归一化得 3D 点

6. Baseline 开源链接速查表

均为广泛使用、可放心引用的官方仓库;「用途」栏标注与本文哪一层对应。

用途(本文对应层)仓库说明
通用图像处理/霍夫变换(识别)opencv/opencvHoughLinesP、HoughCircles、Canny 都在这里
稳健拟合/RANSAC(识别)scikit-image/scikit-imageransac、CircleModel、LineModelND
最小环/子图同构(拓扑)networkx/networkxminimum_cycle_basis、GraphMatcher、simple_cycles
线框解析深度学习基线(拓扑/线框)zhou13/LCNN点线双任务解析,Wireframe 数据集基线
线框解析进阶基线(拓扑/线框)GrumpyZhou/HAWPHolistically-Attracted Wireframe Parsing
单目深度估计(3D·点)DepthAnything/Depth-Anything-V2单张图直接预测深度图
点云/3D 几何处理(3D)isl-org/Open3D点云→平面/网格、配准、重建
2D 图→3D 生成基线(3D·体)VAST-AI-Research/TripoSR单张图→3D 网格,图像转 3D 主流基线
多视图→3D 生成(3D·体)3DTopia/LGMLarge Multi-View Gaussian Model
文本/图→3D(3D·体,AIGC)ashawkey/stable-dreamfusion扩散模型驱动的 3D 生成
B-rep/实体建模内核(3D·体)Open-Cascade-SAS/OCCT工业级边界表示法内核(OpenCascade)

选型建议:逆向工程/精度优先走传统路线(OpenCV + skimage + networkx + Open3D + OCCT); AIGC 内容生成走深度学习路线(HAWP/L-CNN 做线框、Depth Anything 做深度、TripoSR/LGM 生成体)。


7. 给新手的学习路线

  1. 第 1 天:跑通本文 2、3 节两行代码(OpenCV 霍夫 + sklearn RANSAC),用自带示例图看效果。
  2. 第 2 天:理解 4 节图论——用 networkx 对立方体求 6 个面(code/demo8_box_faces.py)。
  3. 第 3 天:看 5 节 DLT 三角化,跑 code/demo7_triangulation.py 验证重建误差。
  4. 进阶:切到对应开源仓库,读 README 的「Quick Start」复现 Wireframe 数据集的 L-CNN/HAWP 基线。

全套可运行示例与图在:code/demo0_demo9*.py + figures/,分册详见 图形识别-经典示例与代码.md、线框图识别-经典示例与代码.md、三维识别-经典示例与代码.md。


⚠️ 说明:本文以原理与图表为主,代码仅保留难点核心片段;全部可运行脚本 见 code/ 目录(demo0_principles.py 生成本文示意图)。