initUndistortRectifyMap源码解析

本文详细介绍了OpenCV中的initUndistortRectifyMap函数,包括参数解析、内部计算过程,涉及到相机内参、旋转矩阵、畸变矫正等多个关键步骤,帮助理解图像畸变矫正的实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

void cv::initUndistortRectifyMap( InputArray _cameraMatrix, InputArray _distCoeffs,
                              InputArray _matR, InputArray _newCameraMatrix,
                              Size size, int m1type, OutputArray _map1, OutputArray _map2 )
{
    //相机内参、畸变矩阵
    Mat cameraMatrix = _cameraMatrix.getMat(), distCoeffs = _distCoeffs.getMat();
    //旋转矩阵、摄像机参数矩阵
    Mat matR = _matR.getMat(), newCameraMatrix = _newCameraMatrix.getMat();

    if( m1type <= 0 )
        m1type = CV_16SC2;
    CV_Assert( m1type == CV_16SC2 || m1type == CV_32FC1 || m1type == CV_32FC2 );
    _map1.create( size, m1type );
    Mat map1 = _map1.getMat(), map2;
    if( m1type != CV_32FC2 )
    {
        _map2.create( size, m1type == CV_16SC2 ? CV_16UC1 : CV_32FC1 );
        map2 = _map2.getMat();
    }
    else
        _map2.release();

    Mat_<double> R = Mat_<double>::eye(3, 3);
    //A为相机内参
    Mat_<double> A = Mat_<double>(cameraMatrix), Ar;
initUndistortRectifyMap 是OpenCV中的一个函数,用于计算相机的畸变矫正映射。以下是该函数的源代码实现(版本为OpenCV 4.5.2): ```c++ void cv::initUndistortRectifyMap( InputArray cameraMatrix, InputArray distCoeffs, InputArray R, InputArray newCameraMatrix, Size size, int m1type, OutputArray map1, OutputArray map2) { Mat cameraMatrixMat = cameraMatrix.getMat(), RMat = R.getMat(), newCameraMatrixMat = newCameraMatrix.getMat(); CV_Assert( cameraMatrixMat.type() == CV_64FC1 || cameraMatrixMat.type() == CV_32FC1 ); CV_Assert( distCoeffs.empty() || distCoeffs.type() == CV_64FC1 || distCoeffs.type() == CV_32FC1 ); CV_Assert( RMat.empty() || RMat.type() == CV_64FC1 || RMat.type() == CV_32FC1 ); CV_Assert( newCameraMatrixMat.type() == CV_64FC1 || newCameraMatrixMat.type() == CV_32FC1 ); CV_Assert( m1type == CV_16SC2 || m1type == CV_32FC1 || m1type < 0 ); if( !map1.needed() && !map2.needed() ) return; map1.create(size, m1type); Mat map1Mat = map1.getMat(); map2.create(size, m1type == CV_16SC2 ? CV_16UC1 : m1type); Mat map2Mat = map2.getMat(); Mat_<double> A, Ar, I = Mat_<double>::eye(3,3); cameraMatrixMat.convertTo(A, CV_64F); newCameraMatrixMat.convertTo(Ar, CV_64F); Mat_<double> Rmat; R.convertTo(Rmat, CV_64F); if( distCoeffs.empty() ) distCoeffs = Mat_<double>::zeros(1, 5); Mat distCoeffsMat = distCoeffs.getMat(); if (CV_MAT_DEPTH(m1type) == CV_32F) { float* map1f = map1Mat.ptr<float>(); float* map2f = map2Mat.ptr<float>(); double v0 = A(1, 2), inv_f = 1./A(0, 0); double _a = Ar(0, 0), _b = Ar(0, 1), _c = Ar(0, 2), _d = Ar(1, 0), _e = Ar(1, 1), _f = Ar(1, 2), _g = Ar(2, 0), _h = Ar(2, 1), _i = Ar(2, 2); double k1 = distCoeffsMat.at<double>(0, 0); double k2 = distCoeffsMat.at<double>(0, 1); double k3 = distCoeffsMat.at<double>(0, 4); double k4 = distCoeffsMat.rows + distCoeffsMat.cols - 1 >= 7 ? distCoeffsMat.at<double>(0, 2) : 0.; double k5 = distCoeffsMat.rows + distCoeffsMat.cols - 1 >= 8 ? distCoeffsMat.at<double>(0, 3) : 0.; for( int i = 0; i < size.height; ++i) { float* map1fi = map1f + i*size.width; float* map2fi = map2f + i*size.width; double y = (i + 0.5 - v0)*inv_f; for( int j = 0; j < size.width; ++j) { double x = (j + 0.5 - A(0, 2))*inv_f; double x0 = x, y0 = y, x02, y02; if( k1 != 0 || k2 != 0 || k3 != 0 || k4 != 0 || k5 != 0 ) { double r2 = x*x + y*y, _2xy = 2*x*y; double radial = 1 + r2*(k1 + r2*(k2 + r2*k3)); x0 = x*radial + k4*_2xy + k5*(r2 + 2*x*x); y0 = y*radial + k4*(r2 + 2*y*y) + k5*_2xy; } x02 = x0*_a + y0*_b + _c; y02 = x0*_d + y0*_e + _f; map1fi[j] = (float)x02; map2fi[j] = (float)y02; } } } else { short* map1s = map1Mat.ptr<short>(); ushort* map2s = map2Mat.ptr<ushort>(); double v0 = A(1, 2), inv_f = 1./A(0, 0); double _a = Ar(0, 0), _b = Ar(0, 1), _c = Ar(0, 2), _d = Ar(1, 0), _e = Ar(1, 1), _f = Ar(1, 2), _g = Ar(2, 0), _h = Ar(2, 1), _i = Ar(2, 2); double k1 = distCoeffsMat.at<double>(0, 0); double k2 = distCoeffsMat.at<double>(0, 1); double k3 = distCoeffsMat.at<double>(0, 4); double k4 = distCoeffsMat.rows + distCoeffsMat.cols - 1 >= 7 ? distCoeffsMat.at<double>(0, 2) : 0.; double k5 = distCoeffsMat.rows + distCoeffsMat.cols - 1 >= 8 ? distCoeffsMat.at<double>(0, 3) : 0.; for( int i = 0; i < size.height; ++i) { short* map1si = map1s + i*size.width*2; ushort* map2si = map2s + i*size.width; double y = (i + 0.5 - v0)*inv_f; for( int j = 0; j < size.width; ++j) { double x = (j + 0.5 - A(0, 2))*inv_f; double x0 = x, y0 = y, x02, y02; if( k1 != 0 || k2 != 0 || k3 != 0 || k4 != 0 || k5 != 0 ) { double r2 = x*x + y*y, _2xy = 2*x*y; double radial = 1 + r2*(k1 + r2*(k2 + r2*k3)); x0 = x*radial + k4*_2xy + k5*(r2 + 2*x*x); y0 = y*radial + k4*(r2 + 2*y*y) + k5*_2xy; } x02 = x0*_a + y0*_b + _c; y02 = x0*_d + y0*_e + _f; map1si[j*2] = (short)(x02*map1Mat.cols); map1si[j*2+1] = (short)(y02*map1Mat.rows); map2si[j] = saturate_cast<ushort>(sqrt(x*x + y*y)*newCameraMatrixMat.at<double>(0, 0) + 0.5); } } } } ``` 该函数的输入参数包括:相机内参矩阵,畸变系数,旋转矩阵,新的相机内参矩阵,输出映射尺寸和映射类型。其中,相机内参矩阵和畸变系数是必须的输入参数,而旋转矩阵和新的相机内参矩阵可以为空。映射类型可以选择CV_16SC2或CV_32FC1,分别表示输出映射为16位有符号整型或32位浮点型。 函数的主要实现过程是根据输入参数计算畸变矫正映射,最后将结果输出到map1和map2中。具体实现过程可参考上述代码。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值