OpenCV之稠密光流

20 篇文章 0 订阅

介绍

参考链接

在OpenCV中,光流分为稀疏光流和稠密光流,关于稀疏光流可以参考之前的文章
OpenCV之光流

稠密光流的解释,可以参考OpenCV官方文档

OpenCV提供了另一种算法来寻找密集的光流。它计算帧中所有点的光流。它基于Gunner Farneback的算法,该算法在Gunner法尔内巴克2003年的“基于多项式展开的双帧运动估计”中进行了解释。

其实稀疏光流和稠密光流的区别,见名知义,稀疏光流是跟踪部分点,而稠密光流跟踪的是全部的点。

实现

OpenCV中的API如下:

void cv::calcOpticalFlowFarneback(
	InputArray 	prev,
	InputArray 	next,
	InputOutputArray 	flow,
	double 	pyr_scale,
	int 	levels,
	int 	winsize,
	int 	iterations,
	int 	poly_n,
	double 	poly_sigma,
	int 	flags 
)	

参数解释

  • prev,前一帧8位单通道输入图像
  • next,当前帧图像,大小和类型与prev相同
  • flow,输出流图像,其大prev相同,类型为CV_32FC2
  • pyr_scale,指定为每个图像构建金字塔的图像比例(</1),pyr_scale=0.5表示经典金字塔,其中每一个下一层都比上一层小两倍
  • levels,金字塔层数(包括初始图像); levels = 1意味着不会创建额外的图层,只会使用原始图像
  • winsize,平均窗口大小;较大的值提高了算法对图像的鲁棒性,并可以检测更快速的运动,但会产生更模糊的运动场
  • iterations,每个金字塔等级上执行迭代算法的迭代次数。用于在每个像素中查找多项式展开的像素邻域;
  • poly_n,用于在每个像素中找到多项式展开的像素邻域的大小;较大的值意味着图像将近似于更平滑的表面,从而产生更多鲁棒算法和更模糊的运动场,通常poly_n=5或7
  • poly_sigma,于平滑导数的高斯的标准偏差,用作多项式展开的基础;对于poly_n = 5,可以设置poly_sigma = 1.1,对于poly_n = 7,可以设置poly_sigma = 1.5;
  • flags,操作标志,可取计算方法有:
    OPTFLOW_USE_INITIAL_FLOW 使用输入流作为初始流近似。
    OPTFLOW_FARNEBACK_GAUSSIAN 使用Gaussian winsize×winsiz过滤器代替光流估计的相同大小的盒子过滤器;通常情况下,这个选项可以比使用箱式过滤器提供更精确的流量,代价是速度更低;通常,应将高斯窗口的胜利设置为更大的值以实现相同的稳健性水平。

代码例子

官方例子,计算得到一个具有光流矢量(u,v)的双通道阵列。我们找到了它们的大小和方向。我们对结果进行颜色编码,以便更好地可视化。方向对应于图像的色调值。幅值对应于“值”平面。

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/video.hpp>

using namespace cv;
using namespace std;

int main()
{
    VideoCapture capture("../vtest.avi");
    if (!capture.isOpened()){
        //error in opening the video input
        cerr << "Unable to open file!" << endl;
        return 0;
    }

    Mat frame1, prvs;
    capture >> frame1;
    cvtColor(frame1, prvs, COLOR_BGR2GRAY);

    while(true){
        Mat frame2, next;
        capture >> frame2;
        if (frame2.empty())
            break;
        cvtColor(frame2, next, COLOR_BGR2GRAY);

        Mat flow(prvs.size(), CV_32FC2);
        calcOpticalFlowFarneback(prvs, next, flow, 0.5, 3, 15, 3, 5, 1.2, 0);

        // visualization
        Mat flow_parts[2];
        split(flow, flow_parts);
        Mat magnitude, angle, magn_norm;
        cartToPolar(flow_parts[0], flow_parts[1], magnitude, angle, true);
        normalize(magnitude, magn_norm, 0.0f, 1.0f, NORM_MINMAX);
        angle *= ((1.f / 360.f) * (180.f / 255.f));

        //build hsv image
        Mat _hsv[3], hsv, hsv8, bgr;
        _hsv[0] = angle;
        _hsv[1] = Mat::ones(angle.size(), CV_32F);
        _hsv[2] = magn_norm;
        merge(_hsv, 3, hsv);
        hsv.convertTo(hsv8, CV_8U, 255.0);
        cvtColor(hsv8, bgr, COLOR_HSV2BGR);

        imshow("frame2", bgr);
		imshow("img", prvs);

        int keyboard = waitKey(30);
        if (keyboard == 'q' || keyboard == 27)
            break;

        prvs = next;
    }
}

运行截图
截图

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

chasentech

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

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

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

打赏作者

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

抵扣说明:

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

余额充值