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

news2024/11/18 4:34:17

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

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

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

相关文章

Redis -- 缓存击穿问题

缓存击穿问题也叫热点Key问题&#xff0c;就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了&#xff0c;无数的请求访问会在瞬间给数据库带来巨大的冲击。 常见的解决方案有两种&#xff1a; 互斥锁 逻辑过期 逻辑分析&#xff1a;假设线程1在查询缓存之后&…

Java实现一个简易的布隆过滤器Bloom Filter

目录 什么是布隆过滤器&#xff1f; 作用&#xff1a; 实现一个简单的布隆过滤器&#xff1a; 解析&#xff1a; 什么是布隆过滤器&#xff1f; 布隆过滤器&#xff08;Bloom Filter&#xff09;是一种用于快速检查一个元素是否可能存在于一个集合中的数据结构&#xff0c;它…

【移动安全】对webview漏洞的一些分析

这次分析的app如下&#xff1a; 打开发现该app发现需要登录界面&#xff1a; 拖进jadx看一下&#xff0c;先来看一下AndroidManifest.xml文件 发现有两个类是导出&#xff0c;再来分析这两个类 这个RegistrationWebView类利用webview.loadUrl进行加载网页 java public class…

代码随想录第三十一天 | 贪心算法P1 | ● 理论基础 ● 455. ● 376. ● 53.

理论基础 题目分类 一般解题步骤 贪心算法一般分为如下四步&#xff1a; 将问题分解为若干个子问题找出适合的贪心策略求解每一个子问题的最优解将局部最优解堆叠成全局最优解 这个四步其实过于理论化了&#xff0c;我们平时在做贪心类的题目 很难去按照这四步去思考&…

Ps:合并到 HDR Pro

Ps菜单&#xff1a;文件/自动/合并到 HDR Pro Automate/Merge to HDR Pro 合并到 HDR Pro Merge to HDR Pro命令可以将同一场景的具有不同曝光度的多个图像合并起来&#xff0c;从而捕获单个 HDR 图像中的全部动态范围。 合并到 HDR Pro 命令分两步进行。 首先&#xff0c;需要…

什么是NLP?

&#x1f916;NLP是什么&#xff1f;&#x1f916; NLP&#xff08;Natural Language Processing&#xff09;&#xff0c;全称自然语言处理&#xff0c;是人工智能不可或缺的一环&#xff0c;它搭建了人与计算机之间沟通的桥梁&#x1f309;。 &#x1f6e0;️NLP强大功能一…

Day:003 | Python爬虫:高效数据抓取的编程技术(爬虫基础)

urllib发送get请求 在目前网络获取数据的方式有多种方式&#xff1a;GET方式大部分被传输到浏览器的html&#xff0c;images, js,css, … 都是通过GET 方法发出请求的。它是获取数据的主要方法 例如&#xff1a;www.baidu.com 搜索 Get请求的参数都是在Url中体现的,如果有中…

客户不报预算咋办?

谈崩了10个单子&#xff0c;我才领悟到谈判的精髓。创业一年了&#xff0c;去年累计服务客户30。说起来是市场好也罢&#xff0c;凑巧也罢反正没怎么费劲就谈下了不少客户&#xff0c;也做到了月入5位数。 今年一开年因为有老客户撑着&#xff0c;我也没太认真拓展新客户&#…

Mysql数据库getshell方法

今天摸鱼时候&#xff0c;突然有人问我不同的数据库getshell的方式&#xff0c;一时间我想到了mysql还有redis未授权访问到getshell的方式&#xff0c;但是仅仅第一时间只想到了这两种&#xff0c;我有查了查资料&#xff0c;找到了上面两种数据库getshell的补充&#xff0c;以…

Android源码笔记-输入事件(二)

这一节主要了解输入事件的获取&#xff0c;InputReaderThread继承自C的Thread类&#xff0c;Thread类封装了pthread线程工具&#xff0c;提供了与Java层Thread类相似的API。C的Thread类提供了一个名为threadLoop()的纯虚函数&#xff0c;当线程开始运行后&#xff0c;将会在内建…

