双目视觉主要步骤:相机标定--立体校正--立体匹配

1、双目相机标定:

stereoCalibrate(objectPoints, imagePoints1, imagePoints2, cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R=None, T=None, E=None, F=None, flags=None, criteria=None)

# 参数含义
objectPoints- vector<point3f> 型的数据结构,存储标定角点在世界坐标系中的位置
imagePoints1- vector<vector<point2f>> 型的数据结构,存储标定角点在第一个摄像机下的投影后的亚像素坐标
imagePoints2- vector<vector<point2f>> 型的数据结构,存储标定角点在第二个摄像机下的投影后的亚像素坐标
cameraMatrix1-输入/输出型的第一个摄像机的相机矩阵。如果CV_CALIB_USE_INTRINSIC_GUESS , CV_CALIB_FIX_ASPECT_RATIO ,CV_CALIB_FIX_INTRINSIC , or CV_CALIB_FIX_FOCAL_LENGTH其中的一个或多个标志被设置,该摄像机矩阵的一些或全部参数需要被初始化
distCoeffs1-第一个摄像机的输入/输出型畸变向量。根据矫正模型的不同,输出向量长度由标志决定
cameraMatrix2-输入/输出型的第二个摄像机的相机矩阵。参数意义同第一个相机矩阵相似
distCoeffs2-第一个摄像机的输入/输出型畸变向量。根据矫正模型的不同,输出向量长度由标志决定
imageSize-图像的大小
R-输出型,第一和第二个摄像机之间的旋转矩阵
T-输出型,第一和第二个摄像机之间的平移矩阵
E-输出型,基本矩阵
F-输出型,基础矩阵
term_crit-迭代优化的终止条件
flag-
 CV_CALIB_FIX_INTRINSIC 如果该标志被设置,那么就会固定输入的cameraMatrix和distCoeffs不变,只求解R,T,E,F
 CV_CALIB_USE_INTRINSIC_GUESS 根据用户提供的cameraMatrix和distCoeffs为初始值开始迭代
 CV_CALIB_FIX_PRINCIPAL_POINT 迭代过程中不会改变主点的位置
 CV_CALIB_FIX_FOCAL_LENGTH 迭代过程中不会改变焦距
 CV_CALIB_SAME_FOCAL_LENGTH 强制保持两个摄像机的焦距相同
 CV_CALIB_ZERO_TANGENT_DIST 切向畸变保持为零
 CV_CALIB_FIX_K1,...,CV_CALIB_FIX_K6 迭代过程中不改变相应的值。如果设置了 CV_CALIB_USE_INTRINSIC_GUESS 将会使用用户提供的初始值,否则设置为零
 CV_CALIB_RATIONAL_MODEL 畸变模型的选择,如果设置了该参数,将会使用更精确的畸变模型,distCoeffs的长度就会变成8


2、立体校正

void 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 )

1、cameraMatrix1-第一个摄像机的摄像机矩阵,即左相机相机内参矩阵,矩阵第三行格式应该为 0 0 1
2、distCoeffs1-第一个摄像机的畸变向量
3、cameraMatrix2-第一个摄像机的摄像机矩阵,即右相机相机内参矩阵,矩阵第三行格式应该为 0 0 1
4、distCoeffs2-第二个摄像机的畸变向量
5、imageSize-图像大小
6、R- 相机之间的旋转矩阵,这里R的意义是:相机1通过变换R到达相机2的位姿
7、T-  左相机到右相机的平移矩阵
8、R1-输出矩阵,第一个摄像机的校正变换矩阵(旋转变换)
9、R2-输出矩阵,第二个摄像机的校正变换矩阵(旋转矩阵)
10、P1-输出矩阵,第一个摄像机在新坐标系下的投影矩阵
11、P2-输出矩阵,第二个摄像机在想坐标系下的投影矩阵
12、Q-4*4的深度差异映射矩阵
13、flags-可选的标志有两种零或者 CV_CALIB_ZERO_DISPARITY ,如果设置 CV_CALIB_ZERO_DISPARITY 的话,该函数会让两幅校正后的图像的主点有相同的像素坐标。否则该函数会水平或垂直的移动图像,以使得其有用的范围最大
alpha-拉伸参数。如果设置为负或忽略,将不进行拉伸。如果设置为0,那么校正后图像只有有效的部分会被显示(没有黑色的部分),如果设置为1,那么就会显示整个图像。设置为0~1之间的某个值,其效果也居于两者之间。
14、newImageSize-校正后的图像分辨率,默认为原分辨率大小。
15、validPixROI1-可选的输出参数,Rect型数据。其内部的所有像素都有效
16、validPixROI2-可选的输出参数,Rect型数据。其内部的所有像素都有效

3、立体匹配

cv2.StereoSGBM_create([,minDisparity [,numDisparities [,blockSize [,P1 [,P2 [,disp12MaxDiff [,preFilterCap [,uniquenessRatio [,speckleWindowSize [,speckleRange [,mode]]]]]]]]]]]])

minDisparity最小可能的差异值。通常情况下,它是零,但有时整流算法可能会改变图像,所以这个参数需要作相应的调整。numDisparities最大差异减去最小差异。该值总是大于零。在当前的实现中,该参数必须可以被16整除。BLOCKSIZE匹配的块大小。它必须是> = 1的奇数。通常情况下,它应该在3..11的范围内。P1控制视差平滑度的第一个参数。见下文。P2第二个参数控制视差平滑度。值越大,差异越平滑。P1是相邻像素之间的视差变化加或减1的惩罚。P2是相邻像素之间的视差变化超过1的惩罚。该算法需要P2> P1。请参见stereo_match.cpp示例,其中显示了一些相当好的P1和P2值(分别为8 * number_of_image_channels * SADWindowSize * SADWindowSize和32 * number_of_image_channels * SADWindowSize * SADWindowSize)。disp12MaxDiff左右视差检查中允许的最大差异(以整数像素为单位)。将其设置为非正值以禁用检查。preFilterCap预滤波图像像素的截断值。该算法首先计算每个像素的x导数,并通过[-preFilterCap,preFilterCap]间隔剪切其值。结果值传递给Birchfield-Tomasi像素成本函数。uniquenessRatio最佳(最小)计算成本函数值应该“赢”第二个最佳值以考虑找到的匹配正确的百分比保证金。通常,5-15范围内的值就足够了。speckleWindowSize平滑视差区域的最大尺寸,以考虑其噪声斑点和无效。将其设置为0可禁用斑点过滤。否则,将其设置在50-200的范围内。speckleRange每个连接组件内的最大视差变化。如果你做斑点过滤,将参数设置为正值,它将被隐式乘以16.通常,1或2就足够好了。mode将其设置为StereoSGBM :: MODE_HH以运行全尺寸双通道动态编程算法。它将消耗O(W * H * numDisparities)字节,这对640x480立体声很大,对于HD尺寸的图片很大。默认情况下,它被设置为false。