【opencv】教程代码 —video(2) optical_flow (稀疏光流、稠密光流)

1. optical_flow.cpp 稀疏光流

327118f3ebc8b7ffc68d1760fd32ff7b.png

62a05c48f5d9112269e05d4eae77878f.png

51be73ff14b7801fea9632f66d0711c8.png

#include <iostream> // 引入输入输出流库
#include <opencv2/core.hpp> // 引入OpenCV的核心功能模块
#include <opencv2/highgui.hpp> // 引入OpenCV的高级GUI模块,提供显示图像的功能
#include <opencv2/imgproc.hpp> // 引入OpenCV的图像处理模块
#include <opencv2/videoio.hpp> // 引入OpenCV的视频处理模块
#include <opencv2/video.hpp> // 引入OpenCV的视频分析模块using namespace cv; // 使用OpenCV命名空间
using namespace std; // 使用标准命名空间int main(int argc, char **argv) // 主函数
{const string about ="This sample demonstrates Lucas-Kanade Optical Flow calculation.\n" // 介绍这个程序,说它展示了如何计算Lucas-Kanade光流"The example file can be downloaded from:\n" // 提示样本文件可以从以下链接下载"  https://www.bogotobogo.com/python/OpenCV_Python/images/mean_shift_tracking/slow_traffic_small.mp4";const string keys ="{ h help |      | print this help message }" // 定义了一个帮助选项"{ @image | vtest.avi | path to image file }"; // 定义了一个输入参数,路径到视频文件,默认值为"vtest.avi"CommandLineParser parser(argc, argv, keys); // 使用命令行解析器来解析输入参数parser.about(about); // 设置关于信息if (parser.has("help")) // 如果有"help"参数{parser.printMessage(); // 打印帮助信息return 0; // 并退出程序}string filename = samples::findFile(parser.get<string>("@image")); // 获取输入视频文件的路径if (!parser.check()) // 检查解析的参数是否正确{parser.printErrors(); // 打印错误信息return 0; // 并退出程序}VideoCapture capture(filename); // 创建一个VideoCapture对象来捕捉视频if (!capture.isOpened()){ // 检查视频是否成功打开//error in opening the video inputcerr << "Unable to open file!" << endl; // 如果没有打开成功,输出错误信息return 0; // 并退出程序}// Create some random colorsvector<Scalar> colors; // 创建一个Scalar类型的向量,用于存储颜色RNG rng; // 随机数生成器for(int i = 0; i < 100; i++) // 生成100个随机颜色{int r = rng.uniform(0, 256); // 生成红色分量int g = rng.uniform(0, 256); // 生成绿色分量int b = rng.uniform(0, 256); // 生成蓝色分量colors.push_back(Scalar(r,g,b)); // 存储到颜色向量中}Mat old_frame, old_gray; // 声明两个Mat对象,用于存储前一帧的图像及其灰度图vector<Point2f> p0, p1; // 声明两个点的向量,用于存储角点的位置// Take first frame and find corners in itcapture >> old_frame; // 从视频中获取第一帧图像cvtColor(old_frame, old_gray, COLOR_BGR2GRAY); // 将图像转换成灰度图goodFeaturesToTrack(old_gray, p0, 100, 0.3, 7, Mat(), 7, false, 0.04); // 寻找前100个强角点存入p0// Create a mask image for drawing purposes// 创建一个和视频帧相同大小的mask用于绘画目的Mat mask = Mat::zeros(old_frame.size(), old_frame.type()); while(true){ // 循环处理视频的每帧图像Mat frame, frame_gray; // 每一帧图像及其灰度图capture >> frame; // 获取下一帧图像if (frame.empty()) // 如果获取的帧为空,即视频结束了break; // 跳出循环cvtColor(frame, frame_gray, COLOR_BGR2GRAY); // 将获取的帧转换成灰度图// calculate optical flowvector<uchar> status; // 一个标记向量,标记对于每个点,是否找到了光流vector<float> err; // 一个错误向量,存储了每一个点的误差TermCriteria criteria = TermCriteria((TermCriteria::COUNT) + (TermCriteria::EPS), 10, 0.03); // 设置迭代搜索算法的终止准则(10次迭代或误差小于0.03)calcOpticalFlowPyrLK(old_gray, frame_gray, p0, p1, status, err, Size(15,15), 2, criteria); // 计算光流,将结果存储于p1vector<Point2f> good_new; // 存储"流过"后的点for(uint i = 0; i < p0.size(); i++) // 遍历每一个点{// Select good pointsif(status[i] == 1) { // 如果该点的光流是良好的good_new.push_back(p1[i]); // 将其添加到good_new向量中// draw the tracksline(mask,p1[i], p0[i], colors[i], 2); // 在mask上画线追踪运动轨迹circle(frame, p1[i], 5, colors[i], -1); // 在当前帧上对运动点进行标记}}Mat img; // 声明一个Mat来存储结果图像add(frame, mask, img); // 将原图像和mask相加得到最终的图像imshow("Frame", img); // 显示图像int keyboard = waitKey(30); // 等待30ms或者某个按键被按下if (keyboard == 'q' || keyboard == 27) // 如果按下了'q'键或者Esc键break; // 跳出循环// Now update the previous frame and previous pointsold_gray = frame_gray.clone(); // 更新前一帧的灰度图p0 = good_new; // 更新角点}
}

