【opencv】教程代码 —video(1) 对象追踪

CamShift算法、MeanShift追踪算法来追踪视频中的一个目标

  1. camshift.cpp CamShift算法

d51b48a7669b92e019bd2da22a42a82d.png

90fae2165e3fcf0f90138f745c9da3c8.png

9603051895892a58938b263df76c9a9b.png

// 引入相关的头文件
#include <iostream> // 包含C++的输入输出流库
#include <opencv2/imgcodecs.hpp> // OpenCV图像编解码功能
#include <opencv2/imgproc.hpp> // OpenCV图像处理功能
#include <opencv2/videoio.hpp> // OpenCV视频I/O操作
#include <opencv2/highgui.hpp> // OpenCV高级GUI功能
#include <opencv2/video.hpp> // OpenCV视频处理功能


// 使用命名空间,简化代码中的命名
using namespace cv; // OpenCV命名空间
using namespace std; // 标准命名空间


// 主函数
int main(int argc, char **argv)
{
    // 关于程序的说明字符串
    const string about =
        "This sample demonstrates the camshift algorithm.\n"
        "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 |<none>| path to image file }";
    // 解析命令行参数
    CommandLineParser parser(argc, argv, keys);
    parser.about(about);
    // 如果命令行中包含帮助参数,则输出帮助信息并退出程序
    if (parser.has("help"))
    {
        parser.printMessage();
        return 0;
    }
    // 获取图像文件路径
    string filename = parser.get<string>("@image");
    // 检查参数解析是否成功
    if (!parser.check())
    {
        parser.printErrors();
        return 0;
    }


    // 打开视频文件
    VideoCapture capture(filename);
    // 检查视频是否成功打开
    if (!capture.isOpened()){
        // 打开失败时打印错误信息并退出程序
        cerr << "Unable to open file!" << endl;
        return 0;
    }


    // 声明一些变量用于处理图像
    Mat frame, roi, hsv_roi, mask;
    // 读取视频的第一帧
    capture >> frame;


    // 设置跟踪窗口的初始位置  // 这里硬编码了窗口的值
    Rect track_window(300, 200, 100, 50);


    // 设置追踪的区域
    roi = frame(track_window);
    // 将感兴趣区域(ROI)的颜色空间转换为HSV
    cvtColor(roi, hsv_roi, COLOR_BGR2HSV);
    // 过滤HSV图像中的某些颜色区域,并生成遮罩图像
    inRange(hsv_roi, Scalar(0, 60, 32), Scalar(180, 255, 255), mask);


    // 直方图的参数设置
    float range_[] = {0, 180};
    const float* range[] = {range_};
    Mat roi_hist;
    int histSize[] = {180};
    int channels[] = {0};
    // 计算HSV图像的直方图
    calcHist(&hsv_roi, 1, channels, mask, roi_hist, 1, histSize, range);
    // 标准化直方图
    normalize(roi_hist, roi_hist, 0, 255, NORM_MINMAX);


    // 设置迭代的终止条件,要么是迭代10次,要么至少移动1pt
    TermCriteria term_crit(TermCriteria::EPS | TermCriteria::COUNT, 10, 1);


    // 循环处理视频帧
    while(true){
        Mat hsv, dst;
        // 读取一帧图像
        capture >> frame;
        // 如果读取到空帧,则退出循环
        if (frame.empty())
            break;
        // 将图像从BGR转换到HSV色彩空间
        cvtColor(frame, hsv, COLOR_BGR2HSV);
        // 计算反向投影
        calcBackProject(&hsv, 1, channels, roi_hist, dst, range);


        // 应用camshift算法获取新的窗口位置
        RotatedRect rot_rect = CamShift(dst, track_window, term_crit);


        // 在图像上绘制旋转矩形
        Point2f points[4];
        rot_rect.points(points);
        for (int i = 0; i < 4; i++)
            line(frame, points[i], points[(i+1)%4], 255, 2);
        // 显示图像
        imshow("img2", frame);


        // 处理键盘输入
        int keyboard = waitKey(30);
        // 如果按下'q'或Esc键,则退出循环
        if (keyboard == 'q' || keyboard == 27)
            break;
    }
}

