当前位置: 首页 > news >正文

OpenCV相机标定与3D重建(59)用于立体相机标定的函数stereoCalibrate()的使用

  • 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

标定立体相机设置。此函数找到两个相机各自的内参以及两个相机之间的外参。
cv::stereoCalibrate 是 OpenCV 中用于立体相机标定的函数。它通过一组已知的3D点及其在两个相机中的对应2D投影,来估计两个相机之间的相对位置和方向(旋转矩阵R和平移向量T),同时还可以优化每个相机的内参矩阵和畸变系数。

函数原型

double cv::stereoCalibrate	
(InputArrayOfArrays 	objectPoints,InputArrayOfArrays 	imagePoints1,InputArrayOfArrays 	imagePoints2,InputOutputArray 	cameraMatrix1,InputOutputArray 	distCoeffs1,InputOutputArray 	cameraMatrix2,InputOutputArray 	distCoeffs2,Size 	imageSize,InputOutputArray 	R,InputOutputArray 	T,OutputArray 	E,OutputArray 	F,OutputArrayOfArrays 	rvecs,OutputArrayOfArrays 	tvecs,OutputArray 	perViewErrors,int 	flags = CALIB_FIX_INTRINSIC,TermCriteria 	criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 1e-6) 
)		

参数

  • 参数objectPoints 校准图案点的向量的向量。结构与 calibrateCamera 中相同。对于每个图案视图,两个相机需要看到相同的物体点。因此,objectPoints.size()、imagePoints1.size() 和 imagePoints2.size() 需要相等,并且对于每个 i,objectPoints[i].size()、imagePoints1[i].size() 和 imagePoints2[i].size() 也需要相等。
  • 参数imagePoints1 第一个相机观测到的校准图案点投影的向量的向量。结构与 calibrateCamera 中相同。
  • 参数imagePoints2 第二个相机观测到的校准图案点投影的向量的向量。结构与 calibrateCamera 中相同。
  • 参数cameraMatrix1 第一个相机的输入/输出内参矩阵,与 calibrateCamera 中相同。对于立体情况,可以使用额外的标志,见下文。
  • 参数distCoeffs1 输入/输出畸变系数向量,与 calibrateCamera 中相同。
  • 参数cameraMatrix2 第二个相机的输入/输出内参矩阵。详见 cameraMatrix1 的描述。
  • 参数distCoeffs2 第二个相机的镜头畸变系数的输入/输出向量。详见 distCoeffs1 的描述。
  • 参数imageSize 仅用于初始化相机内参矩阵的图像尺寸。
  • 参数R 输出旋转矩阵。连同平移向量 T 一起,该矩阵将第一个相机坐标系中的点变换到第二个相机坐标系中的点。更技术性地说,R 和 T 的组合执行了从第一个相机坐标系到第二个相机坐标系的基底变换。由于其对偶性,这个组合等价于第一个相机相对于第二个相机坐标系的位置。
  • 参数T 输出平移向量,参见上述描述。
  • 参数E 输出本质矩阵。
  • 参数F 输出基础矩阵。
  • 参数rvecs 输出旋转向量(Rodrigues 表示)的向量,估计每个立体对中第一相机坐标系下的图案视图。具体来说,每个第 i 个旋转向量连同对应的第 i 个平移向量(见下一个输出参数描述),将校准图案从物体坐标空间变换到立体对中第一相机的相机坐标空间。更技术性地说,第 i 个旋转和平移向量的组合执行了从物体坐标空间到立体对中第一相机的相机坐标空间的基底变换。
  • 参数tvecs 输出平移向量的向量,估计每个图案视图,参见上一个输出参数(rvecs)的参数描述。
  • 参数perViewErrors 每个图案视图的 RMS 重投影误差的输出向量。
  • 参数flags 不同的标志,可能是零或以下值的组合:
    • CALIB_FIX_INTRINSIC 固定 cameraMatrix? 和 distCoeffs?,以便只估计 R、T、E 和 F 矩阵。
    • CALIB_USE_INTRINSIC_GUESS 根据指定的标志优化一些或全部的内参。初始值由用户提供。
    • CALIB_USE_EXTRINSIC_GUESS R 和 T 包含有效的初始值,这些值被进一步优化。否则,R 和 T 初始化为图案视图的中位数(每个维度分别处理)。
    • CALIB_FIX_PRINCIPAL_POINT 在优化过程中固定主点。
    • CALIB_FIX_FOCAL_LENGTH 固定 f y ( j ) f^{(j)}_y fy(j) f y ( j ) f^{(j)}_y fy(j)
    • CALIB_FIX_ASPECT_RATIO 优化 f y ( j ) f^{(j)}_y fy(j) ,固定比率 f x ( j ) / f y ( j ) f^{(j)}_x/f^{(j)}_y fx(j)/fy(j)
    • CALIB_SAME_FOCAL_LENGTH 强制 f x ( 0 ) = f x ( 1 ) f^{(0)}_x=f^{(1)}_x fx(0)=fx(1) f y ( 0 ) = f y ( 1 ) f^{(0)}_y=f^{(1)}_y fy(0)=fy(1)
    • CALIB_ZERO_TANGENT_DIST 将每个相机的切向畸变系数设为零并固定不变。
    • CALIB_FIX_K1,…, CALIB_FIX_K6 在优化过程中不改变相应的径向畸变系数。如果设置了 CALIB_USE_INTRINSIC_GUESS,则使用提供的 distCoeffs 矩阵中的系数;否则,将其设置为 0。
    • CALIB_RATIONAL_MODEL 启用系数 k4、k5 和 k6。为了提供向后兼容性,此额外标志应显式指定以使标定函数使用有理模型并返回8个系数。如果不设置此标志,函数计算并返回仅5个畸变系数。
    • CALIB_THIN_PRISM_MODEL 启用系数 s1、s2、s3 和 s4。为了提供向后兼容性,此额外标志应显式指定以使标定函数使用薄棱镜模型并返回12个系数。如果不设置此标志,函数计算并返回仅5个畸变系数。
    • CALIB_FIX_S1_S2_S3_S4 在优化过程中不改变薄棱镜畸变系数。如果设置了 CALIB_USE_INTRINSIC_GUESS,则使用提供的
      distCoeffs 矩阵中的系数;否则,将其设置为 0。
    • CALIB_TILTED_MODEL 启用系数 τX 和 τY。为了提供向后兼容性,此额外标志应显式指定以使标定函数使用倾斜传感器模型并返回14个系数。如果不设置此标志,函数计算并返回仅5个畸变系数。
  • CALIB_FIX_TAUX_TAUY 在优化过程中不改变倾斜传感器模型的系数。如果设置了 CALIB_USE_INTRINSIC_GUESS,则使用提供的 distCoeffs 矩阵中的系数;否则,将其设置为 0。
  • criteria 迭代优化算法的终止条件。
    该函数估计了构成立体对的两个相机之间的变换。如果分别计算了一个物体相对于第一个相机和第二个相机的姿态 (R1, T1) 和 (R2, T2),并且对于一个立体相机,两个相机之间的相对位置和方向是固定的,那么这两个姿态肯定相互关联。这意味着,如果已知两个相机之间的相对位置和方向 (R, T),就可以在给定 (R1, T1) 的情况下计算 (R2, T2)。这就是该函数所做的。它计算 (R, T) 使得:

