C++和OPENCV实现相机标定

目录

代码功能说明

函数参数与输出详解

1. 输入参数

2. 输出参数

关键结果解读

1. 旋转矩阵 R

2. 平移向量 T

3. 标定误差 stereoError

与其他步骤的关联

1. 单目 vs. 立体标定

2. 对立体校正的影响

3. 对深度计算的影响

常见问题排查

1. 标定误差过高

2. 外参结果不合理

3. 后续应用失败

总结

问题分析与解决方案

1. 畸变系数异常的原因

2. 立体标定误差高的原因

解决方案

步骤1:优化单目标定参数

步骤2:优化标定板图像

步骤3:验证标定板角点检测

步骤4:验证相机内参合理性

步骤5:修正立体标定参数

代码修正对比表

验证与调试流程

关键参数解释

最终建议

原因分析与解决方案

1. 标定标志设置导致参数强制归零

2. 左相机畸变系数异常的可能原因

解决方案

步骤1:调整标定标志以允许更多畸变参数

步骤2:验证标定板角点检测

步骤3:优化标定图像集

步骤4:重新标定并分析结果

关键代码修改说明

1. 允许估计高阶畸变参数

2. 标定后验证畸变系数

3. 异常值处理

畸变系数模型说明

总结


C++和OPENCV,实现双目视觉及三维重建。

左右相机各拍17张棋盘标定板图片;

棋盘标定板长12个格子,宽9个格子,格子边长6mm;

左右相机图像

放在两个文件夹了,命名都是从1.PNG到17.PNG,

在vs2019中运行正常

以下是代码中立体标定部分的详细解释:


代码功能说明

这段代码通过 stereoCalibrate 函数计算双目相机系统的 外参(旋转矩阵 R 和平移向量 T,并输出标定误差。
其核心目的是确定左右相机之间的空间几何关系,为后续的立体校正和深度计算提供基础。


函数参数与输出详解

1. 输入参数
  • objectPoints: 三维标定板角点的物理坐标(单位由 squareSize 决定,例如毫米)。
  • leftImagePoints / rightImagePoints: 左右图像中检测到的对应角点的像素坐标。
  • leftCameraMatrix / leftDistCoeffs: 左相机的内参矩阵和畸变系数(已通过单目标定得到)。
  • rightCameraMatrix / rightDistCoeffs: 右相机的内参矩阵和畸变系数(同上)。
  • imageSize: 图像分辨率(如 1280x1024)。
  • CALIB_FIX_INTRINSIC: 标志位,表示 固定左右相机的内参和畸变系数,仅优化外参。
2. 输出参数
  • R: 右相机相对于左相机的 旋转矩阵(3x3 矩阵),表示右相机的姿态如何旋转以对齐到左相机坐标系。
  • T: 右相机相对于左相机的 平移向量(3x1 向量),单位为标定板尺寸单位(例如毫米)。
  • E: 本质矩阵(Essential Matrix),用于描述两相机之间的极几何关系,满足 x2TEx1=0 x_2^T E x_1 = 0 x2T​Ex1​=0。
  • F: 基础矩阵(Fundamental Matrix),类似本质矩阵但考虑了内参,满足 p2TFp1=0 p_2^T F p_1 = 0 p2T​Fp1​=0(p p p 为像素坐标)。
  • stereoError: 标定误差(单位:像素),表示角点重投影误差的均方根(RMS)。

关键结果解读

1. 旋转矩阵 R
  • 物理意义: 右相机的坐标系需要经过旋转矩阵 R 变换后,才能与左相机坐标系对齐。
  • 示例:

    cpp

     
      
    R = [ 0.999, 0.001, -0.005,
    -0.001, 0.999, 0.003,
    0.005, -0.003, 0.999 ]
    表示右相机相对于左相机的旋转角度极小(接近平行安装)。
2. 平移向量 T
  • 物理意义: 右相机相对于左相机的空间位置偏移,通常以左相机为原点。
  • 示例:

    cpp

    T = [-34.6668, 0.1029, 4.6637]  // 单位:毫米
    表示右相机位于左相机左侧 34.67mm,上方 0.10mm,后方 4.66mm。
3. 标定误差 stereoError
  • 合理范围: 误差应小于 0.5像素。若误差过大(如 >1像素),可能原因包括:
    • 角点检测不准确(检查生成的 *_corners_*.jpg)。
    • 标定板图像数量不足或分布不合理。
    • 相机内参标定不准确(单目标定阶段问题)。

与其他步骤的关联

1. 单目 vs. 立体标定
  • 单目标定:确定单个相机的内参(焦距、主点)和畸变系数。
  • 立体标定:在单目标定基础上,计算双目的外参(R, T)。
2. 对立体校正的影响
  • RT 用于 stereoRectify 函数,生成左右相机的校正映射矩阵(R1, R2, P1, P2)。
  • RT 不准确,会导致校正后的图像无法对齐,视差图无效(如全黑或噪声严重)。
3. 对深度计算的影响
  • 平移向量 T 的模长(基线长度)直接影响深度精度。较大的基线(如 100mm)适合远距离测距,较小的基线(如 30mm)适合近距离。

常见问题排查

1. 标定误差过高
  • 检查角点检测:确认所有标定板图像的角点均被正确标记(查看 *_corners_*.jpg)。
  • 增加标定板多样性:采集标定板在不同距离、角度下的图像,覆盖整个视野。
  • 验证单目标定结果:确保左右相机的内参和畸变系数合理(如主点应在图像中心附近)。
2. 外参结果不合理
  • 检查标定板方向:标定板的坐标系定义需一致(例如棋盘格的第一个角点位置)。
  • 验证物理安装:平移向量 T 的 X 分量应为负值(右相机在左相机左侧)。
3. 后续应用失败
  • 校正验证:使用 stereoRectifyinitUndistortRectifyMap 后,绘制水平线验证对齐效果。
  • 深度生成调试:检查视差图生成参数(如 numDisparities 是否覆盖实际视差范围)。

总结

此代码段通过立体标定确定了双相机的空间关系,输出的 RT 是深度计算的核心参数。标定误差和参数合理性直接影响后续步骤的准确性,需通过多角度验证确保结果可靠。

C++和OPENCV实现相机标定代码:

#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include <string>

using namespace cv;
using namespace std;

// 可调参数区域
const Size boardSize(11, 8);          // 棋盘格内角点数量(格子数-1)
const float squareSize = 6.0f;        // 棋盘格实际尺寸(毫米)
const string leftFolder = "left_images/";    // 左图文件夹路径
const string rightFolder = "right_images/";  // 右图文件夹路径
// 新标志:仅估计k1, k2, p1, p2,固定高阶项
const int calibrationFlags = CALIB_FIX_ASPECT_RATIO |  CALIB_FIX_K3 | CALIB_FIX_K4 | CALIB_FIX_K5 | CALIB_FIX_K6;

const Size imageSize(1280, 1024);       // 图像尺寸(需根据实际修改)
// 立体匹配参数(根据场景调整)
const int minDisparity = 0;
const int numDisparities = 16 * 5;     // 必须为16的整数倍
const int blockSize = 5;             // 奇数,3-11之间
const int disp12MaxDiff = 20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值