Opencv4+稀疏光流算法详解+实现

0. 写在前面

        项目需要用到光流法找到图像中的点运动方向,想到光流法刚好适用。原理部分参考:          图像处理算法--光流法-原理-CSDN博客

1. Opencv4.5.4稀疏光流函数说明
1.1 稀疏光流API介绍
 
  • prevImg:视频前一帧图像/金字塔,单通道CV_8UC1
  • nextImg:视频后一帧图像/金字塔,单通道CV_8UC1
  • prevPts:前一帧图像的特征向量(输入)需要找到流的2D点的矢量,点坐标必须是单精度浮点数
  • nextPts:后一帧图像的特征向量(输出),输出二维点的矢量(具有单精度浮点坐标),包含第二图像中输入特征点计算新位置;当传递OPTFLOW_USE_INITIAL_FLOW标志时,向量必须与输入中的大小相同
  • status:输出状态向量(无符号字符);如果找到相应特征的流,则向量的每个元素设置为1,否则设置为0
  • err:输出错误矢量
  • winSize:每个金字塔等级的搜索窗口winSize大小
  • maxLevel:基于0的最大金字塔等级数,如果设置为0,则不使用金字塔,如果设置为1,则使用两个类别,依次类推,如果将金字塔传递给输入,那么算法将使用与金字塔一样多的级别,但不超过maxLevel
  • criteria:停止条件,指定迭代搜索算法的终止条件
  • flags:操作标志,OPTFLOW_USE_INITIAL_FLOW使用初始估计,存储在nextPts中;如果未设置标志,则将prevPts复制到nextPts并将其视为初始估计。
  • OPTFLOW_LK_GET_MIN_EIGENVALS使用最小特征值作为误差测量(参见minEigThreshold描述);如果没有设置标志,则将原稿周围的色块和移动点之间的L1距离除以窗口中的像素数,用作误差测量
  • minEigThreshold:算法计算光流方程的2x2正常矩阵的最小特征值,除以窗口中的像素数;如果此值小于minEigThreshold,则过滤掉相应的功能并且不处理其流程,因此它允许删除坏点并获得性能提升。
1.2 算法实现步骤
  1. 实例化VideoCapture,循环读取视频数据,视频帧灰度转换;
  2. 执行角点检测,保存角点检测的特征数据;
  3. 初始化时如果检测到前一帧为空,把当前帧的灰度图像给前一帧;
  4. 执行光流跟踪,并输出跟踪后的特征向量;
  5. 遍历光流跟踪的输出特征向量,并得到距离和状态都符合预期的特征向量;
  6. 重置集合大小,绘制光流线,交换特征向量的输入和输出;
  7. 将用于跟踪的角点绘制出来,展示最终的跟踪效果。
1.3 代码如下
void MainWindow::on_pBtn_OpenFile_clicked()
{
    //打开图片文件,选择图片
    QString filename = QFileDialog::getOpenFileName(this,tr("Open File"),QDir::homePath(),tr("所有文件(*.avi *.mp4 *.h624 *.mkv)\n(*.jpg)\n(*.bmp)\n(*.png)"));

    capture.open(filename.toStdString()); //.toStdString()

    if(!capture.isOpened())
    {
        ui->statusBar->showMessage(tr("Open Video Failed!"));
    }
    else
    {
        ui->statusBar->showMessage(tr("Open Video Success!"));
    }

    Mat frame,gray;
    vector<Point2f> features;//检测出来的角点集合
    vector<Point2f> inPoints;//这个主要是为了画线用的
    vector<Point2f> fpts[2];//[0],存入的是是二维特征向量,[1]输出的二维特征向量
    Mat pre_frame,pre_gray;
    vector<uchar> status;//光流输出状态
    vector<float> err;//光流输出错误
    //【2】循环读取视频
    while(capture.read(frame))
    {//循环读取视频中每一帧的图像
       //【3】将视频帧图像转为灰度图
       cvtColor(frame,gray,COLOR_BGR2GRAY);//ps:角点检测输入要求单通道

       //【4】如果特征向量(角点)小于40个我们就重新执行角点检测
       if(fpts[0].size()<40){//如果小于40个角点就重新开始执行角点检测
           //执行角点检测
           goodFeaturesToTrack(gray,features,5000,0.01,10,Mat(),3,false,0.04);
           //【5】将检测到的角点放入fpts[0]中作为,光流跟踪的输入特征向量
           //将检测到的角点插入vector
           fpts[0].insert(fpts[0].begin(),features.begin(),features.end());
           inPoints.insert(inPoints.end(),features.begin(),features.end());
           qDebug()<<"角点检测执行完成,角点个数为:"<<features.size();
       }else{
           qDebug()<<"正在跟踪...";
       }
       //【6】初始化的时候如果检测到前一帧为空,这个把当前帧的灰度图像给前一帧
       if(pre_gray.empty()){//如果前一帧为空就给前一帧赋值一次
           gray.copyTo(pre_gray);
       }

       //执行光流跟踪
       qDebug()<<"开始执行光流跟踪";
       //【7】执行光流跟踪,并将输出的特征向量放入fpts[1]中
       calcOpticalFlowPyrLK(pre_gray,gray,fpts[0],fpts[1],status,err);
       qDebug()<<"光流跟踪执行结束";
       //【8】遍历光流跟踪的输出特征向量,并得到距离和状态都符合预期的特征向量。让后将其重新填充到fpts[1]中备用
       int k =0;
       for(size_t i=0;i<fpts[1].size();i++){//循环遍历二维输出向量
           double dist = abs(fpts[0][i].x - fpts[1][i].x) + abs(fpts[0][i].y - fpts[1][i].y);//特征向量移动距离
           if(dist>2&&status[i]){//如果距离大于2,status=true(正常)
               inPoints[k] = inPoints[i];
               fpts[1][k++] = fpts[1][i];
           }
       }
       //【9】重置集合大小(由于有错误/不符合条件的输出特征向量),只拿状态正确的
       //重新设置集合大小
       inPoints.resize(k);
       fpts[1].resize(k);
       //【10】绘制光流线,这一步要不要都行
       //绘制光流线
       if(true){
           for(size_t i = 0;i<fpts[1].size();i++){
               line(frame,inPoints[i],fpts[1][i],Scalar(0,255,0),1,8,0);
               circle(frame, fpts[1][i], 2, Scalar(0, 0, 255), 2, 8, 0);
           }
       }

       qDebug()<<"特征向量的输入输出交换数据";
       //【11】交换特征向量的输入和输出,(循环往复/进入下一个循环),此时特征向量的值会递减
       std::swap(fpts[1],fpts[0]);//交换特征向量的输入和输出,此处焦点的总数量会递减

       //【12】将用于跟踪的角点绘制出来
       //将角点绘制出来
       for(size_t i = 0;i<fpts[0].size();i++){
           circle(frame,fpts[0][i],2,Scalar(0,0,255),2,8,0);
       }

       //【13】重置前一帧图像(每一个循环都要刷新)
       gray.copyTo(pre_gray);
       frame.copyTo(pre_frame);
       //【14】展示最终的效果
       imshow("frame",frame);
       int keyValue = waitKey(100);
       if(keyValue==27){//如果用户按ese键退出播放
           break;
       }
    }

}
   3. 效果演示 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/466206.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

