OpenCV CUDA 模块光流处理------实现 Lucas-Kanade 稀疏光流(Sparse Optical Flow)的类DensePyrLKOpticalFlow

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

算法描述

cv::cuda::DensePyrLKOpticalFlow是OpenCV CUDA模块中实现Lucas-Kanade稀疏光流(Sparse Optical Flow)的类,但它也可以通过参数配置来计算稠密光流(Dense Optical Flow)。

这个类是 cv::cuda::DenseOpticalFlow 的子类,因此它遵循统一的接口,并支持在 GPU 上高效运行 Lucas-Kanade 类型的光流算法。

类定义概览

属性说明
头文件<opencv2/cudaoptflow.hpp>
命名空间cv::cuda
继承自cv::cuda::DenseOpticalFlow
用途在 GPU上实现基于金字塔的Lucas-Kanade光流算法(稀疏或稠密)
加速方式利用CUDA进行GPU加速

算法背景:Lucas-Kanade 光流

Lucas-Kanade (LK) 是一种经典的稀疏光流算法,用于追踪图像中的关键点运动。标准LK只适用于小位移,但通过构建图像金字塔(PyrLK),可以处理更大范围的运动。

虽然LK本质上是“稀疏”的,但DensePyrLKOpticalFlow支持在整幅图像上进行稠密估计(即每个像素都计算一个运动向量)。

创建对象与常用函数

创建实例:
cv::Ptr<cv::cuda::DensePyrLKOpticalFlow> optflow = cv::cuda::DensePyrLKOpticalFlow::create
(
    cv::Size winSize,       // 窗口大小,如 cv::Size(21, 21)
    int numLevels,          // 图像金字塔层数
    int itersPerLevel,      // 每层迭代次数
    bool useInitialFlow     // 是否使用初始光流估计
);

示例:

cv::Ptr<cv::cuda::DensePyrLKOpticalFlow> optflow = cv::cuda::DensePyrLKOpticalFlow::create
(
    cv::Size(21, 21),   // 窗口大小
    5,                  // 金字塔层数
    30,                 // 每层迭代次数
    false               // 不使用初始 flow
);

常用成员函数

函数名描述
calc(InputArray I0, InputArray I1, InputOutputArray flow, Stream& stream = Stream::Null())计算光流(必须为灰度图 CV_8UC1 或 CV_32FC1)
getWinSize() / setWinSize(cv::Size)获取/设置窗口大小
getNumLevels() / setNumLevels(int)获取/设置金字塔层数
getIterations() / setIterations(int)获取/设置每层迭代次数
collectGarbage()手动释放内部缓存资源

代码示例


#include <opencv2/cudaoptflow.hpp>
#include <opencv2/cudaimgproc.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: 创建 DensePyrLKOpticalFlow 对象
    Ptr<DensePyrLKOpticalFlow> optflow = DensePyrLKOpticalFlow::create(
        Size(21, 21),   // 窗口大小
        5,              // 金字塔层数
        30,             // 每层迭代次数
        false           // 不使用初始 flow
    );

    // Step 4: 准备输出矩阵(CV_32FC2 格式)
    GpuMat d_flow;

    // Step 5: 执行光流计算
    optflow->calc(d_frame1, d_frame2, d_flow);

    // Step 6: 下载结果到 CPU
    Mat host_flow;
    d_flow.download(host_flow);  // host_flow 类型为 CV_32FC2

    // Step 7: 分离 flow_x 和 flow_y
    std::vector<Mat> flow_parts(2);
    split(host_flow, flow_parts);  // flow_parts[0] = dx, flow_parts[1] = dy

    // Step 8: 显示 flow_x 和 flow_y
    normalize(flow_parts[0], flow_parts[0], 0, 1, NORM_MINMAX);
    normalize(flow_parts[1], flow_parts[1], 0, 1, NORM_MINMAX);

    imshow("Flow X", flow_parts[0]);
    imshow("Flow Y", flow_parts[1]);

    // Step 9: 合成彩色光流图(HSV 表示方向和强度)
    Mat mag, ang;
    cartToPolar(flow_parts[0], flow_parts[1], mag, ang, true);

    Mat hsv_channels[] = {
        ang,
        Mat::ones(ang.size(), CV_32F),
        mag
    };

    Mat hsv_merged;
    merge(hsv_channels, 3, hsv_merged);
    hsv_merged.convertTo(hsv_merged, CV_8U, 255);

    Mat bgr_out;
    cv::cvtColor(hsv_merged, bgr_out, cv::COLOR_HSV2BGR);

    imshow("Optical Flow HSV", bgr_out);

    waitKey(0);
    return 0;
}

运行结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

村北头的码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值