• 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

OpenCV CUDA 模块中实现的稀疏光流算法类,基于 Lucas-Kanade 方法,并支持图像金字塔结构。适用于特征点跟踪任务(如角点、FAST 特征等)。

创建对象方法

静态函数:create()

static Ptr<cv::cuda::SparsePyrLKOpticalFlow> cv::cuda::SparsePyrLKOpticalFlow::create(
    cv::Size winSize = cv::Size(21, 21),
    int maxLevel = 3,
    int iters = 30,
    bool useInitialFlow = false
);

参数说明:

参数名类型默认值描述
winSizeSizeSize(21,21)Lucas-Kanade 算法使用的窗口大小(必须为奇数)
maxLevelint3金字塔最大层级数(0 表示不使用金字塔)
itersint30每层金字塔上的最大迭代次数
useInitialFlowboolfalse是否使用初始 flow 输入

主要成员函数

深色版本

函数名返回类型描述
calc()void计算两帧图像之间的稀疏光流
getWinSize()Size获取当前窗口大小
getMaxLevel()int获取金字塔最大层级
getIterations()int获取每层迭代次数
getUseInitialFlow()bool获取是否启用初始 flow 输入
setUseInitialFlow(bool flag)void设置是否启用初始 flow 输入
getStream()Stream&获取当前使用的 CUDA 流
setStream(const Stream& stream)void设置使用的 CUDA 流
collectGarbage()void显式释放内部资源(如显存)

calc() 函数原型

void cv::cuda::SparsePyrLKOpticalFlow::calc(
    InputArray prevImg,            // 前一帧图像 (灰度图 CV_8UC1)
    InputArray nextImg,            // 当前帧图像 (灰度图 CV_8UC1)
    InputArray prevPts,            // 上一帧中要追踪的点集 (CV_32FC2)
    InputOutputArray nextPts,      // 输出:当前帧中追踪到的点集
    OutputArray status,            // 输出:每个点是否成功追踪 (uchar)
    OutputArray err = noArray(),   // 可选输出:误差值
    Stream& stream = Stream::Null()
);

参数说明:

参数名类型描述
prevImgInputArray前一帧图像(灰度图,CV_8UC1)
nextImgInputArray当前帧图像(灰度图,CV_8UC1)
prevPtsInputArray上一帧的特征点位置(CV_32FC2 格式)
nextPtsInputOutputArray输出:当前帧中对应点的位置(CV_32FC2)
statusOutputArray输出:每个点是否成功追踪(uchar,1 成功,0 失败)
errOutputArray / noArray()可选输出:误差值
streamStream&可选 CUDA 流,默认为 Stream::Null()

注意事项与要求

条件要求
输入图像格式必须为灰度图(CV_8UC1)
关键点格式必须为 CV_32FC2 格式,且是单行矩阵(rows == 1
图像尺寸prevImgnextImg 的尺寸必须相同
实时性支持支持实时处理,适合小数量关键点
替代方案对于稠密光流,请使用 DenseOpticalFlowNvidiaOpticalFlow 系列接口

示例代码

#include <opencv2/cudaimgproc.hpp>
#include <opencv2/cudaoptflow.hpp>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace cv::cuda;

int main()
{
    // Step 1: 读取两帧图像(灰度图)
    Mat frame1 = imread( "/media/dingxin/data/study/OpenCV/sources/images/frame1.png", IMREAD_GRAYSCALE );
    Mat frame2 = imread( "/media/dingxin/data/study/OpenCV/sources/images/frame2.png", IMREAD_GRAYSCALE );

    if ( frame1.empty() || frame2.empty() )
    {
        std::cerr << "无法加载图像" << std::endl;
        return -1;
    }

    // Step 2: 上传到 GPU
    GpuMat d_frame1, d_frame2;
    d_frame1.upload( frame1 );
    d_frame2.upload( frame2 );

    // Step 3: 检测角点作为追踪起点
    std::vector< Point2f > corners;
    goodFeaturesToTrack( frame1, corners, 500, 0.01, 10 );  // 最多检测500个角点

    // Step 4: 转换为 GPU 可用数组
    GpuMat d_prevPts;

    // 构造一行多列的 CV_32FC2 格式 Mat
    Mat m_prevPts( 1, corners.size(), CV_32FC2 );
    for ( size_t i = 0; i < corners.size(); ++i )
    {
        m_prevPts.at< cv::Vec2f >( 0, i ) = cv::Vec2f( corners[ i ].x, corners[ i ].y );
    }

    d_prevPts.upload( m_prevPts );

    // Step 5: 创建稀疏光流对象
    Ptr< cuda::SparsePyrLKOpticalFlow > lk = cuda::SparsePyrLKOpticalFlow::create();

    // Step 6: 准备输出变量
    GpuMat d_nextPts;
    GpuMat d_status;
    GpuMat d_err;

    // Step 7: 计算稀疏光流
    lk->calc( d_frame1, d_frame2, d_prevPts, d_nextPts, d_status, d_err );

    // Step 8: 下载结果
    Mat nextPts, status;
    d_nextPts.download( nextPts );
    d_status.download( status );

    // Step 9: 绘制跟踪结果
    Mat output;
    cv::cvtColor( frame1, output, COLOR_GRAY2BGR );

    // 注意:status 和 nextPts 都是单行矩阵,所以使用 (0, i)
    for ( int i = 0; i < status.cols; ++i )
    {
        if ( ( int )status.at< uchar >( 0, i ) == 1 )
        {
            Point2f pt1 = corners[ i ];
            Point2f pt2 = nextPts.at< Point2f >( 0, i );

            // 确保点在图像范围内
            if ( pt2.x >= 0 && pt2.y >= 0 && pt2.x < frame1.cols && pt2.y < frame1.rows )
            {
                line( output, pt1, pt2, Scalar( 0, 255, 0 ), 1 );
                circle( output, pt2, 2, Scalar( 0, 0, 255 ), -1 );
            }
        }
    }

    imshow( "Sparse PyrLK Optical Flow", output );
    waitKey( 0 );

    return 0;
}

运行结果

在这里插入图片描述

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