获取远程管理软件保存的凭据

点击星标&#xff0c;即时接收最新推文 本文选自《内网安全攻防&#xff1a;红队之路》 扫描二维码五折购书 内网敏感数据的发现 内网的核心敏感数据&#xff0c;不仅包括数据库、电子邮件&#xff0c;还包括个人数据及组织的业务数据、技术数据等。可以说&#xff0c;价值较高…

(零)OpenOFDM接收端整体思路

一旦捕获射频信号并将其下变频至基带&#xff0c;解码管道就会启动&#xff0c;包括&#xff1a; OFDM&#xff0c;多载波调制的一种。通过频分复用实现高速串行数据的并行传输, 它具有较好的抗多径衰落的能力&#xff0c;能够支持多用户接入。 OFDM主要思想是&#xff1a;将信…

(1)fopen,fseek,fread,ftell,rewind作用和使用方法,大端小端

文章目录 1.fopen&#xff0c;fseek&#xff0c;fread&#xff0c;ftell&#xff0c;rewind作用和使用方法2.bin文件里从0x0000到0x0x0007是00 00 DF 00 00 01 00 00&#xff0c;但是用fread读出来前四个字节是DF0000&#xff0c;然后是0x1000&#xff0c;这是为什么&#xff1…

2024蓝桥杯每日一题(回溯)

备战2024年蓝桥杯 -- 每日一题 Python大学A组 试题一&#xff1a;木棒 试题二&#xff1a;n皇后问题 试题三&#xff1a;糖果 试题四&#xff1a;飞机降落 试题五&#xff1a;生日蛋糕 试题一&#xff1a;木棒 【问题描述】 乔治拿来一组等长…

steam_api.dll“是什么?打开游戏出现找不到steam_api.dll无法继续执行代码如何解决

"steam_api.dll"是什么&#xff1f;&#xff0c;steam_api.dll它是由windows系统Visual C Redistributable for Visual Studio提供的。当这个文件损坏或丢失时&#xff0c;会导致一些应用程序无法运行&#xff0c;显示找不到"steam_api.dll"缺失错误。本文…

马斯克开源的grok AI大模型

马斯克践行诺言&#xff0c;坚持开源原则&#xff0c;选择开源自家的 AI 大模型——Grok-1 下载链接如下: https://github.com/xai-org/grok-1 Grok-1 开源仅过去了 10 个小时&#xff0c;该项目便获得了 超过16k 的 Star&#xff0c;成为众人关注的焦点所在。 后续继续更新…

Python二级备考(1)考纲+基础操作

考试大纲如下&#xff1a; 基本要求 考试内容 考试方式 比较希望能直接刷题&#xff0c;因为不懂的比较多可能会看视频。 基础操作刷题&#xff1a; 知乎大头计算机1-13题 import jieba txtinput() lsjieba.lcut(txt) print("{:.1f}".format(len(txt)/len(ls)…

