OpenCV稠密光流估计的一个类cv::optflow::DenseRLOFOpticalFlow

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

算法描述

cv::optflow::DenseRLOFOpticalFlow 是OpenCV 中用于稠密光流估计的一个类,属于optflow模块。它是RLOF(Regularized Location-Only Flow)算法的一种实现,用于计算视频帧之间的像素级运动矢量。

DenseRLOFOpticalFlow 是一种基于稀疏特征匹配 + 插值的稠密光流算法,其主要特点包括:

  • 基于稀疏特征点(如 FAST、ORB)进行初始匹配;
  • 使用正则化插值方法将稀疏匹配扩展为全图像素级别的光流场(稠密光流);
  • 可以处理大位移运动(相比传统 LK 光流更鲁棒);
  • 支持自定义特征检测器和描述子;
  • 适用于视频稳定、动作分析、视频插值等任务。

常用静态方法

1.创建函数

cpp 复制代码
static Ptr<DenseRLOFOpticalFlow> cv::optflow::DenseRLOFOpticalFlow::create
( 	
    Ptr< RLOFOpticalFlowParameter >  	rlofParam = Ptr< RLOFOpticalFlowParameter >(),
		float  	forwardBackwardThreshold = 1.f,
		Size  	gridStep = Size(6, 6),
		InterpolationType  	interp_type = InterpolationType::INTERP_EPIC,
		int  	epicK = 128,
		float  	epicSigma = 0.05f,
		float  	epicLambda = 999.0f,
		int  	ricSPSize = 15,
		int  	ricSLICType = 100,
		bool  	use_post_proc = true,
		float  	fgsLambda = 500.0f,
		float  	fgsSigma = 1.5f,
		bool  	use_variational_refinement = false 
	) 		

参数:

参数名 类型 默认值 说明
rlofParam Ptr nullptr 可选:自定义参数对象。如果传入,则其他参数将被忽略。
forwardBackwardThreshold float 1.0f 正向/反向一致性检查的阈值。用于剔除不一致的匹配点。值越大越宽松。
gridStep Size (6, 6) 稠密插值时使用的网格步长。值越小,插值越密集,计算量越大。
interp_type InterpolationType InterpolationType::INTERP_EPIC 插值类型,可选:INTERP_LINEAR, INTERP_EPIC, INTERP_RIC
epicK int 128 EPIC 插值中使用的邻域大小。控制局部特征的范围。
epicSigma float 0.05f EPIC 中高斯核的标准差,影响平滑程度。
epicLambda float 999.0f EPIC 中正则化系数,防止过拟合。值越大越平滑。
ricSPSize int 15 RIC 插值中的超像素大小。仅在使用 INTERP_RIC 时有效。
ricSLICType int 100 SLIC 超像素分割类型。仅在使用 INTERP_RIC 时有效。
use_post_proc bool true 是否启用后处理步骤(如去噪、平滑)。
fgsLambda float 500.0f FGS 后处理中的正则化系数。控制平滑强度。
fgsSigma float 1.5f FGS 后处理中的高斯核标准差。
use_variational_refinement bool false 是否使用变分优化进一步提升精度(会显著增加计算时间)。
  1. calc(InputArray I0, InputArray I1, OutputArray flow) 计算从 I0 到 I1 的光流
  2. setFeatureDetector(Ptr detector) 设置自定义特征检测器
  3. setFeaturesToTrack(int numFeatures) 设置每帧中最多使用的特征点数

代码示例

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


using namespace cv;
using namespace std;
// 将光流向量转换为 HSV 图像以便可视化
Mat visualizeFlow( const Mat& flow )
{
    vector< Mat > planes;   // ✅ 正确声明 planes 为 vector<Mat>
    split( flow, planes );  // 自动拆分为两个通道:x-flow 和 y-flow

    Mat mag, angle;
    cartToPolar( planes[ 0 ], planes[ 1 ], mag, angle, true );  // 计算幅度和角度

    normalize( mag, mag, 0, 1, NORM_MINMAX );  // 归一化到 [0, 1]

    // HSV 颜色空间可视化
    Mat hsv[ 3 ];
    hsv[ 0 ] = angle;                              // Hue = 方向
    hsv[ 1 ] = Mat::ones( angle.size(), CV_32F );  // Saturation = 1
    hsv[ 2 ] = mag;                                // Value = 幅度

    Mat hsvFull;
    merge( hsv, 3, hsvFull );                    // 合并三个通道
    hsvFull.convertTo( hsvFull, CV_8U, 255.0 );  // 转换为 8U 类型用于显示
    Mat rgbOut;
    cvtColor( hsvFull, rgbOut, COLOR_HSV2BGR );  // 转换为 BGR 显示图像

    return rgbOut;
}
int main()
{
    // 读取两帧图像(灰度图)
    Mat frame1 = imread( "/media/dingxin/data/study/OpenCV/sources/images/left01.jpg", IMREAD_COLOR );
    Mat frame2 = imread( "/media/dingxin/data/study/OpenCV/sources/images/right01.jpg", IMREAD_COLOR );

    if ( frame1.empty() || frame2.empty() )
    {
        cerr << "无法加载图像!" << endl;
        return -1;
    }

    // 创建 DenseRLOF 实例并设置高级参数
    Ptr< optflow::DenseRLOFOpticalFlow > rlof = optflow::DenseRLOFOpticalFlow::create( nullptr,               // 使用默认参数对象
                                                                                       1.0f,                  // forwardBackwardThreshold
                                                                                       Size( 8, 8 ),          // gridStep
                                                                                       optflow::INTERP_EPIC,  // interp_type
                                                                                       128,                   // epicK
                                                                                       0.05f,                 // epicSigma
                                                                                       1000.0f,               // epicLambda
                                                                                       15,                    // ricSPSize
                                                                                       100,                   // ricSLICType
                                                                                       true,                  // use_post_proc
                                                                                       500.0f,                // fgsLambda
                                                                                       1.5f,                  // fgsSigma
                                                                                       false                  // use_variational_refinement
    );

    // 计算稠密光流
    Mat flow;
    rlof->calc( frame1, frame2, flow );

    // 可视化结果
    Mat flowImage = visualizeFlow( flow );
    imshow( "Frame 1", frame1 );
    imshow( "Frame 2", frame2 );
    imshow( "Dense RLOF Optical Flow", flowImage );
    waitKey( 0 );

    return 0;
}

运行结果