
双目相机、SLAM、极线几何与相机标定总结目录为什么 SLAM 常把图像变成灰度图双目深度中的 d、f、B、Z什么是极平面、极线和图像平面什么是去畸变、双目矫正和极线对齐ORB-SLAM3 双目特征匹配的大致流程为什么右目畸变错误会影响 SLAM 和手部轨迹矫正后没有黑边是否代表操作错误焦距到底决定什么为什么焦距更大时深度分辨能力更好标定误差、重投影误差与极线误差如何在真实场景验证极线误差标定阶段与运行阶段的正确参数组合AprilTag 检测与 solvePnP 的关系最常见的错误与检查清单1. 为什么 SLAM 常把图像变成灰度图传统几何 SLAM 主要关心的是角点、边缘、局部纹理、明暗变化、同一特征在前后帧的位置变化以及同一特征在左右目图像中的位置差。这些信息通常用单通道灰度图就能表达因此很多 SLAM 系统会把彩色图B、G、R 三个通道转换成灰度图Gray 一个通道OpenCV 中常见写法graycv2.cvtColor(color_image,cv2.COLOR_BGR2GRAY)灰度图并不是只有纯黑和纯白而是0黑色255白色中间数值不同程度的灰色常见灰度转换近似为[Gray0.299R0.587G0.114B]灰度化的主要优点数据量约降为彩色图的三分之一特征提取和匹配更快内存占用更小左右相机色彩差异影响更小传统 ORB、FAST 等特征本身主要依赖亮度结构颜色并不是完全没用。语义 SLAM、目标检测、手部识别、彩色指套识别等任务仍可使用彩色图。推荐并行流程灰度左右图 → 双目 SLAM → 相机轨迹、地图点、深度 彩色左目图 → 手部、AprilTag、物体检测2. 双目深度中的 d、f、B、Z双目矫正后某个空间点在左右图中的位置分别为[p_L(u_L,v_L)][p_R(u_R,v_R)]理想情况下[v_L\approx v_R]视差定义为[du_L-u_R]双目深度公式[Z\frac{fB}{d}]符号含义常见单位(d)左右图中同一真实点的水平像素差px(f)矫正图像对应的像素焦距px(B)左右相机光心之间的物理距离即基线m、mm(Z)该点沿相机前方方向的深度m、mm2.1 视差 d 的直观含义例如同一个桌角左图横坐标uL 450 右图横坐标uR 370.4则[d450-370.479.6\text{ px}]意思是同一个真实桌角在左右两张矫正后的图像中水平方向错开了 79.6 个像素。它不是左右相机的真实距离。2.2 基线 B 的含义例如[B0.1\text{ m}100\text{ mm}]它是左右相机光心之间的真实物理距离可以通过机械尺寸或双目标定外参获得。因此(d) 是图像中的像素错位(B) 是现实世界中的相机间距二者不是同一个量但存在关系[d\frac{fB}{Z}]2.3 近大远小在焦距和基线固定时[d\text{ 大}\Rightarrow Z\text{ 小}][d\text{ 小}\Rightarrow Z\text{ 大}]通俗地说近处物体在左右图中“跳得多”远处物体“跳得少”。3. 什么是极平面、极线和图像平面3.1 左右图像平面图像平面是相机模型中的几何平面。通俗理解左相机有一张“成像画布”右相机有一张“成像画布”空间中的一个点会分别投影到两张画布上。实际数字图像是该连续平面被像素化后的结果三维空间 ↓ 投影 连续图像平面 ↓ 采样 数字图像中的像素坐标 (u, v)工程上可以近似理解为左图像平面对应左目图像右图像平面对应右目图像3.2 极平面设左相机光心为 (O_L)右相机光心为 (O_R)空间点为 (P)三点[O_L,\ O_R,\ P]确定一个平面这个平面叫做极平面。3.3 极线极平面分别与左右图像平面相交产生两条直线左极线右极线极线的含义是已知左图中的一个点后它在右图中的对应点理论上只能出现在对应极线上而不是出现在右图任意位置。未经双目矫正时极线可能是斜线经过双目矫正后极线通常变成水平线。4. 什么是去畸变、双目矫正和极线对齐这三个概念要分开。4.1 去畸变 Undistortion单个镜头会产生径向畸变、切向畸变等。去畸变使用该相机的内参 (K)畸变参数 (D)把弯曲的直线和错误的像素位置修正到理想针孔相机模型中。左右相机各有自己的[K_L,D_L][K_R,D_R]4.2 双目矫正 Stereo Rectification双目矫正还要使用左右相机之间的外参[R,T]它把左右相机虚拟地旋转到一个更方便匹配的姿态使得两个图像平面共面两个水平轴平行同一个空间点在左右图中的纵坐标接近极线变成水平线OpenCV 常见流程R1,R2,P1,P2,Q,roi1,roi2cv2.stereoRectify(K1,D1,K2,D2,image_size,R,T)然后生成映射表map1_x,map1_ycv2.initUndistortRectifyMap(K1,D1,R1,P1,image_size,cv2.CV_32FC1)map2_x,map2_ycv2.initUndistortRectifyMap(K2,D2,R2,P2,image_size,cv2.CV_32FC1)执行重映射left_rectcv2.remap(left_raw,map1_x,map1_y,cv2.INTER_LINEAR)right_rectcv2.remap(right_raw,map2_x,map2_y,cv2.INTER_LINEAR)4.3 极线对齐双目矫正后的理想条件[v_L^{rect}\approx v_R^{rect}]于是左右匹配只需沿水平方向寻找二维搜索上、下、左、右都找 变成 一维搜索只在同一水平行附近左右找这就是极线对齐带来的主要价值。5. ORB-SLAM3 双目特征匹配的大致流程双目 SLAM 通常不是只检测左目也不是简单在右图中寻找“相同亮度的像素”。更准确的流程是左图提取 ORB 特征点和描述子 右图提取 ORB 特征点和描述子 ↓ 以左目特征为主建立匹配 ↓ 在右图相同水平极线附近筛选候选 ↓ 比较 ORB 描述子 ↓ 局部灰度块进一步细化 ↓ 得到亚像素右目坐标 ↓ 计算视差和深度5.1 为什么不是“相同亮度”单个像素亮度相同并不代表是同一个空间点。ORB 描述子比较的是特征点周围的局部明暗结构。例如左目描述子101101001011... 右目候选A101001111011... 右目候选B101101001001...通过汉明距离判断谁更相似。通常还会限制极线位置合理视差范围特征尺度描述子距离局部图块差异5.2 为什么常常只显示左目特征很多系统以左目为参考相机。最后保存的信息可能是左目像素坐标 右目匹配坐标 视差 深度因此查看器只显示左目不代表右目没有参与计算。6. 为什么右目畸变错误会影响 SLAM 和手部轨迹误差链路可以写成右目畸变参数错误 → 右图去畸变位置错误 → 双目矫正后无法正确极线对齐 → 左右特征匹配减少或错配 → 视差错误 → 三角化深度和地图点错误 → ORB-SLAM3 相机位姿优化受影响 → SLAM 世界坐标系中的手部轨迹继承相机位姿误差例如本来应该左图点(450, 320) 右图点(370, 320)右目畸变错误后可能变成右图错误位置(373, 326)此时水平位置错误导致视差错误垂直位置错误导致极线误差水平视差[d450-37377]纵向极线误差[e_{\text{epi}}|320-326|6\text{ px}]如果 SLAM 输出的相机世界位姿为[T_{\text{world}\leftarrow\text{camera}}]手部相机坐标为[P_{\text{camera}}]则[P_{\text{world}}T_{\text{world}\leftarrow\text{camera}}P_{\text{camera}}]相机位姿错了手部世界坐标也会继承该误差。7. 矫正后没有黑边是否代表操作错误不一定。去畸变或双目矫正后理论上可能出现黑边因为输出画布中的某些位置在原图中没有对应像素。但如果使用了以下方式图像可以没有黑边放大自动裁剪有效 ROIalpha0公共有效区域查看器只显示有效部分OpenCV 中new_K,roicv2.getOptimalNewCameraMatrix(K,D,image_size,alpha,image_size)常见含义alpha效果0尽量没有黑边但会裁剪或放大1尽量保留完整视野但可能有黑边01折中双目矫正中也有类似的alpha参数。7.1 裁剪是否破坏几何真值正确理解裁剪会损失边缘视野但不必然破坏保留区域的几何正确性。只要后续参数同步更新新焦距正确新主点正确新投影矩阵正确左右坐标系一致极线仍可对齐。7.2 真正危险的情况图像已经经过去畸变双目矫正裁剪缩放却仍然使用原始[K,D]这会造成参数与图像坐标不一致。例如左边裁掉 50 像素[c_x’c_x-50]如果又缩放 0.8 倍[f_x’0.8f_x][f_y’0.8f_y][c_x’0.8(c_x-50)][c_y’0.8(c_y-y_{\text{crop}})]8. 焦距到底决定什么相机投影公式[uf_x\frac{X}{Z}c_x][vf_y\frac{Y}{Z}c_y]焦距决定空间角度对应多少像素目标在图像中占多大相机视场角有多宽同样空间运动产生多大像素位移双目视差有多明显8.1 焦距与视场角近似关系[\mathrm{FOV}2\arctan\left(\frac{\text{传感器尺寸}}{2f}\right)]因此焦距大视野窄目标更大焦距小视野宽目标更小8.2 物理焦距与像素焦距物理焦距2.8 mm 4 mm 8 mm像素焦距fx 800 px fy 798 px二者关系大致为[f_x\frac{f_{\text{mm}}}{\text{单像素物理宽度}_{\text{mm}}}]SLAM、双目深度和solvePnP通常使用像素焦距。9. 为什么焦距更大时深度分辨能力更好物体真实深度不会因为焦距改变而改变。“深度分辨能力更好”是指同样的真实深度变化在图像中会造成更明显的视差变化因此更容易区分相近的两个深度。双目关系[d\frac{fB}{Z}]在 (B) 和 (Z) 固定时[f\text{ 越大}\Rightarrow d\text{ 越大}]9.1 数值例子设[B0.1\text{ m}][Z2\text{ m}]焦距 400 px[d\frac{400\times0.1}{2}20\text{ px}]若视差误差为 1 px[Z_{19}\frac{400\times0.1}{19}\approx2.105\text{ m}][Z_{21}\frac{400\times0.1}{21}\approx1.905\text{ m}]深度误差约 10 cm 量级。焦距 800 px[d\frac{800\times0.1}{2}40\text{ px}]若视差误差同样为 1 px[Z_{39}\frac{800\times0.1}{39}\approx2.051\text{ m}][Z_{41}\frac{800\times0.1}{41}\approx1.951\text{ m}]深度误差约 5 cm 量级。近似误差传播[|\Delta Z|\approx\frac{Z^2}{fB}|\Delta d|]因此[f\text{ 越大}\Rightarrow |\Delta Z|\text{ 越小}]前提是视差匹配误差 (\Delta d) 基本相同。注意单纯把数字图像resize放大并不会产生新的真实光学信息也不会真正提升深度精度。10. 标定误差、重投影误差与极线误差10.1 标定中的重投影误差标定时使用的是原始带畸变图像。流程原始畸变图像 → 检测棋盘格、ChArUco 等角点 → 得到观测像素位置 → 拟合 K、D、每张图的 R、t → 把已知三维角点重新投回原始图像 → 比较预测点和检测点检测到的实际图像角点[p_{\text{obs}}(u_{\text{obs}},v_{\text{obs}})]标定模型预测位置[p_{\text{proj}}(u_{\text{proj}},v_{\text{proj}})]单点重投影误差[e\sqrt{(u_{\text{obs}}-u_{\text{proj}})^2(v_{\text{obs}}-v_{\text{proj}})^2}]例如[p_{\text{obs}}(500.3,320.7)][p_{\text{proj}}(499.8,321.1)]则[e\approx0.64\text{ px}]总 RMS 重投影误差[\mathrm{RMS}\sqrt{\frac{1}{N}\sum_{i1}{N}e_i2}]它表示标定模型与标定图中检测结果的一致程度。它不直接等于真实三维测量误差也不等于双目极线误差。10.2 极线误差双目矫正后对应点应该满足[v_L^{rect}\approx v_R^{rect}]每个点的垂直极线误差可定义为[e_{\text{epi},i}|v_{L,i}{rect}-v_{R,i}{rect}|]例如左图角点(450.3, 320.2) 右图角点(372.8, 320.7)则[e_{\text{epi}}|320.2-320.7|0.5\text{ px}]横坐标差 (u_L-u_R) 是视差纵坐标差 (v_L-v_R) 才是矫正后的极线误差。11. 如何在真实场景验证极线误差应该使用没有参加标定的独立数据。推荐30100 对同步左右图棋盘格ChArUco多 AprilTag 板覆盖中央、四角、近中远距离和不同倾角完整流程独立左右同步图 → 使用标定参数做双目矫正 → 在左右矫正图中检测相同编号角点 → 计算每个点的纵坐标差 → 统计 mean、median、RMS、P95、max → 按图像位置画误差分布11.1 计算代码from__future__importannotationsimportnumpyasnpdefcompute_rectified_epipolar_error(points_left:np.ndarray,points_right:np.ndarray,)-dict[str,float]: 输入 points_left: (N, 2)左矫正图中的 (u, v) points_right: (N, 2)右矫正图中的对应 (u, v) 输出 极线误差统计单位为像素 points_leftnp.asarray(points_left,dtypenp.float64)points_rightnp.asarray(points_right,dtypenp.float64)ifpoints_left.shape!points_right.shape:raiseValueError(左右对应点数量或形状不一致)ifpoints_left.ndim!2orpoints_left.shape[1]!2:raiseValueError(输入必须为形状 (N, 2))iflen(points_left)0:raiseValueError(没有有效对应点)errorsnp.abs(points_left[:,1]-points_right[:,1])return{count:float(len(errors)),mean_px:float(np.mean(errors)),median_px:float(np.median(errors)),rms_px:float(np.sqrt(np.mean(errors**2))),p95_px:float(np.percentile(errors,95)),max_px:float(np.max(errors)),}11.2 推荐统计指标至少报告有效对应点数量平均误差 mean中位数 medianRMSP95最大误差 max图像中央和四角分区误差静态状态动态状态经验参考平均垂直极线误差大致评价 0.3 px很好0.30.5 px较好0.51.0 px通常可用12 px建议排查 2 px双目匹配通常明显受影响这只是经验值最终要结合图像分辨率焦距基线工作距离SLAM 匹配阈值所需深度精度11.3 静态与动态分开测试静态测试主要反映内参畸变参数双目外参矫正算法动态测试还会包含左右时间不同步滚动快门运动模糊支架形变自动曝光差异自动对焦变化如果静态很好、动态变差问题可能主要在同步和成像时序而不是标定本身。12. 标定阶段与运行阶段的正确参数组合这是整个流程最容易混淆的地方。12.1 标定阶段第一次标定时还没有可靠的 (K,D)因此不能先正确去畸变再标定。正确流程原始畸变图 → 直接检测标定板角点 → 拟合 K、D、R、t → 用 K、D 把三维角点投影回原始畸变图 → 计算重投影误差检测棋盘格角点本身通常不需要输入相机参数ret,cornerscv2.findChessboardCorners(gray,pattern_size)12.2 运行阶段运行时可以选两种正确做法。方案 A在原始图上检测原始畸变图 → 检测 Tag 四角 → 使用原始 K、D 做 solvePnPsuccess,rvec,tveccv2.solvePnP(object_points,image_points_raw,K_original,D_original,)方案 B先去畸变或双目矫正再检测原始图 → 使用 K、D 去畸变或双目矫正 → 在处理后的图上检测 Tag → 使用处理后图像对应的新内参 → 畸变设为零success,rvec,tveccv2.solvePnP(object_points,image_points_rectified,K_rectified,None,)核心对应关系图像坐标类型应使用的相机参数原始畸变图原始 (K) 原始 (D)单目去畸变图(K_{\text{new}}) 零畸变双目矫正左图从 (P_1) 提取的新内参 零畸变双目矫正右图从 (P_2) 提取的新内参 零畸变双目矫正左图的新内参通常可写为[K_{\text{rect,left}}P_1[:,0:3]]13. AprilTag 检测与 solvePnP 的关系要区分两个步骤。13.1 Tag 检测输入图像输出Tag ID四个角点像素坐标这一阶段主要依赖黑白边缘方形轮廓编码内容局部纹理通常不需要输入 (K,D)。13.2 姿态估计根据Tag 四个图像角点Tag 真实边长对应图像坐标系的相机内参图像是否还包含畸变计算[rvec,\ tvec]如果 Tag 物体坐标以中心为原点tvec表示 Tag 中心在相机坐标系中的位置。OpenCVsolvePnP的关系[X_cRX_ot]其中(X_o)Tag 坐标系中的点(X_c)相机坐标系中的点(R,t)Tag 到相机的位姿如果物体点单位是 mm则tvec也是 mm。13.3 关键原则角点检测 “角点在图像哪里” 姿态估计 “Tag 离相机多远、朝向如何”检测阶段通常不依赖相机参数姿态估计阶段必须使用和图像坐标一致的相机参数。14. 最常见的错误与检查清单14.1 常见错误错误 1矫正图继续使用原始 K、D图像已去畸变 solvePnP 仍使用原始 K、D会产生二次畸变补偿和坐标不一致。错误 2图像裁剪后主点未修改裁掉左侧 (x_0) 像素后[c_x’c_x-x_0]裁掉顶部 (y_0) 像素后[c_y’c_y-y_0]错误 3图像缩放后焦距和主点未缩放缩放比例为 (s_x,s_y)[f_x’s_xf_x][f_y’s_yf_y][c_x’s_xc_x][c_y’s_yc_y]错误 4左右使用不同 ROI但未同步坐标左右图必须在统一的矫正坐标定义下做视差比较。错误 5只看重投影误差不测真实极线误差重投影误差小不保证双目外参和真实使用状态一定好。错误 6只看平均误差必须同时看medianRMSP95max图像位置分布错误 7只做静态测试头部设备还应测试转头快速平移动态光照运动模糊时间同步14.2 推荐检查清单相机状态分辨率与标定一致裁剪方式与标定一致自动对焦关闭或固定曝光和增益尽量固定电子防抖关闭数字变焦关闭左右时间同步正常机械支架无松动标定参数左相机 (K_1,D_1) 对应左图右相机 (K_2,D_2) 对应右图双目外参 (R,T) 方向正确基线单位正确图像尺寸与标定尺寸一致矫正后使用 (P_1,P_2) 对应的新内参矫正图畸变设置为零极线验证使用独立验证图像左右角点编号严格对应计算 (|v_L-v_R|)统计 mean、median、RMS、P95、max检查图像中央与四角静态和动态分别测试可视化水平线和误差热图SLAM 验证左右匹配数量是否正常深度分布是否合理近距离与远距离深度是否稳定转头时轨迹是否异常抖动纯旋转时是否出现明显虚假平移地图点是否在边缘区域异常手部世界坐标是否继承头部轨迹漂移最终核心总结灰度化是为了减少计算量并保留几何特征。视差 (d) 是同一真实点在左右图中的水平像素差。基线 (B) 是左右相机光心之间的真实物理距离。焦距 (f) 决定空间角度被映射成多少像素。极线限定了对应点在另一张图中的可能位置。双目矫正使对应极线水平化满足 (v_L\approx v_R)。右目畸变错误会破坏极线对齐、视差和三角化深度。矫正后无黑边不一定是错误可能只是裁剪或放大了有效区域。裁剪可以保留几何正确性但必须同步更新内参和主点。焦距增大不会改变真实深度但会让视差变化更明显从而降低相同像素误差带来的深度误差。重投影误差是模型预测像素和标定图中检测像素之间的距离。极线误差是矫正后左右对应点的纵坐标差。标定时在原始畸变图上检测角点。运行时原始图使用原始 (K,D)矫正图使用新内参和零畸变。Tag 检测和 Tag 姿态估计是两个不同步骤。最重要的参数一致性原则原始图坐标 ↔ 原始 K、D 去畸变图坐标 ↔ 新 K、零畸变 双目矫正图坐标 ↔ P1/P2 对应的新内参、零畸变