这段代码的主要功能是使用OpenCV库来实现Lucas-Kanade光流算法的计算。程序首先读取一个视频文件,然后在视频的第一帧中找到角点使用这些角点计算每一帧之间的光流,从而追踪画面中的物体运动。追踪的过程中,程序对每个有效的点在画面上绘制标记,并通过颜色区分不同的轨迹。最终显示在窗口中的是这些运动轨迹的叠加效果。当按下'q'键或Esc键时,程序结束。

29271e84f8d884f75e9f6ae849cf5125.png

calcOpticalFlowPyrLK(old_gray, frame_gray, p0, p1, status, err, Size(15,15), 2, criteria);

9e6aa44cd095adb11c3a81f869b78315.png

2. optical_flow_dense.cpp 稠密光流

c54626959b667db9c97cd633dcf0f598.png

31a3ebd7bc547729b8b218bc087d7398.png

e4432f42e48c9cea98c19aa706483218.png

#include <iostream> // 引入输入输出流库
#include <opencv2/core.hpp> // 引入OpenCV核心功能模块头文件
#include <opencv2/highgui.hpp> // 引入OpenCV高级用户界面模块头文件
#include <opencv2/imgproc.hpp> // 引入OpenCV图像处理模块头文件
#include <opencv2/videoio.hpp> // 引入OpenCV视频输入输出模块头文件
#include <opencv2/video.hpp> // 引入OpenCV视频分析模块头文件using namespace cv; // 使用OpenCV命名空间
using namespace std; // 使用标准命名空间int main() // 主函数
{VideoCapture capture(samples::findFile("vtest.avi")); // 创建视频捕获对象并打开文件if (!capture.isOpened()){ // 如果视频文件没有成功打开cerr << "Unable to open file!" << endl; // 输出错误信息到标准错误return 0; // 退出程序}Mat frame1, prvs; // 定义两个Mat对象,分别用于存储第一帧和前一帧的图像capture >> frame1; // 从视频中读取第一帧cvtColor(frame1, prvs, COLOR_BGR2GRAY); // 将第一帧转换为灰度图像,存储在prvs中while(true){ // 循环处理视频中的每一帧Mat frame2, next; // 定义两个Mat对象,用于存储当前帧和转换后的灰度帧capture >> frame2; // 从视频中读取当前帧if (frame2.empty()) // 如果当前帧为空,表示视频结束break; // 跳出循环cvtColor(frame2, next, COLOR_BGR2GRAY); // 将当前帧转换为灰度图像Mat flow(prvs.size(), CV_32FC2); // 定义一个Mat对象,用于存储光流calcOpticalFlowFarneback(prvs, next, flow, 0.5, 3, 15, 3, 5, 1.2, 0); // 计算前一帧和当前帧之间的光流// 下面的代码块用于可视化光流Mat flow_parts[2]; // 定义一个Mat数组,用于分割光流的x和y分量split(flow, flow_parts); // 分割光流Mat magnitude, angle, magn_norm; // 定义幅度、角度和归一化幅度的Mat对象cartToPolar(flow_parts[0], flow_parts[1], magnitude, angle, true); // 将笛卡尔坐标转换为极坐标,获取幅度和角度normalize(magnitude, magn_norm, 0.0f, 1.0f, NORM_MINMAX); // 将幅度归一化到0到1之间angle *= ((1.f / 360.f) * (180.f / 255.f)); // 将角度转换到0到255之间的范围内(用于HSV颜色空间)//构建HSV图像Mat _hsv[3], hsv, hsv8, bgr; // 定向Mat对象,用于构建HSV图像和转换后的BGR图像_hsv[0] = angle; // 角度作为H通道_hsv[1] = Mat::ones(angle.size(), CV_32F); // 饱和度设置为1,全部是白色_hsv[2] = magn_norm; // 归一化后的幅度作为V通道merge(_hsv, 3, hsv); // 合并上面的三个通道来构建一个HSV图像hsv.convertTo(hsv8, CV_8U, 255.0); // 将32位float型的HSV图像转换为8位unsigned char型cvtColor(hsv8, bgr, COLOR_HSV2BGR); // 将HSV颜色空间的图像转换为BGR颜色空间imshow("frame2", bgr); // 在窗口中显示BGR图像int keyboard = waitKey(30); // 等待30ms的按键事件,若无事件则继续if (keyboard == 'q' || keyboard == 27) // 如果按键是'q'或者ESC键break; // 跳出循环,结束程序prvs = next; // 更新前一帧的图像}
}

