正确使用StereoRectify

双目矫正的使用

cv::fisheye::StereoRectify()函数, 主要用于对双目图像做出矫正,计算出用于立体矫正的参数;具体的使用方法如下:


void cv::fisheye::stereoRectify	(InputArray K1,InputArray D1,
                                 InputArray K2, InputArray D2,
                                 const Size &imageSize, InputArray R, 
                                 InputArray tvec, 
                                 OutputArray 	R1,OutputArray 	R2,
                                 OutputArray P1, OutputArray P2, OutputArray Q, 
                                 int flags, const Size &newImageSize = Size(), 
                                 double balance = 0.0, double fov_scale = 1.0)	

其中参数的含义如下:

K1第一个相机的内参,Size为3x3, 数据类型为CV_32F 或者 CV_64F
D1第一个相机的畸变参数, Size必须为4x1, 数据类型为CV_32F 或者 CV_64F
K2第二个相机的内参,Size为3x3, 数据类型为CV_32F 或者 CV_64F
D2第二个相机的畸变参数, Size必须为4x1, 数据类型为CV_32F 或者 CV_64F
imageSize做双目标定StereoCalibration() 时用的图片的size, 如ImageSize = cv::Size(640,480)
R两个相机之间的旋转矩阵, Rrl, 如果内参采用Kalibr标定, 那么这里的R就是Kalibr标定出的T的前3x3
tvec两个相机之间的平移向量,trl, 即为左目相机在右目相机坐标系中的坐标, 所以,如果两个相机左右摆放, 该向量中x值一般为负数;
R1第一个相机的修正矩阵, 即从实际去畸变后的左目摆放位姿到经过极线矫正后的左目位姿之间, 有一个旋转量,为R1
R2第二个相机的修正矩阵, 即从实际去畸变后的右目摆放位姿到经过极线矫正后的右目位姿之间, 有一个旋转量,为R2
P1修正后第一个相机的投影矩阵; P1包含了R1和K1, 可直接将左目相机坐标系的三维点,投影到像素坐标系中; 要注意会投影到修正后的图像中
P2修正后第二个相机的投影矩阵; P2包含了R2和K2, 可直接将左目相机坐标系的三维点,投影到像素坐标系中; 要注意会投影到修正后的图像中
Q视差图转换成深度图的矩阵; 
flagsOperation flags that may be zero or fisheye::CALIB_ZERO_DISPARITY . If the flag is set, the function makes the principal points of each camera have the same pixel coordinates in the rectified views. And if the flag is not set, the function may still shift the images in the horizontal or vertical direction (depending on the orientation of epipolar lines) to maximize the useful image area.
newImageSize修正后图像的新Size.  该参数应该与下一步使用initUndistortRectifyMap()时所使用的iMAGE SIZE一致. 默认为 (0,0), 表示和 imageSize 一致. 当图像的径向畸变较严重时, 这个值设置的大一点,可以更好地保留一个细节;  (see the stereo_calib.cpp sample in OpenCV samples directory)
balance值在[0,1]之间, 设置这个值可以改变新图像的focal length, 从最小值到最大值之间变动;
fov_scale新的focal length = original focal length/ fov_scale

遇到的一些问题:

 Assertion failed (D.empty() || ((D.total() == 4) && (D.depth() == 5 || D.depth() == 6))) in estimateNewCameraMatrixForUndistortRectify, file Downloads/opencv-3.4.0/modules/calib3d/src/fisheye.cpp, line 545

问题的原因就是括号里的内容, 按照函数的要求D应该是4x1的Mat, 但是我实际输入的是5x1, 所以出错;

具体原因也可以到提示中的源码里查找, 找到出错的地方即为estimateNewCameraMatrixForUndistortRectify() 里面; 

void cv::fisheye::estimateNewCameraMatrixForUndistortRectify(InputArray K, InputArray D, const Size &image_size, InputArray R,
    OutputArray P, double balance, const Size& new_size, double fov_scale)
{
    CV_INSTRUMENT_REGION();

    CV_Assert( K.size() == Size(3, 3)       && (K.depth() == CV_32F || K.depth() == CV_64F));
    CV_Assert(D.empty() || ((D.total() == 4) && (D.depth() == CV_32F || D.depth() == CV_64F)));
}

