上一个教程 : 创建标定图案
下一个教程 : 使用 OpenCV 标定相机
原作者 | Victor Eruhimov |
---|---|
兼容性 | OpenCV >= 4.0 |
本教程的目的是学习如何根据一组棋盘图像标定相机。
测试数据:使用 data/chess 文件夹中的图像。
- 在 cmake 配置中将 BUILD_EXAMPLES 设为 ON,编译 OpenCV 样本。
- 进入 bin 文件夹,使用 imagelist_creator 创建一个 XML/YAML 图像列表。
- 然后,运行校准示例获取相机参数。使用等于 3 厘米的正方形尺寸。
姿态估计
现在,让我们编写代码,检测图像中的棋盘并找出它与摄像头的距离。您可以将此方法应用于在图像中检测到的任何具有已知 3D 几何形状的物体。
测试数据:使用数据文件夹中的 chess_test*.jpg 图像。
- 创建一个空的控制台项目。加载测试图像:
Mat img = imread(argv[1], IMREAD_GRAYSCALE);
- 使用 findChessboard 函数检测图像中的棋盘:
bool found = findChessboardCorners( img, boardSize, ptvec, CALIB_CB_ADAPTIVE_THRESH );
- 现在,编写一个函数,在任意坐标系下生成一个包含棋盘 3d 坐标的向量
<Point3f>
数组。为简单起见,让我们选择这样一个坐标系,即棋盘的一个角位于原点,棋盘位于 z = 0 平面上。 - 从 XML/YAML 文件中读取摄像机参数:
FileStorage fs( 文件名, FileStorage::READ );
Mat intrinsics, distortion;
fs["camera_matrix"] >> intrinsics;
fs["distortion_coefficients"] >> distortion;
- 现在我们可以通过运行
solvePnP
来找到棋盘的姿势了:
vector<Point3f> boardPoints;
// 填充数组
...
solvePnP(Mat(boardPoints), Mat(foundBoardCorners), cameraMatrix、
distCoeffs,rvec,tvec,false);
- 计算重投影误差,就像在校准示例中那样(参见 opencv/samples/cpp/calibration.cpp,函数 computeReprojectionErrors)。
问:如何计算从摄像机原点到任意一个角的距离?答:由于我们的图像位于三维空间中,因此我们需要计算从摄像机原点到任何一个角的距离: 由于图像位于三维空间中,我们首先要计算摄像机的相对姿态。这样就可以得到三维到二维的对应关系。然后,我们可以应用简单的 L2 准则来计算任意点(角的端点)之间的距离。