C++ OpenCV视频操作之稠密光流对象跟踪

前言

我们在学习完稀疏光流跟踪完后,我们再学习一下稠密光流对象跟踪,稠密光流算法(即图像上所有像素点的光流都计算出来),由于要计算图像上所有点的光流,故计算耗时,速度慢。一般来说我们在平时应用上可能会用到的比较少,在这里我们就简单讲解一下。

视频效果

看过稀疏光流的视频的人,再对比上面的视频可以看出来明显稠密光流跟踪的速度要慢不少,视频的播放都看出卡顿的感觉。

函数API

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 )
参数说明如下:

InputArray :输入前一帧图像

InputArray :输入后一帧图像

OutputArray :输出的光流

double:金字塔上下两层之间的尺度关系 

int :金字塔层数 

int:均值窗口大小,越大越能denoise并且能够检测快速移动目标,但会引起模糊运动区域

int:迭代次数 

int:像素领域大小,一般为5,7等

double:高斯标注差,一般为1-1.5

int:计算方法。主要包括OPTFLOW_USE_INITIAL_FLOW和OPTFLOW_FARNEBACK_GAUSSIAN

代码实现

我们再新建一个项目名为opencv--video4,按照配置属性(VS2017配置OpenCV通用属性),然后在源文件写入#include和main方法

先在外层读取第一帧图像

读取图像并时行稠密光流计算,下图红框内就是用到了我们的API,明显可以看出来这里比稀疏光流要简单些,因为不用再先获取特征点进行对比了,下面的蓝色框就是我们绘制结果的函数

代码结尾

绘制结果的函数

这样整个就完成了,文章开头的视频就是我们运行起来的效果,下面是视频中的截图

-END-

Vaccae的往期经典


OpenCV

《C++ OpenCV案例实战---卡号获取

《C++ OpenCV案例实战---卡片截取(附代码)

《C++ OpenCV透视变换---切换手机正面图片》

《C++ OpenCV实战---获取数量

《C++ OpenCV实战---利用颜色分割获取数量》


Android

《Android利用SurfaceView结合科大讯飞修改语音实别UI

《Android关于语音识别的功能实现分析(一)---结构化思维》

《Android关于语音识别的功能实现分析(二)---语义解析》

《Android根据类生成签名字符串

《Android碎片化布局fragment的实战应用


.Net C#

《C#自定义特性(Attribute)讲解与实际应用

《C#根据类生成签名字符串(附DEMO下载地址)


数据库及其它

《Oracel存储过程写报表实战》

《Delphi轮播视频和图片程序(用于双屏显示程序)

《SQL随机增加销售数据的脚本编写(附脚本下载地址)


长按下方二维码关注微卡智享

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
实现视频稠密光流跟踪需要以下步骤: 1. 创建一个PictureBox控件来显示视频帧。 2. 导入OpenCV库。 3. 打开视频文件,使用VideoCapture类来读取每一帧。 4. 对每一帧应用稠密光流跟踪算法,使用CalcOpticalFlowFarneback方法来计算光流向量。 5. 为了可视化光流向量,可以在每一帧上绘制箭头来表示光流方向和大小。 6. 将处理后的帧显示在PictureBox控件中。 以下是实现视频稠密光流跟踪的C#代码示例: ```csharp using System; using System.Drawing; using System.Windows.Forms; using OpenCvSharp; namespace DenseOpticalFlowDemo { public partial class Form1 : Form { private VideoCapture _capture; private Mat _previousFrame; private Mat _currentFrame; private Mat _outputFrame; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { // 打开视频文件 _capture = new VideoCapture("test.mp4"); if (!_capture.IsOpened()) { MessageBox.Show("Failed to open video file!"); Close(); return; } // 读取第一帧并转换为灰度图像 _capture.Read(_previousFrame); Cv2.CvtColor(_previousFrame, _previousFrame, ColorConversionCodes.BGR2GRAY); // 创建输出帧 _outputFrame = new Mat(_previousFrame.Rows, _previousFrame.Cols, MatType.CV_8UC3); } private void timer1_Tick(object sender, EventArgs e) { // 读取下一帧并转换为灰度图像 _capture.Read(_currentFrame); Cv2.CvtColor(_currentFrame, _currentFrame, ColorConversionCodes.BGR2GRAY); // 计算稠密光流向量 var flow = new Mat(); Cv2.CalcOpticalFlowFarneback(_previousFrame, _currentFrame, flow, 0.5, 3, 15, 3, 5, 1.2, 0); // 可视化光流向量 for (int y = 0; y < _outputFrame.Rows; y += 10) { for (int x = 0; x < _outputFrame.Cols; x += 10) { var flowVec = flow.At<Point2f>(y, x); Cv2.Line(_outputFrame, new Point(x, y), new Point((int)(x + flowVec.X), (int)(y + flowVec.Y)), Scalar.Red, 2); Cv2.Circle(_outputFrame, new Point(x, y), 2, Scalar.Blue, 2); } } // 将处理后的帧显示在PictureBox中 pictureBox1.Image = BitmapConverter.ToBitmap(_outputFrame); // 更新上一帧为当前帧 _previousFrame = _currentFrame.Clone(); } } } ``` 在上述代码中,我们使用了一个Windows Forms应用程序,其中包含一个PictureBox控件和一个计时器控件。在窗体加载时,我们打开视频文件并读取第一帧作为上一帧,以便在下一次计时器事件时使用。在计时器事件中,我们读取下一帧并计算稠密光流向量,然后在每个像素位置绘制箭头来表示光流方向和大小。最后,我们将处理后的帧显示在PictureBox控件中,更新上一帧为当前帧。 请注意,稠密光流跟踪是一项计算密集型任务,可能需要较长时间才能处理完整个视频。为了避免在UI线程上进行长时间计算,建议将计算过程放在单独的线程中执行,并使用Invoke方法在UI线程上更新PictureBox控件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Vaccae

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

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

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

打赏作者

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

抵扣说明:

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

余额充值