springcloud:4.2 GateWay结合JWT实现网关鉴权

概述 概述 简介 JWT是一种用于双方之间传递安全信息的简洁的、URL安全的声明规范。 定义了一种简洁的,自包含的方法用于通信双方之间以Json对象的形式安全的传递信息。 特别适用于分布式站点的单点登录(SSO)场景 传统的session认证的缺点 安全性:CSRF攻击因为基于cookie来…

掌握AI写作工具:引领内容创作潮流

随着技术发展&#xff0c;AI技术正日益渗透到各行各业&#xff0c;并对内容创作领域产生了深远影响。随着AI写作工具的不断发展和普及&#xff0c;内容创作者们正逐渐看到了AI在提高效率、创造力和质量方面的巨大潜力。本文将探讨AI写作工具如何引领内容创作潮流&#xff0c;以…

vue antd table嵌套表格 左侧展开图标动态控制显示隐藏

antd a-table想要实现如以下效果&#xff0c;有子级就显示展开图标&#xff0c;没有就不显示图标&#xff1a; 话不多说&#xff0c;直接上代码&#xff1a; <template><a-table :columns"columns" :data-source"dataSource"><template #b…

最新若依项目快速上手

最新若依项目快速上手 配套视频&#xff1a;若依项目快速上手视频 1. 下载源码 官网&#xff1a;https://ruoyi.vip/ 前端 git clone https://github.com/yangzongzhuan/RuoYi-Vue3.git后端 git clone https://gitee.com/y_project/RuoYi-Vue.git2. 数据库 创建数据库ry-vue…

JAVA后端调用OpenAI接口 实现打字机效果(SSE)

SSE SSE&#xff08;Server-Sent Events&#xff0c;服务器发送事件&#xff09;是一种基于HTTP协议的通信技术&#xff0c;它允许服务器持续地将数据推送给客户端&#xff0c;而无需客户端发起请求。这种通信方式通常用于实时性要求较高的场景&#xff0c;如实时更新、通知、或…

Linux:搭建ntp服务器

我准备两个centos7服务器 一个为主服务器连接着外网&#xff0c;并且搭建了ntp服务给其他主机同步 另外一个没有连接外网&#xff0c;通过第一台设备去同步时间 首先两个服务器都要安装ntp软件 yum -y install ntp 再把他俩的时间都改成别的 左侧的是主服务器&#xff0c;主…

【Docker篇】自定义Dockerfile的操作

文章目录 &#x1f354;镜像结构&#x1f6f8;什么是Dockerfile⭐基于Ubuntu镜像构建一个新镜像&#xff0c;运行一个java项目&#x1f50e;使用 java:8-alpine &#x1f354;镜像结构 镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。 我们以MySQL为例&am…

JVM中对象创建过程

在JVM中对象的创建&#xff0c;我们从一个new指令开始&#xff1a; 这个过程大概图示如下&#xff1a; 虚拟机收到new指令触发。 类加载检查&#xff1a;如果类没有被类加载器加载&#xff0c;则执行类加载流程&#xff08;将class信息加载到JVM的运行时数据区的过程&#xff…

KiCad 从原理图创建或者导出原理图符号

KiCad 从原理图创建或者导出原理图符号 原理图中&#xff0c;在下那个要导出的符号上点击右键-》属性-》编辑符号 在符号编辑中选择&#xff1a;文件-》导出符号 加微信&#xff1a;jiyuyun18, 交流电子技术 留言&#xff1a;CSND 电子技术交流群&#xff0c;加入电子微信电…

如何利用生成式AI进行品牌定位调研?

在激烈的市场竞争中&#xff0c;一个明确的品牌定位能够帮助企业突出其独特性&#xff0c;吸引并保留目标消费者。品牌定位调研是企业了解自身、竞争对手以及市场需求的重要手段&#xff0c;是制定有效市场策略的基础。本文将详细介绍如何进行品牌定位调研&#xff0c;包括调研…

PyTorch学习笔记之激活函数篇(四)

4、 Leaky ReLU 函数 4.1 公式 Leaky ReLU函数的公式&#xff1a; f ( x ) { x , x > 0 λ x , x < 0 , λ ∈ ( 0 , 1 ) f(x) \begin{cases} x&,x>0 \\ \lambda x&,x<0,\lambda \in(0,1) \end{cases} f(x){xλx​,x>0,x<0,λ∈(0,1)​ Leakly R…

MySQL连接数不足导致服务异常GetConnectionTimeoutException

文章目录 场景复现解决方案一、调整连接数二、优化程序 场景复现 已经上线正常运行的项目突然很多功能无法使用&#xff0c;查看程序日志发现MySQL报错&#xff0c;异常信息: Could not open JDBC Connection for transaction; nested exception is com.alibaba.druid.pool.Ge…

分布式(计算机算法)

目录 分布式计算 分布式​编辑 分布式和集群 分布式和集群的应用场景 分布式应用场景 集群应用场景 哪种技术更优、更快、更好呢 性能 稳定性 以下概念来源于百度百科 分布式计算 分布式计算是近年提出的一种新的计算方式。所谓分布式计算就是在两个或多个软件互相共享信息…