这是一个简单的两两帧视觉里程计,两帧图像之间R,t的估计只使用了对极几何,尺度因子由数据集的真实轨迹获得,本项目的实现基于Opencv.
问题描述:
输入:
使用相机采集的图片序列;相机的内参(即焦距$f_x$,$fy$,相机光心$c_x$,$c_y$,畸变参数$k_1$,$k_2$,$k_3$,$p_1$,$p_2$),相机内参可通过Opencv、matlab、kalibr等工具进行标定。
输出:
以第一帧图片为参考系,输出每帧图片的坐标。
算法步骤:
- 读入相机参数
- 获取两帧连续图像$I^t$,$I^{t+1}$
- 对获取的图像进行去畸变处理
- 对$I^t$提取FAST特征点,使用LK金字塔光流法在$I^{t+1}$中跟踪这些特征点,若跟踪的特征点数量小于预设的阈值,则在$I^{t+1}$中重新提取FAST特征点
- 使用五点法及RANSAC计算本质矩阵$E$
- 通过本质矩阵$E$估计两帧之间的$R,t$
- 使用数据集中的真实轨迹获取两帧之间的尺度因子,计算出$I^{t+1}$在参考系中的$R,t$并输出显示
核心算法代码:
- 从第二帧开始,通过真实轨迹坐标计算并保存每帧的尺度到vector中
1 | void getAbusoluteScale(vector<double> scale,string ground_truth){ |
- 转灰度图、去畸变
1 | cvtColor(ref,ref,CV_BGR2GRAY); |
- 获取FAST特征点,并将其存于类型为vector
的kp中,便于后续LK跟踪、本质矩阵计算
1 | void featureDetection(Mat& frame,vector<Point2f>& kp){ |
- 使用opencv的函数进行光流跟踪,返回两幅图像的匹配点,并将跟踪失败的点去掉
1 | void LKFeatureTracking(Mat& ref,Mat& curr,vector<Point2f>& ref_kp,vector<Point2f>& cur_kp){ |
- 计算本质矩阵,并从本质矩阵中估计R,t
1 | E=findEssentialMat(cur_kp,ref_kp,K,RANSAC); |
设有三帧图像,索引分别为1,2,3,其中,
所以第三帧到第一帧的变换矩阵为:
所以,获取各帧图像的pose代码如下:
1
2t_f=R_f*(scale[frame_id]*t)+t_f;
R_f=R_f*R;如果需要跟踪的特征点少于阈值,则重新提取特征点
1
2
3if(cur_kp.size()<MIN_NUM){
featureDetection(curr,cur_kp);
}