视频网站后台管理系统,短网址赚钱平台,衡阳城乡建设局网站,岳阳云溪区建设局网站操作系统#xff1a;ubuntu22.04 OpenCV版本#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言#xff1a;C11
算法描述
为已校准的立体相机的每个头计算校正变换。 cv::stereoRectify 是 OpenCV 中用于立体校正的函数#xff0c;它基于已知的相机参数和相对位置ubuntu22.04 OpenCV版本OpenCV4.9 IDE:Visual Studio Code 编程语言C11
算法描述
为已校准的立体相机的每个头计算校正变换。 cv::stereoRectify 是 OpenCV 中用于立体校正的函数它基于已知的相机参数和相对位置通过 cv::stereoCalibrate 或其他方法获得计算出两个相机的投影矩阵和重映射变换使得从两个相机获取的图像能够被矫正为仿佛它们是并排且光学轴平行的状态。这样做的目的是为了简化后续的视差图计算。
函数原型
void cv::stereoRectify
(InputArray cameraMatrix1,InputArray distCoeffs1,InputArray cameraMatrix2,InputArray distCoeffs2,Size imageSize,InputArray R,InputArray T,OutputArray R1,OutputArray R2,OutputArray P1,OutputArray P2,OutputArray Q,int flags CALIB_ZERO_DISPARITY,double alpha -1,Size newImageSize Size(),Rect * validPixROI1 0,Rect * validPixROI2 0
)
参数
参数cameraMatrix1第一个相机的内参矩阵。参数distCoeffs1第一个相机的畸变参数。参数cameraMatrix2第二个相机的内参矩阵。参数distCoeffs2第二个相机的畸变参数。参数imageSize用于立体校准的图像尺寸。参数R从第一个相机坐标系到第二个相机坐标系的旋转矩阵详见 stereoCalibrate。参数T从第一个相机坐标系到第二个相机坐标系的平移向量详见 stereoCalibrate。参数R1第一个相机的输出3x3校正变换旋转矩阵。该矩阵将未校正的第一个相机坐标系中的点转换为校正后的第一个相机坐标系中的点。更技术性地说它执行了从未校正的第一个相机坐标系到校正后的第一个相机坐标系的基础变换。参数R2第二个相机的输出3x3校正变换旋转矩阵。该矩阵将未校正的第二个相机坐标系中的点转换为校正后的第二个相机坐标系中的点。同样地它执行了从未校正的第二个相机坐标系到校正后的第二个相机坐标系的基础变换。参数P1第一个相机在新的校正后坐标系中的输出3x4投影矩阵即它将校正后的第一个相机坐标系中的点投影到校正后的第一个相机的图像中。参数P2第二个相机在新的校正后坐标系中的输出3x4投影矩阵即它将校正后的第一个相机坐标系中的点投影到校正后的第二个相机的图像中。参数Q输出4×4视差到深度映射矩阵见 reprojectImageTo3D。参数flags操作标志可以是零或 CALIB_ZERO_DISPARITY。如果设置了该标志则函数会使每个相机的主点在校正后的视图中具有相同的像素坐标。如果没有设置该标志函数可能会沿水平或垂直方向取决于极线的方向移动图像以最大化有用图像区域。参数alpha自由缩放参数。如果它是 -1 或未指定函数将执行默认缩放。否则参数应在 0 和 1 之间。alpha0 表示校正后的图像被缩放和移动使得只有有效的像素可见校正后没有黑色区域。alpha1 表示校正后的图像被减少和移动使得来自原始图像的所有像素都保留在校正后的图像中不丢失源图像像素。任何中间值都会产生这两个极端情况之间的中间结果。参数newImageSize校正后的新图像分辨率。应该传递给 initUndistortRectifyMap见 OpenCV 示例目录中的 stereo_calib.cpp 样本。当传递 (0,0)默认值时它被设置为原始 imageSize。设置为更大的值可以帮助保留原始图像中的细节尤其是在存在较大径向畸变的情况下。参数validPixROI1可选输出矩形在校正后的图像中包含所有有效像素的区域。如果 alpha0则 ROI 覆盖整个图像。否则它们可能较小见下图。参数validPixROI2同上适用于第二个相机。
该函数计算每个相机的旋转矩阵这些矩阵虚拟地使两个相机的图像平面成为同一平面。因此这使得所有的极线平行从而简化了密集立体对应问题。函数以 stereoCalibrate 计算的矩阵作为输入并提供两个旋转矩阵以及两个新坐标系中的投影矩阵作为输出。根据相机的相对位置函数区分以下两种情况 水平立体 第一个和第二个相机视图主要沿 x 轴相对偏移可能有小的垂直偏移。在校正后的图像中左右相机中的对应极线是水平的并且具有相同的 y 坐标。P1 和 P2 的形式如下 P1 [ f 0 c x 1 0 0 f c y 0 0 0 1 0 ] \texttt{P1} \begin{bmatrix} f 0 cx_1 0 \\ 0 f cy 0 \\ 0 0 1 0 \end{bmatrix} P1 f000f0cx1cy1000 P2 [ f 0 c x 2 T x ⋅ f 0 f c y 0 0 0 1 0 ] , \texttt{P2} \begin{bmatrix} f 0 cx_2 T_x \cdot f \\ 0 f cy 0 \\ 0 0 1 0 \end{bmatrix} , P2 f000f0cx2cy1Tx⋅f00 , Q [ 1 0 0 − c x 1 0 1 0 − c y 0 0 0 f 0 0 − 1 T x c x 1 − c x 2 T x ] \texttt{Q} \begin{bmatrix} 1 0 0 -cx_1 \\ 0 1 0 -cy \\ 0 0 0 f \\ 0 0 -\frac{1}{T_x} \frac{cx_1 - cx_2}{T_x} \end{bmatrix} Q 10000100000−Tx1−cx1−cyfTxcx1−cx2 其中 Tx 是相机之间的水平偏移如果设置了 CALIB_ZERO_DISPARITY则cx1cx2。
垂直立体 第一个和第二个相机视图主要沿垂直方向相对偏移可能有一点水平偏移。在校正后的图像中极线是垂直的并且具有相同的 x 坐标。P1 和 P2 的形式如下 P1 [ f 0 c x 0 0 f c y 1 0 0 0 1 0 ] \texttt{P1} \begin{bmatrix} f 0 cx 0 \\ 0 f cy_1 0 \\ 0 0 1 0 \end{bmatrix} P1 f000f0cxcy11000 P2 [ f 0 c x 0 0 f c y 2 T y ⋅ f 0 0 1 0 ] , \texttt{P2} \begin{bmatrix} f 0 cx 0 \\ 0 f cy_2 T_y \cdot f \\ 0 0 1 0 \end{bmatrix}, P2 f000f0cxcy210Ty⋅f0 , Q [ 1 0 0 − c x 0 1 0 − c y 1 0 0 0 f 0 0 − 1 T y c y 1 − c y 2 T y ] \texttt{Q} \begin{bmatrix} 1 0 0 -cx \\ 0 1 0 -cy_1 \\ 0 0 0 f \\ 0 0 -\frac{1}{T_y} \frac{cy_1 - cy_2}{T_y} \end{bmatrix} Q 10000100000−Ty1−cx−cy1fTycy1−cy2
其中 Ty 是相机之间的垂直偏移如果设置了 CALIB_ZERO_DISPARITY则cy1cy2。
可以看到P1 和 P2 的前三列实际上会成为新的“校正”相机矩阵。这些矩阵连同 R1 和 R2 可以传递给 initUndistortRectifyMap 来初始化每个相机的校正映射。
示例截图 下面是来自 stereo_calib.cpp 示例的截图。一些红色水平线通过对应的图像区域这意味着图像已经很好地进行了校正这是大多数立体对应算法所依赖的。绿色矩形是 roi1 和 roi2。可以看到它们内部都是有效的像素。
代码示例
#include iostream
#include opencv2/opencv.hpp
#include vectorusing namespace cv;
using namespace std;// 生成测试图像函数
void generateTestImages( Size imageSize, Mat img1, Mat img2 )
{img1 Mat::zeros( imageSize, CV_8UC3 );img2 Mat::zeros( imageSize, CV_8UC3 );// 在第一张图像上画水平线在第二张图像上画稍微偏移的水平线模拟立体图像for ( int y 50; y imageSize.height; y 50 ){line( img1, Point( 0, y ), Point( imageSize.width, y ), Scalar( 0, 255, 0 ), 2 );line( img2, Point( 0, y 10 ), Point( imageSize.width, y 10 ), Scalar( 0, 255, 0 ), 2 );}
}int main()
{// 假设我们已经有以下数据来自 stereoCalibrate 或其他来源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( 5, 1, CV_64F ); // 简化的畸变系数模型Mat distCoeffs2 Mat::zeros( 5, 1, CV_64F );// 假定的旋转和平移矩阵根据实际情况调整Mat R ( Mat_ double ( 3, 3 ) 0.999, 0.001, -0.044, -0.002, 0.998, 0.061, 0.044, -0.061, 0.998 );Mat T ( Mat_ double ( 3, 1 ) 60.0, 0.0, 0.0 ); // 假设两个相机沿X轴平移了60个单位Size imageSize( 640, 480 ); // 图像尺寸// 输出变量Mat R1, R2; // 校正后的旋转矩阵Mat P1, P2; // 新的投影矩阵Mat Q; // 视差到深度映射矩阵Rect validPixROI1, validPixROI2; // 有效像素区域// 操作标志和自由缩放参数int flags CALIB_ZERO_DISPARITY;double alpha -1;Size newImageSize imageSize; // 使用原始图像尺寸// 执行立体校正stereoRectify( cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R, T, R1, R2, P1, P2, Q, flags, alpha, newImageSize, validPixROI1, validPixROI2 );cout Rectification matrices for the first camera:\n R1 endl;cout Rectification matrices for the second camera:\n R2 endl;cout Projection matrix for the first camera:\n P1 endl;cout Projection matrix for the second camera:\n P2 endl;cout Disparity-to-depth mapping matrix:\n Q endl;// 初始化重映射Mat map1x, map1y, map2x, map2y;initUndistortRectifyMap( cameraMatrix1, distCoeffs1, R1, P1, newImageSize, CV_32FC1, map1x, map1y );initUndistortRectifyMap( cameraMatrix2, distCoeffs2, R2, P2, newImageSize, CV_32FC1, map2x, map2y );// 生成一对测试图像Mat img1, img2;generateTestImages( imageSize, img1, img2 );// 应用重映射Mat rectifiedImg1, rectifiedImg2;remap( img1, rectifiedImg1, map1x, map1y, INTER_LINEAR );remap( img2, rectifiedImg2, map2x, map2y, INTER_LINEAR );// 显示结果imshow( Original Image 1, img1 );imshow( Original Image 2, img2 );imshow( Rectified Image 1, rectifiedImg1 );imshow( Rectified Image 2, rectifiedImg2 );waitKey( 0 ); // 等待按键关闭窗口return 0;
}运行结果 命令行输出
Rectification matrices for the first camera:
[0.9990327505785522, 0.002838302200161476, -0.0438806029137316;-0.001498542304358349, 0.9995325828506972, 0.03053473744403527;0.04394675917987673, -0.03043944579710149, 0.9985700388541362]
Rectification matrices for the second camera:
[1, 2.782197548109867e-17, -9.101507439329915e-16;-4.437342568756724e-17, 0.9995349355631407, -0.03049446816700398;9.047190730013251e-16, 0.03049446816700397, 0.9995349355631405]
Projection matrix for the first camera:
[521, 0, 340.8940467834473, 0;0, 521, 249.6826610565186, 0;0, 0, 1, 0]
Projection matrix for the second camera:
[521, 0, 340.8940467834473, 31260;0, 521, 249.6826610565186, 0;0, 0, 1, 0]
Disparity-to-depth mapping matrix:
[1, 0, 0, -340.8940467834473;0, 1, 0, -249.6826610565186;0, 0, 0, 521;0, 0, -0.01666666666666667, 0]