OpenCV CUDA模块中用于稠密光流计算的 TV-L1(Dual TV-L1)算法类cv::cuda::OpticalFlowDual_TVL1

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

算法描述

cv::cuda::OpticalFlowDual_TVL1类是基于变分优化方法的稠密光流算法实现(Dual TV-L1 光流模型),在 GPU 上加速运行。适用于精度要求较高、但对性能要求不极端的应用场景。

所属模块和头文件

  • 模块:opencv_cudaoptflow
  • 头文件:
cpp 复制代码
 #include <opencv2/cudaoptflow.hpp>

功能概述

特性 描述
稠密光流计算 计算图像帧之间的像素级运动矢量(X 和 Y 分量)
GPU 加速 使用 CUDA 在 NVIDIA GPU 上进行加速
高精度 基于 TV-L1 变分优化模型,适用于需要高精度光流的场景
支持参数调节 支持多个超参数调整以平衡速度与质量

创建对象方法

cpp 复制代码
Ptr<cv::cuda::OpticalFlowDual_TVL1> tvl1 = 
    cv::cuda::OpticalFlowDual_TVL1::create();

你也可以使用以下函数设置默认参数:

cpp 复制代码
Ptr<cv::cuda::OpticalFlowDual_TVL1> tvl1 = 
    cv::cuda::OpticalFlowDual_TVL1::create(
        double tau = 0.25,
        double lambda = 0.15,
        double theta = 0.3,
        int nscales = 5,
        int warps = 5,
        double epsilon = 0.01,
        int iterations = 300,
        bool useInitialFlow = false
    );

主要成员函数

函数名 描述
calc(...) 计算两帧图像之间的光流
get/setTau() 获取/设置梯度下降步长 τ
get/setLambda() 获取/设置光流平滑约束系数 λ
get/setTheta() 获取/设置对偶变量更新权重 θ
get/setNumScales() 获取/设置金字塔层数
get/setWarpingsNumber() 获取/设置每层 warp 次数
get/setEpsilon() 获取/设置收敛阈值 ε
get/setIterations() 获取/设置每次 warp 的迭代次数
get/setUseInitialFlow() 是否使用初始 flow 输入(如前一帧结果)

calc() 函数原型

cpp 复制代码
void calc(
    InputArray I0,              // 第一帧图像(灰度图)
    InputArray I1,              // 第二帧图像(灰度图)
    InputOutputArray flowX,     // 输出 X 分量
    InputOutputArray flowY,     // 输出 Y 分量
    Stream& stream = Stream::Null()
);

参数说明:

参数 类型 描述
I0, I1 InputArray 输入的两帧图像(必须为 CV_8UC1 灰度图)
flowX, flowY InputOutputArray 输出的 X/Y 方向光流分量(CV_32FC1)
stream Stream& 可选 CUDA 流,默认为 Stream::Null()

示例代码

cpp 复制代码
#include <opencv2/opencv.hpp>
#include <opencv2/cudaoptflow.hpp>

using namespace cv;
using namespace cv::cuda;

// 自定义绘制函数
void drawOpticalFlow(const Mat& flow, Mat& dst, int step = 16);

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: 创建 Dual TVL1 光流对象
    Ptr<cuda::OpticalFlowDual_TVL1> tvl1 = cuda::OpticalFlowDual_TVL1::create();

    // Step 4: 设置参数(OpenCV 4.9 支持的参数)
    tvl1->setNumIterations(100);       // 总迭代次数
    tvl1->setLambda(0.15);             // 平滑项权重
    tvl1->setUseInitialFlow(false);    // 是否使用初始 flow

    // Step 5: 准备输出光流数据(注意:输出为 CV_32FC2 格式)
    GpuMat flow;  // 注意:不再是 flowX + flowY 分开

    // Step 6: 执行光流计算(注意参数顺序)
    tvl1->calc(d_frame1, d_frame2, flow, Stream::Null());

    // Step 7: 下载结果到 CPU
    Mat host_flow;
    flow.download(host_flow);

    // Step 8: 绘制光流矢量图
    Mat flowImg;
    drawOpticalFlow(host_flow, flowImg);

    imshow("frame1", frame1);
    imshow("frame2", frame2);

    imshow("CUDA Dual TV-L1 Flow", flowImg);
    waitKey(0);

    return 0;
}


// 自定义绘制函数
void drawOpticalFlow(const Mat& flow, Mat& dst, int step) {
    dst = Mat::zeros(flow.size(), CV_8UC3);

    for (int y = 0; y < flow.rows; y += step) {
        for (int x = 0; x < flow.cols; x += step) {
            Point2f f = flow.at<Point2f>(y, x);
            line(dst, Point(x, y), Point(cvRound(x + f.x * 5), cvRound(y + f.y * 5)),
                 Scalar(0, 255, 0));
            circle(dst, Point(cvRound(x + f.x * 5), cvRound(y + f.y * 5)), 1,
                   Scalar(0, 255, 0), -1);
        }
    }
}

运行结果

相关推荐
牛客企业服务38 分钟前
2025年AI面试推荐榜单,数字化招聘转型优选
人工智能·python·算法·面试·职场和发展·金融·求职招聘
视觉语言导航1 小时前
RAL-2025 | 清华大学数字孪生驱动的机器人视觉导航!VR-Robo:面向视觉机器人导航与运动的现实-模拟-现实框架
人工智能·深度学习·机器人·具身智能
糖葫芦君1 小时前
Policy Gradient【强化学习的数学原理】
算法
**梯度已爆炸**1 小时前
自然语言处理入门
人工智能·自然语言处理
ctrlworks2 小时前
楼宇自控核心功能:实时监控设备运行,快速诊断故障,赋能设备寿命延长
人工智能·ba系统厂商·楼宇自控系统厂家·ibms系统厂家·建筑管理系统厂家·能耗监测系统厂家
BFT白芙堂2 小时前
睿尔曼系列机器人——以创新驱动未来,重塑智能协作新生态(上)
人工智能·机器学习·机器人·协作机器人·复合机器人·睿尔曼机器人
aneasystone本尊2 小时前
使用 MCP 让 Claude Code 集成外部工具
人工智能
静心问道2 小时前
SEW:无监督预训练在语音识别中的性能-效率权衡
人工智能·语音识别
羊小猪~~3 小时前
【NLP入门系列五】中文文本分类案例
人工智能·深度学习·考研·机器学习·自然语言处理·分类·数据挖掘
xwz小王子3 小时前
从LLM到WM:大语言模型如何进化成具身世界模型?
人工智能·语言模型·自然语言处理