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

运行结果

相关推荐
ZStack开发者社区26 分钟前
首批 | 云轴科技ZStack加入施耐德电气技术本地化创新生态
人工智能·科技·云计算
X Y O1 小时前
神经网络初步学习3——数据与损失
人工智能·神经网络·学习
web_Hsir1 小时前
vue3.2 前端动态分页算法
前端·算法
唯创知音1 小时前
玩具语音方案选型决策OTP vs Flash 的成本功耗与灵活性
人工智能·语音识别
Jamence1 小时前
多模态大语言模型arxiv论文略读(151)
论文阅读·人工智能·语言模型·自然语言处理·论文笔记
tongxianchao1 小时前
LaCo: Large Language Model Pruning via Layer Collapse
人工智能·语言模型·剪枝
HyperAI超神经2 小时前
OmniGen2 多模态推理×自我纠正双引擎,引领图像生成新范式;95 万分类标签!TreeOfLife-200M 解锁物种认知新维度
人工智能·数据挖掘·数据集·图像生成·医疗健康·在线教程·数学代码
网安INF2 小时前
深度学习中批标准化与神经网络调优
人工智能·深度学习·神经网络·机器学习
开开心心_Every2 小时前
便捷的电脑自动关机辅助工具
开发语言·人工智能·pdf·c#·电脑·音视频·sublime text
EnochChen_2 小时前
多实例学习简介
人工智能