graph LR subgraph 三维世界 P["物体点P(X,Y,Z)"] end subgraph 相机系统 O["光心O"] F["图像平面"] end subgraph 成像结果 P2["像点p(u,v)"] end P -->|光线| O O -->|投影| P2 classDef worldNode fill:#5c6bc0,stroke:#3949ab,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px classDef cameraNode fill:#26a69a,stroke:#00897b,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px classDef imageNode fill:#ec407a,stroke:#d81b60,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px classDef worldSubgraph fill:#e8eaf6,stroke:#3949ab,stroke-width:2px,color:#283593,font-weight:bold classDef cameraSubgraph fill:#e0f2f1,stroke:#00897b,stroke-width:2px,color:#00695c,font-weight:bold classDef imageSubgraph fill:#fce4ec,stroke:#d81b60,stroke-width:2px,color:#ad1457,font-weight:bold class P worldNode class O,F cameraNode class P2 imageNode class 三维世界 worldSubgraph class 相机系统 cameraSubgraph class 成像结果 imageSubgraph linkStyle 0 stroke:#5c6bc0,stroke-width:2px,stroke-dasharray:5 5 linkStyle 1 stroke:#ec407a,stroke-width:2px
graph LR
subgraph 三维世界
P["物体点P(X,Y,Z)"]
end
subgraph 相机系统
O["光心O"]
F["图像平面"]
end
subgraph 成像结果
P2["像点p(u,v)"]
end
P -->|光线| O
O -->|投影| P2
classDef worldNode fill:#5c6bc0,stroke:#3949ab,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
classDef cameraNode fill:#26a69a,stroke:#00897b,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
classDef imageNode fill:#ec407a,stroke:#d81b60,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
classDef worldSubgraph fill:#e8eaf6,stroke:#3949ab,stroke-width:2px,color:#283593,font-weight:bold
classDef cameraSubgraph fill:#e0f2f1,stroke:#00897b,stroke-width:2px,color:#00695c,font-weight:bold
classDef imageSubgraph fill:#fce4ec,stroke:#d81b60,stroke-width:2px,color:#ad1457,font-weight:bold
class P worldNode
class O,F cameraNode
class P2 imageNode
class 三维世界 worldSubgraph
class 相机系统 cameraSubgraph
class 成像结果 imageSubgraph
linkStyle 0 stroke:#5c6bc0,stroke-width:2px,stroke-dasharray:5 5
linkStyle 1 stroke:#ec407a,stroke-width:2px
图11.1:针孔相机模型展示了光线通过光心投射到图像平面的几何关系
Code
graph TD A["世界坐标系<br/>(Xw, Yw, Zw)"] -->|旋转R + 平移t| B["相机坐标系<br/>(Xc, Yc, Zc)"] B -->|透视投影<br/>除以Zc| C["归一化坐标系<br/>(x, y)"] C -->|内参矩阵K<br/>fx, fy, cx, cy| D["像素坐标系<br/>(u, v)"] subgraph 外参变换 E["刚体变换<br/>6个自由度"] end subgraph 内参变换 F["传感器特性<br/>4个参数"] end A -.-> E C -.-> F classDef coordNode fill:#42a5f5,stroke:#1565c0,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px classDef paramNode fill:#9c27b0,stroke:#6a1b9a,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px classDef extSubgraph fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,font-weight:bold classDef intSubgraph fill:#f3e5f5,stroke:#6a1b9a,stroke-width:2px,color:#4a148c,font-weight:bold class A,B,C,D coordNode class E,F paramNode class 外参变换 extSubgraph class 内参变换 intSubgraph linkStyle 0 stroke:#1565c0,stroke-width:2px linkStyle 1 stroke:#0097a7,stroke-width:2px linkStyle 2 stroke:#ad1457,stroke-width:2px linkStyle 3,4 stroke:#6a1b9a,stroke-width:1.5px,stroke-dasharray:3 3 %% 移除渐变定义,使用单色填充
graph TD
A["世界坐标系<br/>(Xw, Yw, Zw)"] -->|旋转R + 平移t| B["相机坐标系<br/>(Xc, Yc, Zc)"]
B -->|透视投影<br/>除以Zc| C["归一化坐标系<br/>(x, y)"]
C -->|内参矩阵K<br/>fx, fy, cx, cy| D["像素坐标系<br/>(u, v)"]
subgraph 外参变换
E["刚体变换<br/>6个自由度"]
end
subgraph 内参变换
F["传感器特性<br/>4个参数"]
end
A -.-> E
C -.-> F
classDef coordNode fill:#42a5f5,stroke:#1565c0,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
classDef paramNode fill:#9c27b0,stroke:#6a1b9a,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
classDef extSubgraph fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,font-weight:bold
classDef intSubgraph fill:#f3e5f5,stroke:#6a1b9a,stroke-width:2px,color:#4a148c,font-weight:bold
class A,B,C,D coordNode
class E,F paramNode
class 外参变换 extSubgraph
class 内参变换 intSubgraph
linkStyle 0 stroke:#1565c0,stroke-width:2px
linkStyle 1 stroke:#0097a7,stroke-width:2px
linkStyle 2 stroke:#ad1457,stroke-width:2px
linkStyle 3,4 stroke:#6a1b9a,stroke-width:1.5px,stroke-dasharray:3 3
%% 移除渐变定义,使用单色填充
def camera_calibration_core(object_points, image_points):"""相机标定核心算法逻辑"""# 1. 构建齐次线性方程组:每个点对应两个约束方程 A = []for (X, Y, Z), (u, v) inzip(object_points, image_points):# 投影方程的线性化:u = (p11*X + p12*Y + p13*Z + p14) / (p31*X + p32*Y + p33*Z + 1) A.append([X, Y, Z, 1, 0, 0, 0, 0, -u*X, -u*Y, -u*Z, -u]) A.append([0, 0, 0, 0, X, Y, Z, 1, -v*X, -v*Y, -v*Z, -v])# 2. SVD求解最小二乘问题:Ah = 0 U, S, Vt = np.linalg.svd(np.array(A)) h = Vt[-1, :] # 最小奇异值对应的解# 3. 重构投影矩阵并分解得到内外参 P = h.reshape(3, 4) K, R, t = decompose_projection_matrix(P)return K, R, t
Code
flowchart TD A["采集标定图像<br/>多个角度的棋盘格"] --> B["提取角点坐标<br/>亚像素精度"] B --> C["建立对应关系<br/>3D世界点 ↔ 2D图像点"] C --> D["构建线性方程组<br/>Ah = 0"] D --> E["SVD求解<br/>最小二乘解"] E --> F["分解投影矩阵<br/>提取内参和外参"] F --> G["非线性优化<br/>最小化重投影误差"] G --> H["畸变参数估计<br/>径向和切向畸变"] H --> I["标定结果验证<br/>重投影误差分析"] subgraph 数据准备 A B C end subgraph 线性求解 D E F end subgraph 非线性优化 G H end subgraph 结果验证 I end %% 移除渐变定义,使用单色填充 classDef prepNode fill:#42a5f5,stroke:#1565c0,color:white,stroke-width:2px,font-weight:bold,border-radius:8px classDef solveNode fill:#ffb74d,stroke:#e65100,color:white,stroke-width:2px,font-weight:bold,border-radius:8px classDef optNode fill:#66bb6a,stroke:#1b5e20,color:white,stroke-width:2px,font-weight:bold,border-radius:8px classDef valNode fill:#f48fb1,stroke:#880e4f,color:white,stroke-width:2px,font-weight:bold,border-radius:8px classDef prepSubgraph fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,font-weight:bold classDef solveSubgraph fill:#fff3e0,stroke:#e65100,stroke-width:2px,color:#bf360c,font-weight:bold classDef optSubgraph fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px,color:#1b5e20,font-weight:bold classDef valSubgraph fill:#fce4ec,stroke:#880e4f,stroke-width:2px,color:#880e4f,font-weight:bold class A,B,C prepNode class D,E,F solveNode class G,H optNode class I valNode class 数据准备 prepSubgraph class 线性求解 solveSubgraph class 非线性优化 optSubgraph class 结果验证 valSubgraph linkStyle 0,1,2,3,4,5,6,7 stroke-width:2px
flowchart TD
A["采集标定图像<br/>多个角度的棋盘格"] --> B["提取角点坐标<br/>亚像素精度"]
B --> C["建立对应关系<br/>3D世界点 ↔ 2D图像点"]
C --> D["构建线性方程组<br/>Ah = 0"]
D --> E["SVD求解<br/>最小二乘解"]
E --> F["分解投影矩阵<br/>提取内参和外参"]
F --> G["非线性优化<br/>最小化重投影误差"]
G --> H["畸变参数估计<br/>径向和切向畸变"]
H --> I["标定结果验证<br/>重投影误差分析"]
subgraph 数据准备
A
B
C
end
subgraph 线性求解
D
E
F
end
subgraph 非线性优化
G
H
end
subgraph 结果验证
I
end
%% 移除渐变定义,使用单色填充
classDef prepNode fill:#42a5f5,stroke:#1565c0,color:white,stroke-width:2px,font-weight:bold,border-radius:8px
classDef solveNode fill:#ffb74d,stroke:#e65100,color:white,stroke-width:2px,font-weight:bold,border-radius:8px
classDef optNode fill:#66bb6a,stroke:#1b5e20,color:white,stroke-width:2px,font-weight:bold,border-radius:8px
classDef valNode fill:#f48fb1,stroke:#880e4f,color:white,stroke-width:2px,font-weight:bold,border-radius:8px
classDef prepSubgraph fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,font-weight:bold
classDef solveSubgraph fill:#fff3e0,stroke:#e65100,stroke-width:2px,color:#bf360c,font-weight:bold
classDef optSubgraph fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px,color:#1b5e20,font-weight:bold
classDef valSubgraph fill:#fce4ec,stroke:#880e4f,stroke-width:2px,color:#880e4f,font-weight:bold
class A,B,C prepNode
class D,E,F solveNode
class G,H optNode
class I valNode
class 数据准备 prepSubgraph
class 线性求解 solveSubgraph
class 非线性优化 optSubgraph
class 结果验证 valSubgraph
linkStyle 0,1,2,3,4,5,6,7 stroke-width:2px
graph TD A["世界坐标系<br/>(Xw, Yw, Zw)"] -->|旋转R + 平移t| B["相机坐标系<br/>(Xc, Yc, Zc)"] B -->|透视投影<br/>除以Zc| C["归一化坐标系<br/>(x, y)"] C -->|内参矩阵K<br/>fx, fy, cx, cy| D["像素坐标系<br/>(u, v)"] subgraph 外参变换 E["刚体变换<br/>6个自由度"] end subgraph 内参变换 F["传感器特性<br/>4个参数"] end A -.-> E C -.-> F classDef coordNode fill:#42a5f5,stroke:#1565c0,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px classDef paramNode fill:#9c27b0,stroke:#6a1b9a,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px classDef extSubgraph fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,font-weight:bold classDef intSubgraph fill:#f3e5f5,stroke:#6a1b9a,stroke-width:2px,color:#4a148c,font-weight:bold class A,B,C,D coordNode class E,F paramNode class 外参变换 extSubgraph class 内参变换 intSubgraph linkStyle 0 stroke:#1565c0,stroke-width:2px linkStyle 1 stroke:#0097a7,stroke-width:2px linkStyle 2 stroke:#ad1457,stroke-width:2px linkStyle 3,4 stroke:#6a1b9a,stroke-width:1.5px,stroke-dasharray:3 3 %% 移除渐变定义,使用单色填充
graph TD
A["世界坐标系<br/>(Xw, Yw, Zw)"] -->|旋转R + 平移t| B["相机坐标系<br/>(Xc, Yc, Zc)"]
B -->|透视投影<br/>除以Zc| C["归一化坐标系<br/>(x, y)"]
C -->|内参矩阵K<br/>fx, fy, cx, cy| D["像素坐标系<br/>(u, v)"]
subgraph 外参变换
E["刚体变换<br/>6个自由度"]
end
subgraph 内参变换
F["传感器特性<br/>4个参数"]
end
A -.-> E
C -.-> F
classDef coordNode fill:#42a5f5,stroke:#1565c0,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
classDef paramNode fill:#9c27b0,stroke:#6a1b9a,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
classDef extSubgraph fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,font-weight:bold
classDef intSubgraph fill:#f3e5f5,stroke:#6a1b9a,stroke-width:2px,color:#4a148c,font-weight:bold
class A,B,C,D coordNode
class E,F paramNode
class 外参变换 extSubgraph
class 内参变换 intSubgraph
linkStyle 0 stroke:#1565c0,stroke-width:2px
linkStyle 1 stroke:#0097a7,stroke-width:2px
linkStyle 2 stroke:#ad1457,stroke-width:2px
linkStyle 3,4 stroke:#6a1b9a,stroke-width:1.5px,stroke-dasharray:3 3
%% 移除渐变定义,使用单色填充
图11.4:镜头畸变校正前后的效果对比,注意图像边缘的几何变化
Code
graph TD subgraph 误差计算 A["观测点<br/>(u_obs, v_obs)"] B["重投影点<br/>(u_proj, v_proj)"] C["误差向量<br/>Δu = u_obs - u_proj<br/>Δv = v_obs - v_proj"] end subgraph 误差分析 D["均方根误差<br/>RMSE = √(Σ(Δu² + Δv²)/N)"] E["最大误差<br/>Max Error"] F["误差分布<br/>空间统计"] end subgraph 质量评估 G["优秀: RMSE < 0.5像素"] H["良好: 0.5 < RMSE < 1.0"] I["需改进: RMSE > 1.0"] end A --> C B --> C C --> D C --> E C --> F D --> G D --> H D --> I %% 使用简单的填充色替代渐变 classDef calcNode fill:#64b5f6,stroke:#1565c0,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px classDef analysisNode fill:#ba68c8,stroke:#6a1b9a,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px classDef excellentNode fill:#66bb6a,stroke:#2e7d32,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px classDef goodNode fill:#ffb74d,stroke:#ef6c00,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px classDef poorNode fill:#ef5350,stroke:#c62828,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px classDef calcSubgraph fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,font-weight:bold classDef analysisSubgraph fill:#f3e5f5,stroke:#6a1b9a,stroke-width:2px,color:#4a148c,font-weight:bold classDef qualitySubgraph fill:#f1f8e9,stroke:#2e7d32,stroke-width:2px,color:#1b5e20,font-weight:bold class A,B,C calcNode class D,E,F analysisNode class G excellentNode class H goodNode class I poorNode class 误差计算 calcSubgraph class 误差分析 analysisSubgraph class 质量评估 qualitySubgraph linkStyle 0,1 stroke:#7b1fa2,stroke-width:2px linkStyle 2,3,4 stroke:#7b1fa2,stroke-width:2px linkStyle 5 stroke:#4caf50,stroke-width:2px linkStyle 6 stroke:#ff9800,stroke-width:2px linkStyle 7 stroke:#f44336,stroke-width:2px
graph TD
subgraph 误差计算
A["观测点<br/>(u_obs, v_obs)"]
B["重投影点<br/>(u_proj, v_proj)"]
C["误差向量<br/>Δu = u_obs - u_proj<br/>Δv = v_obs - v_proj"]
end
subgraph 误差分析
D["均方根误差<br/>RMSE = √(Σ(Δu² + Δv²)/N)"]
E["最大误差<br/>Max Error"]
F["误差分布<br/>空间统计"]
end
subgraph 质量评估
G["优秀: RMSE < 0.5像素"]
H["良好: 0.5 < RMSE < 1.0"]
I["需改进: RMSE > 1.0"]
end
A --> C
B --> C
C --> D
C --> E
C --> F
D --> G
D --> H
D --> I
%% 使用简单的填充色替代渐变
classDef calcNode fill:#64b5f6,stroke:#1565c0,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px
classDef analysisNode fill:#ba68c8,stroke:#6a1b9a,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px
classDef excellentNode fill:#66bb6a,stroke:#2e7d32,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px
classDef goodNode fill:#ffb74d,stroke:#ef6c00,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px
classDef poorNode fill:#ef5350,stroke:#c62828,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px
classDef calcSubgraph fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,font-weight:bold
classDef analysisSubgraph fill:#f3e5f5,stroke:#6a1b9a,stroke-width:2px,color:#4a148c,font-weight:bold
classDef qualitySubgraph fill:#f1f8e9,stroke:#2e7d32,stroke-width:2px,color:#1b5e20,font-weight:bold
class A,B,C calcNode
class D,E,F analysisNode
class G excellentNode
class H goodNode
class I poorNode
class 误差计算 calcSubgraph
class 误差分析 analysisSubgraph
class 质量评估 qualitySubgraph
linkStyle 0,1 stroke:#7b1fa2,stroke-width:2px
linkStyle 2,3,4 stroke:#7b1fa2,stroke-width:2px
linkStyle 5 stroke:#4caf50,stroke-width:2px
linkStyle 6 stroke:#ff9800,stroke-width:2px
linkStyle 7 stroke:#f44336,stroke-width:2px