R 2 = R R 1 . R_2=R R_1. R2=RR1.
T 2 = R T 1 + T . T_2=R T_1 + T. T2=RT1+T.

因此,当给定了第一个相机坐标系中的3D点的坐标表示时,可以计算出该点在第二个相机坐标系中的坐标表示:
[ X 2 Y 2 Z 2 1 ] = [ R T 0 1 ] [ X 1 Y 1 Z 1 1 ] . \begin{bmatrix} X_2 \\ Y_2 \\ Z_2 \\ 1 \end{bmatrix} = \begin{bmatrix} R & T \\ 0 & 1 \end{bmatrix} \begin{bmatrix} X_1 \\ Y_1 \\ Z_1 \\ 1 \end{bmatrix}. X2Y2Z21 =[R0T1] X1Y1Z11 .

可选地,该函数还可以计算本质矩阵 E:

E = [ 0 − T 2 T 1 T 2 0 − T 0 − T 1 T 0 0 ] R E = \begin{bmatrix} 0 & -T_2 & T_1 \\ T_2 & 0 & -T_0 \\ -T_1 & T_0 & 0 \end{bmatrix} R E= 0T2T1T20T0T1T00 R

其中 Ti 是平移向量 T 的分量: T = [ T 0 , T 1 , T 2 ] T T=[T_0, T_1, T_2]^T T=[T0,T1,T2]T 。而且,该函数还可以计算基础矩阵 F:

F = c a m e r a M a t r i x 2 − T ⋅ E ⋅ c a m e r a M a t r i x 1 − 1 F = cameraMatrix2^{-T}\cdot E \cdot cameraMatrix1^{-1} F=cameraMatrix2TEcameraMatrix11

除了立体相关的信息外,该函数还可以对两个相机进行完整的标定。然而,由于参数空间的高维性和输入数据中的噪声,函数可能会偏离正确解。如果可以高精度地单独估计每个相机的内参(例如,使用 calibrateCamera),建议这样做并将 CALIB_FIX_INTRINSIC 标志传递给该函数,同时提供计算得到的内参。否则,如果所有参数一次性估计,限制某些参数是有意义的,例如传递 CALIB_SAME_FOCAL_LENGTH 和 CALIB_ZERO_TANGENT_DIST 标志,这通常是一个合理的假设。

类似于 calibrateCamera,该函数最小化来自两个相机所有可用视图的所有点的总重投影误差。函数返回最终的重投影误差值。

代码示例

