LK光流跟踪

一、什么是光流?

在前几篇文章中,我们介绍了2D-2D、3D-2D、3D-3D等相机位姿估计方法,它们都是在特征点匹配的基础上进行的。当我们回过头再重新考虑特征点匹配方法时,可能会注意到一个问题,即使是最快的ORB特征,每帧图片的计算也需要近20ms,对于30ms/帧运行的SLAM系统来说,一大半时间都花在了计算特征点上。

因此,我们也许会考虑能否避免特征点提取操作?

光流法(Optical Flow)就是一种避免频繁计算特征点的方法。另外还有“直接法(Direct Method),将在后续文章中介绍。

所谓“光流”,从字面上理解就是光的流动。其实在日常生活中,人眼观察到的物体的运动就是光流。因为物体反射光进入人的眼睛,当物体移动后,相应的反射光也会移动,从而使人意识到物体在运动。在计算机中,我们就可以利用像素亮度的变化追踪光线移动的方向,从而确定物体运动方向,进而得到相机运动方向。

LK光流是光流法的一种,它对观测量做了“灰度不变”假设和“某个窗口内的像素具有相同的运动”假设。因而能够从前后两幅图片中追踪到同一个点的位置移动。

二、使用OpenCV中的LK光流

在实际应用中,LK光流的作用就是跟踪特征点。与对每一帧提取特征点相比,使用LK光流只需要提取一次特征点,后续视频帧只需要跟踪就可以了,节约了许多特征提取时间。

int main( int argc, char** argv )
{
    if ( argc != 2 )
    {
        cout<<"usage: useLK path_to_dataset"< keypoints;      // 因为要删除跟踪失败的点,使用list
    cv::Mat color, depth, last_color;
    
    for ( int index=0; index<100; index++ )
    {
        fin>>time_rgb>>rgb_file>>time_depth>>depth_file;
        color = cv::imread( path_to_dataset+"/"+rgb_file );
        depth = cv::imread( path_to_dataset+"/"+depth_file, -1 );
        if (index == 0 )
        {
            // 对第一帧提取FAST特征点
            vector kps;
            cv::Ptr detector = cv::FastFeatureDetector::create();
            detector->detect( color, kps );
            for ( auto kp:kps )
                keypoints.push_back( kp.pt );
            last_color = color;
            continue;
        }
        if ( color.data==nullptr || depth.data==nullptr )
            continue;
        // 对其他帧用LK跟踪特征点
        vector next_keypoints; 
        vector prev_keypoints;
        for ( auto kp:keypoints )
            prev_keypoints.push_back(kp);
        vector status;
        vector error; 
        chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
        cv::calcOpticalFlowPyrLK( last_color, color, prev_keypoints, next_keypoints, status, error );
        chrono::steady_clock::time_point t2 = chrono::steady_clock::now();
        chrono::duration time_used = chrono::duration_cast>( t2-t1 );
        cout<<"LK Flow use time:"<

代码中,先对第一帧图像提取FAST特征点,后续帧使用LK跟踪这些特征点。调用cv::calcOpticalFlowPyrLK即可得到新一帧中更新后的特征点位置。效果如下图所示。

LK光流跟踪_第1张图片
Paste_Image.png

每两张图片间相差10帧。由于相机的移动,越来越多的特征点移动到了视野外,因此能够跟踪到的特征点越来越少。另外,我们也发现误跟踪到了一些不该出现特征点的位置,这说明LK光流法的准确度并不高,特别是特征不明显的点,由于各个方向的亮度变化都很相似,容易导致跟踪错误。

LK光流法的结果可以用于相机位姿估计,它与直接对特征点做匹配的效果是一致的。

测试程序的完整代码地址:https://github.com/jingedawang/LKFlow

三、参考资料

《视觉SLAM十四讲》第8讲 视觉里程计2 高翔
光流Optical Flow介绍与OpenCV实现 zouxy09

你可能感兴趣的:(LK光流跟踪)