此代码是一个利用OpenCV库进行三路相机校准的C++程序。这个示例程序主要用于校准水平摆放的三台相机。
以下是关键函数及其功能的简要总结:
help(char** argv)
: 显示程序的使用方法。calcChessboardCorners(Size boardSize, float squareSize, vector<Point3f>& corners)
: 计算棋盘格角点的3D位置。run3Calibration(...)
: 运行三个相机的校准过程,包括单独校准每个相机和校准相机对(1,2)和(1,3)。readStringList(const string& filename, vector<string>& l)
: 从文件读取图像列表。main(int argc, char** argv)
: 程序的入口点。处理命令行参数,执行校准流程,并显示结果。
主要的类和方法:
类
Size
:表示图像或棋盘格的尺寸。类
Point3f
和Point2f
:分别表示3D点和2D图像点。类
Mat
:OpenCV的核心类,用于存储和处理图像数据。类
FileStorage
:用于读写XML或YAML格式的OpenCV数据文件。
程序的执行流程:
解析命令行参数,包括棋盘格尺寸、输出文件名等。
从文件读取图像列表并检查其合法性。
对每张图像检测棋盘格角点,并存储到相应的列表中。
调用
run3Calibration
函数对三个相机单独进行校准,然后对相机对进行立体校准,得到摄像机的矩阵和畸变系数,以及相机间的旋转和平移矩阵。使用
stereoCalibrate
函数获取立体校准的结果和相关参数。通过
rectify3Collinear
函数计算纠正相机图像畸变后的矩阵。使用
initUndistortRectifyMap
和remap
函数处理图像,消除畸变并进行矫正。显示矫正后的图像,并通过按键操作来退出图像显示。
最后,该程序将所有计算出的参数写入YAML格式的输出文件中。这些参数包括传感器的内参矩阵、畸变系数、旋转矩阵、投影矩阵和视差比率。这些参数对于计算机视觉和图像处理应用非常重要,可以用来纠正图像的畸变并将多个相机视图整合到同一坐标系中。
// 文件名: 3calibration.cpp -- 用于一起校准一条水平线上的3个相机的程序。
#include "opencv2/calib3d.hpp" // 包含OpenCV相机标定和三维重建相关功能的头文件
#include "opencv2/imgproc.hpp" // 包含OpenCV图像处理相关功能的头文件
#include "opencv2/imgcodecs.hpp" // 包含OpenCV图像编解码相关功能的头文件
#include "opencv2/highgui.hpp" // 包含OpenCV高级用户界面相关功能的头文件
#include "opencv2/core/utility.hpp" // 包含OpenCV核心功能(如命令行解析)相关的头文件
#include <stdio.h> // 包含标准输入输出相关功能的头文件
#include <string.h> // 包含C语言字符串操作相关功能的头文件
#include <time.h> // 包含C语言时间操作相关功能的头文件
using namespace cv; // 使用opencv命名空间
using namespace std; // 使用std命名空间
enum { DETECTION = 0, CAPTURING = 1, CALIBRATED = 2 }; // 定义枚举类型,用于描述相机的不同状态
static void help(char** argv) // 定义帮助函数,用于输出程序的用法说明
{
// 输出帮助信息,包含如何使用程序和各种命令行参数的说明
printf( "\nThis is a camera calibration sample that calibrates 3 horizontally placed cameras together.\n"
"Usage: %s\n"
" -w=<board_width> # the number of inner corners per one of board dimension\n"
" -h=<board_height> # the number of inner corners per another board dimension\n"
" [-s=<squareSize>] # square size in some user-defined units (1 by default)\n"
" [-o=<out_camera_params>] # the output filename for intrinsic [and extrinsic] parameters\n"
" [-zt] # assume zero tangential distortion\n"
" [-a=<aspectRatio>] # fix aspect ratio (fx/fy)\n"
" [-p] # fix the principal point at the center\n"
" [input_data] # input data - text file with a list of the images of the board\n"
"\n", argv[0] );
}
static void calcChessboardCorners(Size boardSize, float squareSize, vector<Point3f>& corners) // 定义函数计算棋盘角点
{
corners.resize(0); // 清空角点向量
// 使用嵌套循环按棋盘的格子顺序,计算每个内角点的世界坐标,存入角点向量中
for( int i = 0; i < boardSize.height; i++ )
for( int j = 0; j < boardSize.width; j++ )
corners.push_back(Point3f(float(j*squareSize),
float(i*squareSize), 0));
}
// 定义了三相机标定函数,输入为2D图像点,图像大小,棋盘大小,方格大小,纵横比等参数,输出为相机矩阵、
// 畸变系数以及两两相机之间的旋转和平移矩阵
static bool run3Calibration(vector<vector<Point2f> > imagePoints1,
vector<vector<Point2f> > imagePoints2,
vector<vector<Point2f> > imagePoints3,
Size imageSize, Size boardSize,
float squareSize, float aspectRatio,
int flags,
Mat& cameraMatrix1, Mat& distCoeffs1,
Mat& cameraMatrix2, Mat& distCoeffs2,
Mat& cameraMatrix3, Mat& distCoeffs3,
Mat& R12, Mat& T12, Mat& R13, Mat& T13)
{
int c, i;
// step 1: 分别校准每个相机
vector<vector<Point3f> > objpt(1); // 定义对象点的向量(3D点)
vector<vector<Point2f> > imgpt; // 定义图像点的向量(2D点)
calcChessboardCorners(boardSize, squareSize, objpt[0]); // 计算每个棋盘角的三维点
vector&