#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>using namespace cv;
using namespace std;int main()
{// 假设我们有以下数据vector< vector< Point3f > > objectPoints;  // 物体坐标空间中的3D点数组vector< vector< Point2f > > imagePoints1;  // 第一个相机的图像点数组vector< vector< Point2f > > imagePoints2;  // 第二个相机的图像点数组// 检查是否已经填充了足够的点if ( objectPoints.empty() || imagePoints1.empty() || imagePoints2.empty() ){cerr << "Error: No calibration points provided." << endl;return -1;}// 确保所有数组大小一致if ( objectPoints.size() != imagePoints1.size() || objectPoints.size() != imagePoints2.size() ){cerr << "Error: The number of object points, image points from camera 1, and image points from camera 2 do not match." << endl;return -1;}// 相机内参矩阵 (假设有初始估计)Mat cameraMatrix1 = ( Mat_< double >( 3, 3 ) << 520.9, 0, 325.1, 0, 521.0, 249.7, 0, 0, 1 );Mat cameraMatrix2 = ( Mat_< double >( 3, 3 ) << 520.9, 0, 325.1, 0, 521.0, 249.7, 0, 0, 1 );// 畸变系数 (假设有初始估计)Mat distCoeffs1 = Mat::zeros( 8, 1, CV_64F );  // 8参数模型Mat distCoeffs2 = Mat::zeros( 8, 1, CV_64F );  // 8参数模型// 图像尺寸Size imageSize( 640, 480 );// 输出变量Mat R, T, E, F;vector< Mat > rvecs, tvecs;vector< float > perViewErrors;// 标定标志和终止条件int flags = CALIB_FIX_INTRINSIC;TermCriteria criteria( TermCriteria::COUNT + TermCriteria::EPS, 30, 1e-6 );// 执行立体相机标定double rms = stereoCalibrate( objectPoints,   // 输入的物体点imagePoints1,   // 第一个相机的图像点imagePoints2,   // 第二个相机的图像点cameraMatrix1,  // 第一个相机的内参矩阵distCoeffs1,    // 第一个相机的畸变系数cameraMatrix2,  // 第二个相机的内参矩阵distCoeffs2,    // 第二个相机的畸变系数imageSize,      // 图像尺寸R,              // 输出的旋转矩阵T,              // 输出的平移向量E,              // 输出的本质矩阵F,              // 输出的基础矩阵rvecs,          // 每个视图的旋转向量tvecs,          // 每个视图的平移向量perViewErrors,  // 每个视图的重投影误差flags,          // 标定标志criteria        // 终止条件);cout << "RMS re-projection error: " << rms << endl;cout << "Rotation Matrix:\n" << R << endl;cout << "Translation Vector:\n" << T << endl;cout << "Essential Matrix:\n" << E << endl;cout << "Fundamental Matrix:\n" << F << endl;// 可选:打印每个视图的重投影误差for ( size_t i = 0; i < perViewErrors.size(); ++i ){cout << "Reprojection error for view " << i << ": " << perViewErrors[ i ] << endl;}return 0;
}

运行结果

数据提供了就会有运行结果

http://www.lryc.cn/news/521647.html

相关文章:

  • 摄像头模块在狩猎相机中的应用
  • ruoyi-cloud docker启动微服务无法连接nacos,Client not connected, current status:STARTING
  • 代码随想录算法训练营第三十四天-动态规划-63. 不同路径II
  • 在一个sql select中作多个sum并分组
  • 家用电路频繁跳闸的原因及解决方法!
  • 我的年度总结
  • ASP.NET Core 多环境配置
  • docker 安装mongodb
  • 完整地实现了推荐系统的构建、实验和评估过程,为不同推荐算法在同一数据集上的性能比较提供了可重复实验的框架
  • DRV8311三相PWM无刷直流电机驱动器
  • Mysql--运维篇--备份和恢复(逻辑备份,mysqldump,物理备份,热备份,温备份,冷备份,二进制文件备份和恢复等)
  • 机器学习-归一化
  • Linux 串口检查状态的实用方法
  • Qt的核心机制概述
  • 微调神经机器翻译模型全流程
  • Cesium加载地形
  • gitlab runner正常连接 提示 作业挂起中,等待进入队列 解决办法
  • C#对动态加载的DLL进行依赖注入,并对DLL注入服务
  • HDMI接口
  • A/B 测试:玩转假设检验、t 检验与卡方检验
  • 第143场双周赛:最小可整除数位乘积 Ⅰ、执行操作后元素的最高频率 Ⅰ、执行操作后元素的最高频率 Ⅱ、最小可整除数位乘积 Ⅱ
  • 【STM32】LED状态翻转函数
  • uniapp 小程序 textarea 层级穿透,聚焦光标位置错误怎么办?
  • 汽车 SOA 架构下的信息安全新问题及对策漫谈
  • Unity-Mirror网络框架-从入门到精通之RigidbodyPhysics示例
  • 小程序如何引入腾讯位置服务
  • H3CNE-12-静态路由(一)
  • 多线程锁
  • ZooKeeper 核心知识全解析:架构、角色、节点与应用
  • 笔记本电脑 选购 回收 特权模式使用 指南