OpenCV CUDA 模块光流计算------稀疏光流算法类SparsePyrLKOpticalFlow

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

算法描述

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

创建对象方法

静态函数:create()

cpp 复制代码
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
);

参数说明:

参数名 类型 默认值 描述
winSize Size Size(21,21) Lucas-Kanade 算法使用的窗口大小(必须为奇数)
maxLevel int 3 金字塔最大层级数(0 表示不使用金字塔)
iters int 30 每层金字塔上的最大迭代次数
useInitialFlow bool false 是否使用初始 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() 函数原型

cpp 复制代码
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()
);

参数说明:

参数名 类型 描述
prevImg InputArray 前一帧图像(灰度图,CV_8UC1)
nextImg InputArray 当前帧图像(灰度图,CV_8UC1)
prevPts InputArray 上一帧的特征点位置(CV_32FC2 格式)
nextPts InputOutputArray 输出:当前帧中对应点的位置(CV_32FC2)
status OutputArray 输出:每个点是否成功追踪(uchar,1 成功,0 失败)
err OutputArray / noArray() 可选输出:误差值
stream Stream& 可选 CUDA 流,默认为 Stream::Null()

注意事项与要求

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

示例代码

cpp 复制代码
#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;
}

运行结果

相关推荐
知舟不叙19 分钟前
基于OpenCV实现实时颜色检测
人工智能·opencv·计算机视觉·颜色检测
UP_Continue21 分钟前
排序--计数排序
数据结构·算法
蓑雨春归1 小时前
探索Agent的发展潜力:大模型与具身智能的融合
人工智能
每日新鲜事2 小时前
Lavazza拉瓦萨再度牵手兰博基尼汽车 百年咖啡注入超跑速度
人工智能
说私域2 小时前
传统企业数字化转型:以定制开发开源 AI 智能名片 S2B2C 商城小程序源码为核心的销售环节突破
大数据·人工智能·开源
牵手夏日3 小时前
题目类型——左右逢源
算法
geneculture3 小时前
社会应用融智学的人力资源模式:潜能开发评估;认知基建资产
人工智能·课程设计·融智学的重要应用·三级潜能开发系统·人力资源升维·认知基建·认知银行
愚润求学4 小时前
【递归、搜索与回溯】FloodFill算法(一)
c++·算法·leetcode
仙人掌_lz5 小时前
Qwen-3 微调实战:用 Python 和 Unsloth 打造专属 AI 模型
人工智能·python·ai·lora·llm·微调·qwen3
sunny-ll5 小时前
【C++】详解vector二维数组的全部操作(超细图例解析!!!)
c语言·开发语言·c++·算法·面试