【Linux】软硬链接 / 动静态库

目录 一. 软硬链接1. 硬链接2. 软链接3. unlink4. 目录的硬链接 二. 动静态库1.1 静态库制作1.2 静态库使用2.1 动态库制作2.2 动态库使用3. 动态链接原理 一. 软硬链接 1. 硬链接 硬链接(hard link) 可以将它理解为原始文件的别名, 和原始文件使用相同的 inode 编号和 data …

GraphSage

背景 大型图中节点的低维嵌入在各种预测任务中非常有用。GraphSage是一种通用的归纳框架&#xff0c;它利用节点特征信息&#xff08;例如&#xff0c;文本属性&#xff09;有效地为以前看不见的数据生成节点嵌入。相比于对每个节点训练单独的嵌入&#xff0c;GraphSage学习了一…

深入浅出 -- 系统架构之单体到分布式架构的演变

一、传统模式的技术改革 在很多年以前&#xff0c;其实没有严格意义上的前后端工程师之分&#xff0c;每个后端就是前端&#xff0c;同理&#xff0c;前端也可以是后端&#xff0c;即Ajax、jQuery技术未盛行前的年代。 起初&#xff0c;大部分前端界面很简单&#xff0c;显示的…

thinkphp6入门(21)-- 如何删除图片、文件

假设文件的位置在 /*** 删除文件* $file_name avatar/20240208/d71d108bc1086b498df5191f9f925db3.jpg*/ function deleteFile($file_name) {// 要删除的文件路径$file app()->getRootPath() . public/uploads/ . $file_name; $result [];if (is_file($file)) {if (unlin…

【语音识别】声学建模中基于树的状态绑定

01 基本想法 单音素HMM模型不能很好的应对自然说话人发音时的渐变过程&#xff0c;比如从一个音素转换到另一个音素时会存在协同发音现象。因此语音识别的先驱者提出了上下文建模概念&#xff0c;即使用中心音素&#xff08;单因素&#xff09;和前后两个音素组成三音素对每一…

【Laravel】09 用模型批量赋值简化代码 数据库关系

【Laravel】09 用模型批量赋值简化代码 & 数据库关系 1. 用模型批量赋值简化代码2. 数据库关系 1. 用模型批量赋值简化代码 原来存储一个值 2. 数据库关系 这里可以看到两个SQL是一样的

函数重载和引用【C++】

文章目录 函数重载什么是函数重载&#xff1f;函数重载的作用使用函数重载的注意点为什么C可以函数重载&#xff0c;C语言不行&#xff1f; 引用什么是引用&#xff1f;引用的语法引用的特点引用的使用场景引用的底层实现传参时传引用和传值的效率引用和指针的区别 函数重载 什…

QT Creator概览

&#x1f40c;博主主页&#xff1a;&#x1f40c;​倔强的大蜗牛&#x1f40c;​ &#x1f4da;专栏分类&#xff1a;QT❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、Qt Creator 概览 ①&#xff1a;菜单栏 ②&#xff1a;模式选择 ③&#xff1a;构建套件选择器…

Vue2电商前台项目(二):完成Home首页模块业务

一、项目开发的步骤 1、书写静态页面&#xff08;HTML&#xff0c;CSS&#xff09; 2、拆分组件 3、获取服务器的数据动态展示 4、完成相应的动态业务逻辑 经过分析之后&#xff0c;Home首页可以拆分为7个组件&#xff1a;TypeNav三级联动导航&#xff0c;ListContainer&…

深入解析:如何使用Xcode上传苹果IPA安装包至App Store?

目录 引言 摘要 第二步&#xff1a;打开appuploader工具 第二步&#xff1a;打开appuploader工具&#xff0c;第二步&#xff1a;打开appuploader工具 第五步&#xff1a;交付应用程序&#xff0c;在iTunes Connect中查看应用程序 总结 引言 在将应用程序上架到苹果应用商…