Mat相关的小细节

Mat::depth 返回一个矩阵元素的深度; 返回值只能是标识符, 具体类型对应的标识符如下:

// <interface.h>
#define CV_8U   0  //8位无符号整数 (0…..255)
#define CV_8S   1  //8位符号整数   (-128...127)
#define CV_16U  2  //16位无符号整数 (0...65535)
#define CV_16S  3  //16位符号整数 (-32768...32767)
#define CV_32S  4  //32为符号整数 (-2147483648...2147483648)
#define CV_32F  5  //32位浮点数  (-FLT_MAX...FLX_MAX)
#define CV_64F  6  //64位浮点数  (-DBL_MAX...DBL_MAX)
#define CV_16F  7  //16位浮点数

Mat::total 返回数组元素的总数; 

如4x1的矩阵会返回4; 3x2的矩阵会返回6;

最后, 举个栗子:

//设定左目内参和畸变参数: 分别是3x3和4x1
Mat cameraMatrixL =(Mat_<double>(3, 3) << 216.0891385028069, 0., 319.19103592168216, 0.,286.915780332698, 237.28788884900933, 0., 0., 1.);

Mat distCoeffL =(Mat_<double>(4, 1) << 0.16031814840882294, 0.09948097914060017,
                                      -0.05647543763319335, 0.02313587059407878);
//设定右目内参和畸变参数: 分别是3x3和4x1
Mat cameraMatrixR =(Mat_<double>(3, 3) << 216.47145152004367, 0., 319.57751832884156, 0.,287.23866506549973, 240.30796467665027, 0., 0., 1.);

Mat distCoeffR = (Mat_<double>(4, 1) << 0.15400500709721424, 0.109194432654468,
                                      -0.06512886784397008, 0.025788980687450808);
//设定两个相机之间的旋转和平移, R为Rrl
Mat R = (Mat_<double>(3, 3) << 
        0.9998867545031103, -0.007295111520593036,0.013162808102250304, 
        0.007472043953567141, 0.9998817186236534,-0.01344311427322331, 
        -0.013063182169384159, 0.013539944981760093,0.9998229959155261);
//从平移的数值应该能看出来, t为 左目相机在右目相机的坐标系中的位置
Mat T = (Mat_<double>(3, 1) << 
        -0.10139343341319906, -0.0003237508769501881,0.0013986876758678593);

Mat Rl, Rr, Pl, Pr, Q;

cv::fisheye::stereoRectify(cameraMatrixL, distCoeffL, cameraMatrixR, distCoeffR, imageSize,R, T, Rl, Rr, Pl, Pr, Q, CALIB_ZERO_DISPARITY, imageSize);
//使用R1,P1输出两个映射矩阵
cv::fisheye::initUndistortRectifyMap(cameraMatrixL, distCoeffL, Rl, Pl, 
                                     imageSize,CV_32FC1, mapLx, mapLy);
//使用R2,P2输出两个映射矩阵
cv::fisheye::initUndistortRectifyMap(cameraMatrixR, distCoeffR, Rr, Pr, 
                                     imageSize,V_32FC1, mapRx, mapRy);
Mat ImageL, ImageR;
ImageL = cv::imread("left.png",-1);
ImageR = cv::imread("right.png", -1);
//将双目矫正后的图像放入rectifyImageL2和rectifyImageR2中
Mat rectifyImageL2, rectifyImageR2;
cv::remap(ImageL, rectifyImageL2, mapLx, mapLy, cv::INTER_LINEAR);
cv::remap(ImageR, rectifyImageR2, mapRx, mapRy, cv::INTER_LINEAR);

tips:

在使用的时候一定要注意自己使用的是cv::fisheye::StereoRectify()函数, 还是cv::StereoRectify(), 这点很重要, 因为函数不同,所使用的畸变模型是不一样的;

  • 12
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值