OpenCV相机标定与3D重建(41)从 3D 物点和它们对应的 2D 图像点估算初始相机内参矩阵函数initCameraMatrix2D()的使用
- 操作系统:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 编程语言:C++11
算法描述
从3D-2D点对应关系中找到一个初始的相机内参矩阵。
cv::initCameraMatrix2D 是 OpenCV 库中的一个函数,用于从 3D 物点和它们对应的 2D 图像点估算初始相机内参矩阵。该函数通常作为相机标定过程的一部分,为后续的标定提供一个合理的初始猜测。
函数原型
Mat cv::initCameraMatrix2D
(
InputArrayOfArrays objectPoints,
InputArrayOfArrays imagePoints,
Size imageSize,
double aspectRatio = 1.0
)
参数
- 参数objectPoints: 校准图案点在校准图案坐标空间中的向量的向量。在校准图案坐标系中,每个视图的点集组成一个向量,并且这些向量被组合成一个更大的向量。在旧接口中,所有每视图的向量都被连接起来。详见 calibrateCamera 的详细说明。
- 参数imagePoints: 校准图案点投影的向量的向量。在图像坐标系中,每个视图的点集组成一个向量,并且这些向量被组合成一个更大的向量。在旧接口中,所有每视图的向量都被连接起来。
- 参数imageSize: 用于初始化主点(光心)的图像尺寸(以像素为单位)。
- 参数aspectRatio: 如果它为零或负数,则 fx 和 fy 将独立估计。否则,fx = fy ⋅ aspectRatio。
该函数估计并返回一个用于相机标定过程的初始相机内参矩阵。目前,该函数仅支持平面校准图案,即每个物体点的 z 坐标 = 0。
返回值
Mat: 返回一个3x3的浮点数矩阵,表示初步估计的相机内参矩阵,形式如下:
c
a
m
e
r
a
M
a
t
r
i
x
=
[
f
x
0
c
x
0
f
y
c
y
0
0
1
]
\mathbf{cameraMatrix} = \left[ \begin{array}{ccc} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{array} \right]
cameraMatrix=
fx000fy0cxcy1
其中:
- f x f_x fx 和 f y f_y fy分别是沿 x 轴和 y 轴的焦距(以像素为单位)。
- c x c_x cx 和 c y c_y cy 是主点(光轴与图像平面交点)的位置。
代码示例
#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
int main()
{
// 假设的图像尺寸 (宽度, 高度)
Size imageSize( 640, 480 );
// 创建虚拟的3D物点(例如棋盘格角点)
vector< Point3f > objp;
int boardWidth = 9; // 棋盘格宽度
int boardHeight = 6; // 棋盘格高度
float squareSize = 1.0f; // 单位长度
for ( int i = 0; i < boardHeight; ++i )
{
for ( int j = 0; j < boardWidth; ++j )
{
objp.push_back( Point3f( j * squareSize, i * squareSize, 0 ) );
}
}
// 创建虚拟的2D图像点
vector< vector< Point2f > > imagePoints;
vector< vector< Point3f > > objectPoints;
Mat cameraMatrix = Mat::eye( 3, 3, CV_64F ); // 单位矩阵作为初始相机内参矩阵
Mat distCoeffs = Mat::zeros( 5, 1, CV_64F ); // 无畸变假设
RNG rng( 12345 ); // 使用随机数生成器
// 生成一组虚拟的视图
for ( size_t view = 0; view < 3; ++view )
{
// 创建一个虚拟的旋转和平移向量
Vec3f rvec = Vec3f( rng.uniform( -1.0, 1.0 ), rng.uniform( -1.0, 1.0 ), rng.uniform( -1.0, 1.0 ) );
Vec3f tvec = Vec3f( rng.uniform( -100, 100 ), rng.uniform( -100, 100 ), rng.uniform( 1000, 1500 ) );
// 投影3D点到2D图像平面上
vector< Point2f > projectedPoints;
projectPoints( objp, rvec, tvec, cameraMatrix, distCoeffs, projectedPoints );
// 添加到数据集中
imagePoints.push_back( projectedPoints );
objectPoints.push_back( objp );
}
// 初始化相机内参矩阵
Mat initialCameraMatrix = initCameraMatrix2D( objectPoints, imagePoints, imageSize, 1.0 );
cout << "Initial Camera Matrix with virtual data:\n" << initialCameraMatrix << endl;
return 0;
}
运行结果
Initial Camera Matrix with virtual data:
[460.1674038169938, 0, 319.5;
0, 460.1674038169938, 239.5;
0, 0, 1]