opencv去畸变函数:undistortPoints()使用

(一)函数原型

void undistortPoints(InputArray src, OutputArray dst,
                     InputArray cameraMatrix, InputArray distCoeffs,
                     InputArray R = noArray(), InputArray P = noArray());

1.1函数解释:

这个函数的作用是根据观测到的点计算理想点的坐标。类似于undistort#initUndistortRectifyMap,不同的是undistortPoints操作的是稀疏点(对点去畸变)而不是整张图像。此外该函数还执行了一个反向变换来进行投影,对于三维物体并不会重建其三维坐标,对于平面物体,如果提供合适的R,t,可以在一定程度上恢复三维坐标。

1.2原理

对于每一个观察到的像素坐标点 ( u , v ) , (u,v), (u,v),
首先得到归一化坐标:
x " ← u − c x f x , y " ← v − c y f y x^{"} \leftarrow \frac{u - c_x}{f_x} ,y^{"} \leftarrow \frac{v - c_y}{f_y} x"fxucx,y"fyvcy
对归一化坐标调用undistort进行去畸变:
( x ′ , y ′ ) = undistort ( x " , y " , distCoeffs ) (x', y') = \text{undistort}(x^{"}, y^{"}, \texttt{distCoeffs}) (x,y)=undistort(x",y",distCoeffs)
如果定义了旋转矩阵:
[ X   Y   W ] T ← R ⋅ [ x ′   y ′   1 ] T [X \, Y \, W]^T \leftarrow R \cdot [x' \, y' \, 1]^T [XYW]TR[xy1]T
旋转之后的归一化坐标:
x ← X W , y ← Y W x \leftarrow \frac{X}{W},y \leftarrow \frac{Y}{W} xWXyWY
如果指定了P则将归一化平面的点转到新的像素平面:
u ′ ← x ⋅ f x ′ + c x ′ , v ′ ← y ⋅ f y ′ + c y ′ u' \leftarrow x \cdot f'_x + c'_x,v' \leftarrow y \cdot f'_y + c'_y uxfx+cxvyfy+cy

1.3参数

src:观测点坐标,格式为 2xN / Nx2 的单通道或 1xN / Nx1 的双通道(CV_32FC2 或 CV_64FC2),也可以是 vector 类型。
dst :输出的理想点坐标,1xN / Nx1 的双通道或者vector类型,经过去畸变和反向透视变换后的结果。如果P为单位矩阵或未指定,dst 将包含归一化后的点坐标。
cameraMatrix: 相机的内参矩阵。
distCoeffs: 相机畸变系数。
R:矫正变换矩阵,如果不为空则会对归一化平面的点进行变换。
P:新的内参矩阵,如果不为空则会按照新的内参矩阵将归一化平面上的点投影到相机平面。

(二)使用示例

以ORB-SLAM中去畸变函数为例:


void Frame::UndistortKeyPoints()
{
    // 判断畸变系数(如果是从配置文件中读取)
    if(mDistCoef.at<float>(0)==0.0)
    {
        // 如果畸变系数第一个为0,通常全为0,不需要去畸变
        mvKeysUn=mvKeys;
        return;
    }

    // 定义N*2单通道,类型为32F
    cv::Mat mat(N,2,CV_32F);
    for(int i=0; i<N; i++)
    {
        mat.at<float>(i,0)=mvKeys[i].pt.x;
        mat.at<float>(i,1)=mvKeys[i].pt.y;
    }

    // reshape不会改变数据的内容,只会改变维度和通道等
    mat=mat.reshape(2);
    // P矩阵给的是原来的相机内参,因此结果是像素坐标
    cv::undistortPoints(mat,mat,mK,mDistCoef,cv::Mat(),mK);
    mat=mat.reshape(1);

    // 得到去畸变之后的结果
    mvKeysUn.resize(N);
    for(int i=0; i<N; i++)
    {
        cv::KeyPoint kp = mvKeys[i];
        kp.pt.x=mat.at<float>(i,0);
        kp.pt.y=mat.at<float>(i,1);
        mvKeysUn[i]=kp;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值