该段代码是使用 OpenCV 图像处理库和视频分析库来实现对视频文件进行光流分析和可视化的程序。首先通过VideoCapture对象捕获视频文件中的帧,然后将每两帧之间的光流分析出来,并将光流的信息可视化为BGR颜色空间中的图像,最后在窗口中显示这些图像。通过键盘输入可以控制程序的结束。美观化显示的过程主要是将光流场的每个点的方向(角度)转换成颜色,速度(幅度)转换成颜色亮度来实现。这对于理解和分析视频中的运动模式非常有帮助。

3d8f6aae9370c8c28ccf721f3d78347e.png

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python | NCL风格 | EOF | 相关 | 回归

这里在linux系统上使用geocat实现NCL风格的图片绘制 geocat Linux上安装 geocat conda update condaconda create -n geocat -c conda-forge geocat-vizconda activate geocatconda update geocat-viz Dataset - NOAA Optimum Interpolation (OI) SST V2 # 海温月平均数据- lsm…

C++核心高级编程 --- 4.类和对象

文章目录 第四章&#xff1a;4.类和对象4.1 封装4.1.1 封装的意义4.1.2 struct与class的区别 4.2 对象的初始化和清理4.2.1 构造函数和析构函数4.2.2 构造函数的分类及调用4.2.3 拷贝构造函数调用时机4.2.4 构造函数调用规则4.2.5 深拷贝与浅拷贝4.2.6 初始化列表4.2.7 类对象作…

基础之重蹈覆辙

MESI缓存一致性协议 前&#x1f33d;&#xff1a; 高速缓存底层数据结构&#xff1a;拉链散列表的结构 bucket - cache entry - tag主内存地址 cache line缓存数据 flag缓存行状态 cache line64字节 有效引用主内存地址&#xff0c;连续的相邻的数据结构 读取特别快 处理器…

关于Tomcat双击startup.bat 闪退的解决⽅法

详解Tomcat双击startup.bat 闪退的解决⽅法 作为⼀个刚学习Tomcat的程序猿来说&#xff0c;这是会经常出现的错误。 1.环境变量问题 1.1 ⾸先需要确认java环境是否配置正确&#xff0c;jdk是否安装正确 winR打开cmd&#xff0c;输⼊java 或者 javac 出现下图所⽰就说明jdk配置正…

spark-hive连接操作流程、踩坑及解决方法

文章目录 1 简介2 版本匹配3 spark hive支持版本源码编译3.1 spark-src下载3.2 maven换源3.3 spark编译 4 hive 安装与mysql-metastore配置4.1 mysql下载安装4.1.1 为mysql设置系统环境变量4.1.2 初次登陆更改root身份密码4.1.3 安装后直接更改密码 4.2 hive初始化4.2.1 编写hi…

pycharm pyspark连接虚拟机的hive表 读取数据

方法&#xff1a; hive配置hiveserver2和metastore url <!-- 指定hiveserver2连接的host --> <property><name>hive.server2.thrift.bind.host</name><value>hadoop111</value> </property><!-- 指定hiveserver2连接的端口号 -…

langchain + azure chatgpt组合配置并运行

首先默认你已经有了azure的账号。 最重要的是选择gpt-35-turbo-instruct模型、api_version&#xff1a;2023-05-15&#xff0c;就这两个参数谷歌我尝试了很久才成功。 我们打开https://portal.azure.com/#home&#xff0c;点击更多服务&#xff1a; 我们点击Azure OpenAI&#…

