OpenCV中CalcOpticalFlowFarneback()函数分析

来源:互联网 发布:sqlserver打开数据库 编辑:程序博客网 时间:2024/05/21 17:12

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

0 0
原创粉丝点击