这段C++代码使用OpenCV库实现了一个CamShift算法演示程序,用于视频中的对象跟踪。程序首先通过命令行参数获取一个视频文件的路径,然后打开这个视频,设置一个追踪窗口,并计算出该窗口内图像的HSV色彩空间直方图。在一个循环中,程序不断地读取视频帧,计算直方图的反向投影,并利用CamShift算法更新追踪窗口的位置,最后将更新后的位置用椭圆形状绘制在视频帧上,并显示处理后的视频帧。程序允许用户通过按键退出追踪循环。

inRange(hsv_roi, Scalar(0, 60, 32), Scalar(180, 255, 255), mask);

e8a05d0fc950fffc8906a0bf87025aec.png

calcHist(&hsv_roi, 1, channels, mask, roi_hist, 1, histSize, range);

47010e0085199420fcee231875a2586c.png

calcBackProject(&hsv, 1, channels, roi_hist, dst, range);

3a601f31e89e1148449dccf059116b51.png

2. meanshift.cpp MeanShift追踪算法来追踪视频中的一个目标

238f9e894dbc12f05742fa310ab03256.png

#include <iostream> // 引入标准输入输出流库
#include <opencv2/imgcodecs.hpp> // 引入OpenCV图像编解码库
#include <opencv2/imgproc.hpp> // 引入OpenCV图像处理库
#include <opencv2/videoio.hpp> // 引入OpenCV视频输入输出库
#include <opencv2/highgui.hpp> // 引入OpenCV高层GUI库
#include <opencv2/video.hpp> // 引入OpenCV视频分析库


using namespace cv;  // 使用OpenCV命名空间
using namespace std; // 使用标准命名空间


// 主程序入口点
int main(int argc, char **argv)
{
    // 关于本示例的简介
    const string about =
        "This sample demonstrates the meanshift algorithm.\n"
        "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 |<none>| path to image file }";
    CommandLineParser parser(argc, argv, keys); // 创建命令行解析器
    parser.about(about); // 设置关于信息
    if (parser.has("help")) // 如果命令行参数中有help
    {
        parser.printMessage(); // 打印帮助信息
        return 0; // 退出程序
    }
    string filename = parser.get<string>("@image"); // 获取图像文件的路径
    if (!parser.check()) // 检查命令行参数
    {
        parser.printErrors(); // 打印错误
        return 0; // 退出程序
    }


    VideoCapture capture(filename); // 创建视频捕获对象
    if (!capture.isOpened()){ // 检查是否成功打开视频文件
        cerr << "Unable to open file!" << endl; // 打印无法打开文件的错误信息
        return 0; // 退出程序
    }


    Mat frame, roi, hsv_roi, mask; // 定义矩阵变量:帧,感兴趣区域,HSV色彩空间的感兴趣区域,掩码
    capture >> frame; // 读取视频的第一帧


    // 设置追踪窗口的初始位置
    Rect track_window(300, 200, 100, 50); // 硬编码窗口的值


    // 设置追踪的ROI
    roi = frame(track_window); // 选取感兴趣区域
    cvtColor(roi, hsv_roi, COLOR_BGR2HSV); // 将感兴趣区域转换为HSV色彩空间
    inRange(hsv_roi, Scalar(0, 60, 32), Scalar(180, 255, 255), mask); // 对HSV空间进行颜色范围限定


    float range_[] = {0, 180}; // 定义直方图的范围
    const float* range[] = {range_}; // 设置直方图的范围
    Mat roi_hist; // 定义感兴趣区域的直方图
    int histSize[] = {180}; // 定义直方图的大小
    int channels[] = {0}; // 定义使用的通道
    calcHist(&hsv_roi, 1, channels, mask, roi_hist, 1, histSize, range); // 计算直方图
    normalize(roi_hist, roi_hist, 0, 255, NORM_MINMAX); // 归一化直方图


    // 设置终止条件,迭代10次或至少移动1个点
    TermCriteria term_crit(TermCriteria::EPS | TermCriteria::COUNT, 10, 1); // 创建终止条件


    while(true){ // 循环进行追踪
        Mat hsv, dst; // 定义矩阵变量:HSV色彩空间图像,目标图像
        capture >> frame; // 读取视频帧
        if (frame.empty()) // 如果帧为空则跳出循环
            break;
        cvtColor(frame, hsv, COLOR_BGR2HSV); // 将帧转换为HSV色彩空间
        calcBackProject(&hsv, 1, channels, roi_hist, dst, range); // 计算反向投影


        // 应用meanshift算法获取新的位置
        meanShift(dst, track_window, term_crit); 


        // 在图像上绘制追踪窗口
        rectangle(frame, track_window, 255, 2); 
        imshow("img2", frame); // 显示窗口


        int keyboard = waitKey(30); // 等待键盘输入
        if (keyboard == 'q' || keyboard == 27) // 如果输入'q'或Esc则退出循环
            break;
    }
}

