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;
}

运行结果

相关推荐
不会就选b1 分钟前
算法日常・每日刷题--<队列,宽搜>4
算法
2401_865261631 分钟前
亦唐科技(YIKTANG):创新引领国产贴片机发展,稳居行业领军地位
大数据·人工智能·物联网
阿部多瑞 ABU2 分钟前
私域道德的“立法”与公共秩序的失序——法律-道德异化悖论研究
大数据·人工智能
研华科技Advantech4 分钟前
【案例分享】从单点突破到全场景复制:研华赋能药机装备迈向高效合规新范式
大数据·人工智能·边缘计算·工业设备升级
土星云SaturnCloud6 分钟前
大坝结构安全智能诊断:土星云边缘计算全周期管控实践
服务器·人工智能·安全·ai·边缘计算
众人皆醒我独醉6 分钟前
Embedding:把词变成向量——AI 理解语义的唯一方式
人工智能·面试·llm
王六米。11 分钟前
武汉自动意志科技有限公司:人工智能应用软件开发:需求总在变化,企业交付方案应该如何取舍
大数据·人工智能·科技·视频矩阵获客·企业ai应用·ai内容自动化·武汉自动意志科技
beiju12 分钟前
从模型到可执行 Agent:MCP、Skills 与 Computer Use 架构拆解
人工智能
码字的特恩14 分钟前
微软确认暂不为 Windows 11 加入透明效果自定义功能,建议用户使用第三方工具
人工智能·windows·算法·microsoft·计算机·大模型·编程
qingyunliushuiyu19 分钟前
制造行业智能问数工具怎么选?2026年选型核心要点梳理
大数据·人工智能·经验分享·制造