OpenCV中CalcOpticalFlowFarneback()函数分析

OpenCV中CalcOpticalFlowFarneback函数

  • 函数简介

    CalcOpticalFlowFarneback()函数是利用用Gunnar Farneback的算法计算全局性的稠密光流算法(即图像上所有像素点的光流都计算出来),由于要计算图像上所有点的光流,故计算耗时,速度慢。它的核心思想主要源于”Two-Frame Motion Estimation Based on PolynomialExpansion”论文。下面是是对此函数的详细介绍。

  • 函数分析

    void cv::calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0,
                                   OutputArray _flow0, double pyr_scale, int levels, int winsize,
                                   int iterations, int poly_n, double poly_sigma, int flags )
    // 参数说明如下:
    // _prev0:输入前一帧图像
    // _next0:输入后一帧图像
    // _flow0:输出的光流
    // pyr_scale:金字塔上下两层之间的尺度关系
    // levels:金字塔层数
    // winsize:均值窗口大小,越大越能denoise并且能够检测快速移动目标,但会引起模糊运动区域
    // iterations:迭代次数
    // poly_n:像素领域大小,一般为5,7等
    // poly_sigma:高斯标注差,一般为1-1.5
    // flags:计算方法。主要包括OPTFLOW_USE_INITIAL_FLOW和OPTFLOW_FARNEBACK_GAUSSIAN
    
    // OpenCV中此函数源码
    void cv::calcOpticalFlowFarneback( InputArray _prev0, InputArray _next0,
                                   InputOutputArray _flow0, double pyr_scale, int levels, int winsize,
                                   int iterations, int poly_n, double poly_sigma, int flags )
    {
    #ifdef HAVE_OPENCL
        bool use_opencl = ocl::useOpenCL() && _flow0.isUMat();
        if( use_opencl && ocl_calcOpticalFlowFarneback(_prev0, _next0, _flow0, pyr_scale, levels, winsize, iterations, poly_n, poly_sigma, flags))
        {
            CV_IMPL_ADD(CV_IMPL_OCL);
            return;
        }
    #endif
        // 将_prev0和_next0转换为Mat类型
        Mat prev0 = _prev0.getMat(), next0 = _next0.getMat();
        const int min_size = 32;
        // 创建img指针数组,img[0]指向prev0,img[1]指向next0
        const Mat* img[2] = { &prev0, &next0 };
    
        int i, k;
        double scale;
        Mat prevFlow, flow, fimg;
        // 检查prev0和next0是否大小相同、单通道图像,金字塔尺度关系pyr_scale小于1
        CV_Assert( prev0.size() == next0.size() && prev0.channels() == next0.channels() &&
            prev0.channels() == 1 && pyr_scale < 1 );
        // 创建和prev0大小相同,32位浮点双通道图像
        _flow0.create( prev0.size(), CV_32FC2 );
        // 将_flow0转换成Mat类型
        Mat flow0 = _flow0.getMat();
        // 循环确定金字塔层数
        for( k = 0, scale = 1; k < levels; k++ )
        {
            // scale用于存放第k层图像与原图的尺寸广西
            scale *= pyr_scale;
            // 判断第k层图像行数与min_size关系,确定金字塔层数结束
            if( prev0.cols*scale < min_size || prev0.rows*scale < min_size )
                break;
        }
        // 将计算出的金字塔层数k赋给levels
        levels = k;
        // 遍历金字塔层数
        for( k = levels; k >= 0; k-- )
        {
            // 计算原图与k-1层图像的尺寸关系
            for( i = 0, scale = 1; i < k; i++ )
                scale *= pyr_scale;
            // 定义高斯滤波系数
            double sigma = (1./scale-1)*0.5;
            int smooth_sz = cvRound(sigma*5)|1;
            // 得到高斯滤波器模板大小
            smooth_sz = std::max(smooth_sz, 3);
            // 计算第k层图像矩阵的列数
            int width = cvRound(prev0.cols*scale);
            // 计算第k层图像矩阵的行数
            int height = cvRound(prev0.rows*scale);
    
            if( k > 0 )
                // 创建第k层图像尺寸大小的32位双通道图像,用于存储第k层图像光流flow
                flow.create( height, width, CV_32FC2 );
            else
                // 否则为原图像
                flow = flow0;
            // 如果preFlow未指向任何矩阵数据
            if( prevFlow.empty() )
            {
                // 如果flags为OPTFLOW_USE_INITIAL_FLOW
                if( flags & OPTFLOW_USE_INITIAL_FLOW )
                {
                    // 改变flow0图像大小为flow,用像素关系重采样插值
                    // 插值使用錓NTER_AREA,主要是为了避免波纹出现
                    resize( flow0, flow, Size(width, height), 0, 0, INTER_AREA );
                    // 将flow缩小scale
                    flow *= scale;
                }
                // flags为OPTFLOW_FARNEBACK_GAUSSIAN
                else
                    // 创建一个Mat给flow
                    flow = Mat::zeros( height, width, CV_32FC2 ); 
            }
            else
            {
                // 改变prevFlow图像大小为flow,利用INTER_LINEAR方式进行双线性插值
                resize( prevFlow, flow, Size(width, height), 0, 0, INTER_LINEAR );
                // 将flow增加(1./pyr_sacle)倍
                flow *= 1./pyr_scale;
            }
    
            Mat R[2], I, M;
            for( i = 0; i < 2; i++ )
            {
                // 将img[i]转换为CV_32F格式
                img[i]->convertTo(fimg, CV_32F);
                // 对输出图像fimg进行高斯滤波后用fimg输出
                GaussianBlur(fimg, fimg, Size(smooth_sz, smooth_sz), sigma, sigma);
                // 改变fimg图像大小I,使用双线性插值INTER_LINEAR
                resize( fimg, I, Size(width, height), INTER_LINEAR );
                // 计算邻域图像R[i]
                FarnebackPolyExp( I, R[i], poly_n, poly_sigma );
            }
            // 依据R[0]、R[1]、flow等信息更新矩阵M
            FarnebackUpdateMatrices( R[0], R[1], flow, M, 0, flow.rows );
    
            for( i = 0; i < iterations; i++ )
            {
                // flags为OPTFLOW_FARNEBACK_GAUSSIAN
                if( flags & OPTFLOW_FARNEBACK_GAUSSIAN )
                    // 利用R[0]、R[1]、M等,利用高斯平滑原理,更新光流flow
                    FarnebackUpdateFlow_GaussianBlur( R[0], R[1], flow, M, winsize, i < iterations - 1 );
                // flags为OPTFLOW_USE_INITIAL_FLOW
                else
                    // 利用R[0]、R[1]、M等初始化光流flow
                    FarnebackUpdateFlow_Blur( R[0], R[1], flow, M, winsize, i < iterations - 1 );
            }
            // 将flow赋给prevFlow
            prevFlow = flow;
        }
    }
    
  • 参考文献:

    http://www.chinadmd.com/file/poeootxpoprwtxpcwzw6awiu_1.html

    http://www.aichengxu.com/view/2450131

    http://blog.csdn.net/zouxy09/article/details/8683859

  • 6
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
OpenCV光流算法源码calcopticalflowfarneback实现了Farneback稠密光流算法。这个算法用于计算连续帧之间的运动向量,并且可以应用于目标跟踪、姿态估计等计算机视觉任务。 calcopticalflowfarneback函数的输入参数包括两幅输入图像、金字塔层数、块尺寸、参数k、快速金字塔标识符和光流估计方法标识符。其,金字塔层数表示图像金字塔的层数,用于处理图像的尺度变化;块尺寸表示图像计算光流的像素块的大小;参数k为计算光流所需的参数,代表Gaussian滤波核的标准差;快速金字塔标识符选择是否使用快速金字塔参数估计;光流估计方法标识符选择使用Farneback光流估计的具体方法。 calcopticalflowfarneback函数的输出为每个像素点在x和y方向上的光流向量。这些光流向量可用于表示图像每个像素的运动情况,通过计算当前像素与下一帧图像对应位置的像素之间的运动差异,从而获取图像目标的运动信息。 通过调用calcopticalflowfarneback函数,可以对输入的连续帧序列进行光流计算,并获取到每个像素的运动向量。这些运动向量可以用于后续的目标跟踪、姿态估计等计算机视觉任务,帮助我们更好地理解图像的运动变化和目标的位置信息。 总之,calcopticalflowfarneback函数OpenCV实现Farneback稠密光流算法的源码,通过调用该函数可以计算连续帧之间的光流向量,从而实现图像的运动分析和相关任务的处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值