华为ensp中ospf多区域管理 原理及配置命令(详解)

作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; ————前言———— OSPF 多区域的主要作用是缩小链路状态数据库和路由表的规模&#xff0c;减少路由更新的频率&#xff0c;提高网络的可扩展性&#xff0c;实现路由过滤和路由汇总&#xff0…

A First Course in the Finite Element Method【Daryl L.】|PDF电子书

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

zdpcss_transparent_animation_login:使用纯HTML+CSS+JS开发支持设置主题和带动画的科技风登录界面

废话不多说&#xff0c;先上图&#xff0c;有图有真相&#xff1a; 在左下角有一排颜色&#xff0c;点击可以设置主题色&#xff1a; 比如&#xff0c;我这里点击了橙色&#xff0c;登录界面就变成了如下样子&#xff1a; 另外&#xff0c;在输入账号和密码的时候&#x…

使用 ChatGPT 创建在线课程:一步一步指南与提示模板

原文&#xff1a;Creating Online Courses with ChatGPT 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 谢谢 作为对你支持的感谢&#xff0c;随意定制本书中列出的任何提示&#xff0c;并将其作为你自己的重新销售。是的&#xff0c;对你免费。 它们都结构良好且用…

蓝桥杯—DS1302

目录 1.管脚 2.时序&官方提供的读写函数 3.如何使用读写函数 4.如何在数码管中显示在DS1302中读取出的数据&#xff1f; 1.管脚 2.时序&官方提供的读写函数 /* # DS1302代码片段说明1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。2. 参赛选手可以自行…

韩顺平Java | C23 反射Reflection

需求&#xff1a;通过外部文件配置&#xff0c;在不修改源码情况下控制程序&#xff08;符合设计模式ocp开闭原则&#xff1a;不修改源码的情况下扩容功能&#xff09; ※反射机制 反射机制允许程序在执行期间借助于ReflectioAPI取得任何类的内部信息&#xff08;如成员变量&…

跨境金融区块链服务平台

跨境金融服务是因企业及个人跨境经营、交易、投资、往来等活动而产生的资金使用、调拨、配置等需求&#xff0c;而提供的金融服务。近年来&#xff0c;随着我国经济的快速稳步增长和全球化经济一体化的不断深入发展&#xff0c;跨境金融业务增长迅速&#xff0c;监管也开始转化…

AcWing 731. 毕业旅行问题(每日一题)

原题链接&#xff1a;731. 毕业旅行问题 - AcWing题库 此题难度较大&#xff0c;是2019年字节跳动校招题&#xff0c;里面涉及位运算与状态压缩DP&#xff0c;不会的可以去学习&#xff0c;此题根据个人量力而行。 建议看一下y总的讲解&#xff1a;AcWing 731. 毕业旅行问题&…

初识MySQL(中篇)

使用语言 MySQL 使用工具 Navicat Premium 16 代码能力快速提升小方法&#xff0c;看完代码自己敲一遍&#xff0c;十分有用 目录 1.SQL语言 1.1 SQL语言组成部分 2.MySQL数据类型 2.1 数值类型 2.2 字符串类型 2.3 日期类型 3.创建数据表 3.1 创建数据表方法1 …

Mybitis根据Date查询,查询不到数据的一种情况

使用SimpleDateFormat创建Date对象时&#xff0c;调用SimpleDateFormat构造方法时格式要写为“yyyy-MM-dd”&#xff0c;如果写成“yyyy-mm-dd”会查询不到数据

2024-HW --->SSRF

这不是马上准备就要护网了嘛&#xff0c;如火如荼的报名ing&#xff01;&#xff01;&#xff01;那么小编就来查缺补漏一下以前的web漏洞&#xff0c;也顺便去收录一波poc&#xff01;&#xff01;&#xff01;&#xff01; 今天讲的主人公呢就是SSRF&#xff0c;以前学的时候…

windows server 配置DNS

配置DNS为本机IPV4地址 安装DNS服务器&#xff08;默认即可&#xff09;

【C++ STL排序容器】set 集合

文章目录 【 1. 基本原理 】【 2. set 的定义 】2.1 调用默认构造函数&#xff0c;创建空的 set 容器2.2 在创建 set 容器的同时&#xff0c;对其进行初始化2.3 拷贝构造的方式创建2.4 取已有 set 容器中的部分元素&#xff0c;来初始化新 set 容器2.5 修改排序规则的方式创建 …