该代码使用C++和OpenCV库实现了MeanShift追踪算法来追踪视频中的一个目标。程序首先解析命令行参数来获取视频文件路径,然后使用OpenCV的视频捕获功能来读取视频。它设置了一个初始追踪窗口,计算该窗口中的颜色直方图,并使用归一化处理。接着,程序进入一个循环,在循环中通过MeanShift算法更新追踪窗口的位置,并在视频帧中显示结果。用户可以按'q'或Esc键来退出视频追踪。

a945ea779bd39747990c5f5971dc98d3.png

57d27656f735840b8ac096527eb6193b.png

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

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

相关文章

Jenkins 持续集成 【CICD】

持续集成 &#xff08;Continuous integration&#xff0c;简称CI&#xff09; 持续集成是一种开发实践&#xff0c;它倡导团队成员频繁的集成他们的工作&#xff0c;每次集成都通过自动化构建&#xff08;包括编译、构建、打包、部署、自动化测试&#xff09;来验证&#xff…

Django之REST Client插件

一、接口测试工具介绍 在开发前后端分离项目时,无论是开发后端,还是前端,基本都是需要测试API接口的内容,而目前我们需要开发遵循RESTFul规范的项目,也是必然的(自己不开发前端页面)。 在网上有很多这样的工具,常用的postman,但还是需要下载安装。在这我们介绍一个VSCod…

Spark-Scala语言实战(12)

在之前的文章中&#xff0c;我们学习了如何在spark中使用键值对中的join,rightOuterJoin,leftOuterJoin三种方法。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&#xff0c;请留下你宝贵的点赞&#xff0c;谢谢…

练习 21 Web [GXYCTF2019]BabySQli

SQL联合查询&#xff0c;注意有源码看源码&#xff0c;Base64以及32的区别&#xff0c;MD5碰撞 打开后有登录框&#xff0c;先随意登录尝试 只有输入admin才是返回wrong pass&#xff01; 其他返回wrong user 所以用户名字段一定要输入admin 养成好习惯&#xff0c;先查看源码…

Unity:2D SpriteShape

1.1 简介 Sprite Shape 可以很灵活的更改sprite的轮廓。比如&#xff1a; 它由两部分组成&#xff1a;Sprite Shape Profile、Sprite Shape Controller&#xff0c;需要导入2D Sprite Shape Package. 1.1.1 Sprite导入要求 Texture Type - ‘Sprite (2D and UI)’.Sprite Mo…

替代 Redis 和 Memcached:25 倍吞吐量! | 开源日报 No.213

dragonflydb/dragonfly Stars: 22.4k License: NOASSERTION Dragonfly 是一个内存数据存储&#xff0c;适用于现代应用工作负载&#xff0c;可替代 Redis 和 Memcached。与传统的内存数据存储相比&#xff0c;Dragonfly 提供了 25 倍的吞吐量、更高的缓存命中率和更低尾部延…

ChatGPT/GPT4科研应用与绘图技术及论文写作

2023年随着OpenAI开发者大会的召开&#xff0c;最重磅更新当属GPTs&#xff0c;多模态API&#xff0c;未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义&#xff0c;不亚于互联网和个人电脑的问世。360创始人周鸿祎认为未来各行各业如果不能搭上这班车…

我与C++的爱恋:类与对象(一)

​ ​ &#x1f525;个人主页&#xff1a;guoguoqiang. &#x1f525;专栏&#xff1a;我与C的爱恋 ​C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。 C是基于面向对象的&#xff0c;关注的是对象&…

【贪玩巴斯】Mac的M芯片(M1/2...)下载homebrew方法(24年最新且已验证可行)

1. 按照目前广为流传的方法&#xff08;M1会出现一些问题&#xff09;&#xff1a; 终端输入&#xff1a; /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" 使用国内镜像下载。 2. 输入后按照要求步骤执行即可&#xff…

使用c语言libexpat开源库解析XML数据

1 libexpat简介 Expat 是一个用 C 语言编写的开源 XML 解析库&#xff0c;以其高性能和小巧的体积著称。Expat 兼容多种操作系统平台&#xff0c;包括但不限于 Windows、Linux、macOS 等。由于其跨平台特性和简单易用的API&#xff0c;Expat 成为了许多C/C程序员解析XML文档的…

原型模式详解

原型模式简单的理解来说,就是复制品,用一个已经做好的成品作为原型,然后通过复制它得到新的产品。就好像细胞分裂一样。用Java来说,就是用对象创建对象,而不是通过类来创建对象。 原型模式的目的是从原型实例克隆出新的实例 ,对于那些有非常复杂的初始化过程的对象或者是…

第三方短信-短信合作-106短信

第三方短信-短信合作-106短信 1、你是否也有需要发送短信的业务、但是自己没有短信服务的情况 2、是否需要大量发送短信、但是又不想通过自己的真实手机号发 3、您是否是开发者、但是没有自己的短信服务&#xff0c;需要发送短信可以使用/借用我的短信服务进行发送&#xff0c…

Docker 哲学 - docker swarm

Docker Swarm 模式下的集群管理和服务恢复机制 Docker Swarm 是 Docker 的集群管理和编排功能。在 Swarm 模式下&#xff0c;你可以将多个 Docker 主机组合成一个虚拟主机&#xff0c;称为 Swarm 集群。Swarm 集群由一个或多个管理节点&#xff08;manager nodes&#xff09;和…

Flutter-发布插件到pub上传不上问题

问题1&#xff1a; 尝试指令&#xff1a; flutter packages pub publish --serverhttps://pub.dartlang.org问题2&#xff1a; 问题1解决后&#xff0c;进入验证身份&#xff0c;点击终端显示的链接&#xff0c;跳转到google验证&#xff0c;记得这里要科*学上网&#xff0c;点…

理解pytorch的广播语义

目录 什么是广播运算 广播的条件 示例 示例1 示例2 示例3 补1 示例4 原位运算 示例5 参与广播运算的两个tensor&#xff0c;必须是从右向左对齐 总结规律 两个tensor可以做广播运算的条件&#xff1a; 两个可以互相广播的tensor运算的步骤&#xff1a; 例子&#x…

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

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

接口的总结与面试题

接口本身不能创建对象&#xff0c;只能创建接口的实现类对象&#xff0c;接口类型的变量可以与实现类对象构成多态引用。 声明接口用interface&#xff0c;接口的成员声明有限制&#xff1a; &#xff08;1&#xff09;公共的静态常量 &#xff08;2&#xff09;公共的抽象方…

车载电子电器架构 —— 车辆数据配置开发

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

基于k8s的高性能综合web服务器搭建

目录 基于k8s的高性能综合web服务器搭建 项目描述&#xff1a; 项目规划图&#xff1a; 项目环境&#xff1a; k8s&#xff0c; docker centos7.9 nginx prometheus grafana flask ansible Jenkins等 1.规划设计整个集群的架构&#xff0c;k8s单master的集群环境&…

matlab的歧视:simulink不能使用stm32f4系列的ADC?

2023b的matlab&#xff0c;stm32f407芯片&#xff0c;运行内容Using the Analog to Digital Converter Block to Support STMicroelectronics STM32 Processor Based Boards Using the Analog to Digital Converter Block to Support STMicroelectronics STM32 Processor Base…