【opencv】dnn示例-vit_tracker.cpp 使用OpenCV库和ViTTrack模型实现的视频追踪程序

65e0bcc15f7c222f50af0787fdd9b984.png

这段代码是一个使用OpenCV库和ViTTrack模型实现的视频追踪程序。程序通过摄像头或视频文件获取图像序列,并对选定的目标对象进行实时追踪。

代码主要分为以下几个部分:

导入必要的库:程序开始时先导入了iostream,cmath以及相关OpenCV的库。

参数解析:通过定义一个参数字典keys来解析命令行输入的参数,这些参数包括输入的视频源、模型的路径以及计算后端等。

追踪器的创建与设置:使用给定的模型文件以及命令行参数中的后端和目标设备选项,创建一个ViT追踪器对象。

视频捕获:程序尝试打开摄像头或读取视频文件。如果指定了摄像头或视频文件但不能成功打开,程序将输出错误信息。

目标对象的选择:获取视频的第一帧,并让用户选择一个区域作为追踪的初始目标。

追踪循环:程序进入一个循环,不断从视频源获取新的帧,并使用追踪器更新目标位置。每一次追踪完成后,都会输出框架的计数、预测分数、目标位置方框以及每帧追踪耗时。

追踪结果展示:将追踪的结果(目标位置的矩形框及其分数)覆盖在原图像上,并在窗口中展示出来。

退出处理:程序会在按下ESC键后退出追踪循环,并关闭程序。

整体而言,代码实现了一个基于ViT追踪模型的视频目标追踪系统,包含了从视频源获取图像、初始化追踪目标、连续追踪目标以及展示追踪结果等功能。程序使用OpenCV的DNN模块加载ONNX格式的深度学习模型,并通过选择合适的后端(例如CUDA)和目标设备来加速计算过程。

// VitTracker
// model: https://github.com/opencv/opencv_zoo/tree/main/models/object_tracking_vittrack


#include <iostream> // 引入输入输出流库
#include <cmath> // 引入数学运算库


#include <opencv2/dnn.hpp> // 引入OpenCV深度神经网络模块
#include <opencv2/imgproc.hpp> // 引入OpenCV图像处理模块
#include <opencv2/highgui.hpp> // 引入OpenCV高级用户界面模块
#include <opencv2/video.hpp> // 引入OpenCV视频处理模块


using namespace cv; // 使用cv命名空间简化代码
using namespace cv::dnn; // 使用cv::dnn命名空间简化代码


const char *keys = // 定义命令行参数
        "{ help     h  |   | Print help message }" // 打印帮助信息
        "{ input    i  |   | Full path to input video folder, the specific camera index. (empty for camera 0) }" // 输入视频路径或摄像头索引(默认为0)
        "{ net    | object_tracking_vittrack_2023sep.onnx | Path to onnx model of vitTracker.onnx}" // vitTracker.onnx模型的路径
        "{ backend     | 5 | Choose one of computation backends: " // 选择计算后端
                            "0: automatically (by default), " // 自动选择
                            "1: Halide language (http://halide-lang.org/), " // Halide语言
                            "2: Intel's Deep Learning Inference Engine (https://software.intel.com/openvino-toolkit), " // 英特尔深度学习推理引擎
                            "3: OpenCV implementation, " // OpenCV实现
                            "4: VKCOM, " // VKCOM
                            "5: CUDA }," // CUDA
        "{ target      | 6 | Choose one of target computation devices: " // 选择目标计算设备
                            "0: CPU target (by default), " // CPU
                            "1: OpenCL, " // OpenCL
                            "2: OpenCL fp16 (half-float precision), " // OpenCL fp16 (半精度浮点)
                            "3: VPU, " // VPU
                            "4: Vulkan, " // Vulkan
                            "6: CUDA, " // CUDA
                            "7: CUDA fp16 (half-float preprocess) }" // CUDA fp16 (半精度预处理)
;


static
int run(int argc, char** argv) // 定义主要运行函数
{
    // Parse command line arguments.
    CommandLineParser parser(argc, argv, keys); // 命令行参数解析


    if (parser.has("help")) // 如果存在帮助参数
    {
        parser.printMessage(); // 打印帮助信息
        return 0;
    }


    std::string inputName = parser.get<String>("input"); // 获取输入源
    std::string net = parser.get<String>("net"); // 获取模型路径
    int backend = parser.get<int>("backend"); // 获取后端参数
    int target = parser.get<int>("target"); // 获取目标计算设备参数


    Ptr<TrackerVit> tracker; // 声明一个ViT跟踪器的智能指针
    try // 尝试加载跟踪器和模型
    {
        TrackerVit::Params params; // 创建跟踪器参数结构
        params.net = samples::findFile(net); // 找到或保持模型文件路径
        params.backend = backend; // 设置后端参数
        params.target = target; // 设置目标计算设备参数
        tracker = TrackerVit::create(params); // 创建跟踪器实例
    }
    catch (const cv::Exception& ee) // 如果捕获到异常
    {
        std::cerr << "Exception: " << ee.what() << std::endl; // 打印异常信息
        std::cout << "Can't load the network by using the following files:" << std::endl; // 说明无法加载网络
        std::cout << "net : " << net << std::endl; // 打印网络路径
        return 2;
    }


    const std::string winName = "vitTracker"; // 窗口名称
    namedWindow(winName, WINDOW_AUTOSIZE); // 创建具有自动大小的窗口


    // Open a video file or an image file or a camera stream.
    VideoCapture cap; // 创建视频捕获对象


    if (inputName.empty() || (isdigit(inputName[0]) && inputName.size() == 1)) // 如果输入为空或仅有单个数字(表示摄像头索引)
    {
        int c = inputName.empty() ? 0 : inputName[0] - '0'; // 默认为0或转换数字为摄像头索引
        std::cout << "Trying to open camera #" << c << " ..." << std::endl;
        if (!cap.open(c)) // 尝试打开摄像头
        {
            std::cout << "Capture from camera #" << c << " didn't work. Specify -i=<video> parameter to read from video file" << std::endl; // 打开失败提示
            return 2;
        }
    }
    else if (inputName.size()) // 如果输入非空
    {
        inputName = samples::findFileOrKeep(inputName); // 查找或保持文件路径
        if (!cap.open(inputName)) // 尝试打开视频文件
        {
            std::cout << "Could not open: " << inputName << std::endl; // 打开失败提示
            return 2;
        }
    }


    // Read the first image.
    Mat image; // 创建一个Mat对象用于存放图像
    cap >> image; // 捕获一帧图像
    if (image.empty()) // 如果图像为空
    {
        std::cerr << "Can't capture frame!" << std::endl; // 抓取图像失败提示
        return 2;
    }


    Mat image_select = image.clone(); // 克隆捕获的图像以便用户选择跟踪区域
    putText(image_select, "Select initial bounding box you want to track.", Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0)); // 在图像上添加文字指导用户选择跟踪区域
    putText(image_select, "And Press the ENTER key.", Point(0, 35), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0)); // 提示用户按下回车键确认选择


    Rect selectRect = selectROI(winName, image_select); // 让用户选择一个区域并返回矩形坐标
    std::cout << "ROI=" << selectRect << std::endl; // 输出用户选择的区域


    tracker->init(image, selectRect); // 初始化跟踪器并使用用户选择的区域


    TickMeter tickMeter; // 创建一个时钟计时器对象


    for (int count = 0; ; ++count) // 循环处理视频帧
    {
        cap >> image; // 捕获一帧图像
        if (image.empty()) // 如果图像为空
        {
            std::cerr << "Can't capture frame " << count << ". End of video stream?" << std::endl; // 抓取图像失败提示
            break;
        }


        Rect rect; // 创建一个矩形对象


        tickMeter.start(); // 开始计时
        bool ok = tracker->update(image, rect); // 更新跟踪器状态并返回跟踪框的位置
        tickMeter.stop(); // 停止计时


        float score = tracker->getTrackingScore(); // 获取跟踪评分


        std::cout << "frame " << count << // 输出当前帧数
            ": predicted score=" << score << // 输出预测评分
            "  rect=" << rect << // 输出跟踪框位置
            "  time=" << tickMeter.getTimeMilli() << "ms" << // 输出计时时间
            std::endl;


        Mat render_image = image.clone(); // 克隆当前帧以便绘制跟踪结果


        if (ok) // 如果跟踪成功
        {
            rectangle(render_image, rect, Scalar(0, 255, 0), 2); // 在渲染图像上绘制跟踪框


            std::string timeLabel = format("Inference time: %.2f ms", tickMeter.getTimeMilli()); // 格式化输出计时标签
            std::string scoreLabel = format("Score: %f", score); // 格式化输出评分标签
            putText(render_image, timeLabel, Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0)); // 将计时标签绘制在图像上
            putText(render_image, scoreLabel, Point(0, 35), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0)); // 将评分标签绘制在图像上
        }


        imshow(winName, render_image); // 显示渲染后图像


        tickMeter.reset(); // 重置计时器


        int c = waitKey(1); // 等待按键
        if (c == 27 /*ESC*/) // 如果按下ESC键
            break; // 退出循环
    }


    std::cout << "Exit" << std::endl; // 输出退出提示
    return 0; // 返回成功
}


int main(int argc, char **argv) // 主程序入口函数
{
    try // 尝试运行主功能函数
    {
        return run(argc, argv); // 调用run函数并返回结果
    }
    catch (const std::exception& e) // 捕获任何抛出的异常
    {
        std::cerr << "FATAL: C++ exception: " << e.what() << std::endl; // 输出异常信息
        return 1; // 返回失败
    }
}

该代码是使用OpenCV库实现的一个简单的视频跟踪应用程序。它主要通过解析命令行输入不同的参数来调整视频输入源、选择神经网络模型、计算后端以及目标计算设备。代码首先尝试加载一个基于ViT(Vision Transformer)的目标跟踪器模型。接下来,它通过用户选择的图像区域初始化跟踪器并开始对视频流中的目标进行跟踪。每个循环中,都会更新跟踪器并计算其评分以及跟踪目标的位置,然后将跟踪结果绘制在每帧上并实时显示给用户。如果用户按下ESC键,则会退出循环结束程序。

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

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

相关文章

Hive进阶(4)----MapReduce的计算过程(赋图助君理解)

MapReduce的计算过程 MapReduce是一种编程模型和处理大规模数据集的方法。它通常用于分布式计算环境中&#xff0c;能够将数据处理任务分解成独立的部分&#xff0c;分配给多台计算机进行并行处理。这个模型由Google提出&#xff0c;并在开源领域中得到了广泛的应用和实现。Map…

CSS显示模式

目录 CSS显示模式简介 CSS显示模式的分类 块元素 行元素 行内块元素 元素显示模式的转换 使块内文字垂直居中的方法 设计简单小米侧边栏&#xff08;实践&#xff09; CSS显示模式简介 元素显示模式就是元素&#xff08;标签&#xff09;以什么方式进行显示&#xff0…

前端三剑客 HTML+CSS+JavaScript ② HTML相关概念

他们这样形容我 是暴雨浇不灭的火 —— 24.4.18 学习目标 理解 HTML的概念 HTML的分类 HTML的关系 HTML的语义化 应用 HTML骨架格式 sublime基本使用 一、HTML初识 HTML指的是超文本标记语言&#xff0c;是用来描述网页的一种语言 超文本&#xff1a;暂且理解为“超级的文本”&…

BNB链融合

BNB Chain融合 BNB Chain目前有BNB智能链&#xff08;BSC&#xff09;&#xff0c;BNB信标链 BNB信标链&#xff1a;用作质押和投票的治理层&#xff0c;采用BEP-2代币标准BNB智能链(BSC)&#xff1a;用作EVM兼容层&#xff0c;提供DApp、DeFi服务、共识层、多链支持和其他Web3…

【AI工具之Prezo如何自动生成PPT操作步骤】

先说优缺点&#xff1a; 最大的优点就是免费&#xff08;但说实话功能和体验方面很弱&#xff09;支持中文提问&#xff08;最好用英文&#xff09;&#xff0c;智能生成图文&#xff08;但是只能生成英文内容&#xff09;可以AI生成图片&#xff0c;图片很精美酷炫&#xff0…

Hive进阶(2)----HDFS写入数据流程(赋图助君理解)

HDFS写入数据流程 一、写入流程 1、 Client向NameNode发起RPC请求&#xff0c;来确定请求文件block所在的位置&#xff1b; 2、 NameNode会视情况返回文件的部分或者全部block列表&#xff0c;对于每个block&#xff0c;NameNode都会返回含有该block副本的DataNode地址&…

三、fpga对完成过滤和校验的有效包数据进行有效像素提取、MATLAB对数据源进行处理与下发(完整实现pc机→显示器通信链路)

前言:上篇文章实现了MATLAB模拟发送UDP以太网协议数据包到fpga,能实现双沿数据→单沿数据转换,并将转换后的数据进行包过滤和crc校验,本篇内容要实现真正的从pc机下发视频数据,经过千兆以太网传输存储到fpga 的ddr3中,然后通过hdmi读出到显示屏上。 文章目录 一、模块设…

Tensorflow小技巧01:检测本地Tensorflow的版本

前言&#xff1a; 以Pycharm为例&#xff0c;Windwos10系统&#xff0c;检测本地环境的Tensorflow的版本&#xff1a; 1 打开Pycharm窗口 2 在窗口中输入&#xff1a; pythonPython 3.9.5 (tags/v3.9.5:0a7dcbd, May 3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win…

面试经典算法系列之二叉树17 -- 验证二叉树

面试经典算法32 - 验证二叉树 LeetCode.98 公众号&#xff1a;阿Q技术站 问题描述 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当…

视频教程下载:用ChatGPT快速提升股票投资能力

学完此视频后可以获得&#xff1a; 学习如何使用人工智能/Chatgpt进行基础/快速/高级财务与研究分析 学习如何使用人工智能/Chatgpt对任何公司进行定性投资研究 学习如何使用人工智能/Chatgpt对任何公司进行定量投资研究 学习如何使用人工智能/Chatgpt创建、预测和分析财务…

考研日常记录

由于实在太无聊了 &#xff0c; 所以记录以下考研备考日常 &#xff0c; 增加一点成就感 &#xff0c; 获得一点前进动力。 2024.4.18 周四 课程情况&#xff1a; 无课 时间规划&#xff1a; 上午&#xff1a;休息 下午&#xff1a; 事项耗时进度备注写作业1h复习英语单词…

低噪声放大器是如何实现低噪声放大的功能的

灵敏度作为接收机最重要的指标之一,直接决定了接收机能分辨的最小信号。接收机的灵敏度计算公式如下所示。 Psensitivity=-174dBm+NF+10*lg(BW)+SNR 由接收机灵敏度的计算公式可知,影响接收机灵敏度的指标有噪声系数、带宽和信噪比,因此一旦带宽和信噪比确定了,那么能决…

隧道网络对讲广播音频终端-智慧工地网络报警求助箱

隧道网络对讲广播音频终端-智慧工地网络报警求助箱 SV-6007 网络对讲求助终端 一、描述 SV-6007是我司的一款壁挂式双按键求助对讲终端&#xff0c;具有10/100M以太网接口&#xff0c;其接收网络的音频数据&#xff0c;实时解码播放&#xff0c;还配置了麦克风输入和扬声器输…

[Qt网络编程]之UDP通讯的简单编程实现

hello&#xff01;欢迎大家来到我的Qt学习系列之网络编程之UDP通讯的简单编程实现。希望这篇文章能对你有所帮助&#xff01;&#xff01;&#xff01; 本篇文章的相关知识请看我的上篇文章: http://t.csdnimg.cn/UKyeM 目录 UDP通讯 基于主窗口的实现 基于线程的实现 UDP通讯…

【opencv】dnn示例-segmentation.cpp 通过深度学习模型对图像进行实时语义分割

模型下载地址&#xff1a; http://dl.caffe.berkeleyvision.org/ 配置文件下载&#xff1a; https://github.com/opencv/opencv_extra/tree/4.x/testdata/dnn 该段代码是一个利用深度学习进行语义分割的OpenCV应用实例。下面将详细解释代码的功能和方法。 引入库 引入了一些必要…

统一SQL-支持cast函数

统一SQL介绍 https://www.light-pg.com/docs/LTSQL/current/index.html 源和目标 源数据库&#xff1a;Oracle 目标数据库&#xff1a;Postgresql&#xff0c;TDSQL-MySQL&#xff0c;达梦8&#xff0c;LightDB-Oracle 操作目标 在Oracle中&#xff0c;cast函数允许将一种…

代码随想录-链表 | 142环形链表

代码随想录-链表 | 142环形链表 LeetCode 142-环形链表解题思路代码复杂度难点总结 LeetCode 142-环形链表 题目链接 题目描述 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#x…

死磕GMSSL通信-C/C++系列(一)

死磕GMSSL通信-C/C++系列(一) 最近再做国密通信的项目开发,以为国密也就简单的集成一个库就可以完事了,没想到能有这么多坑。遂写下文章,避免重复踩坑。以下国密通信的坑有以下场景 1、使用GMSSL guanzhi/GmSSL进行通信 2、使用加密套件SM2-WITH-SMS4-SM3 使用心得 ​…

Java学习-详述main方法、可变参数、数组的工具类、二维数组

详述main方法 【1】main方法&#xff1a;程序的入口&#xff0c;在同一个类中&#xff0c;如果有多个方法&#xff0c;那么虚拟机就会识别main方法&#xff0c;从这个方法作为程序的入口 【2】main方法格式严格要求&#xff1a; public static void main(String[] args){} p…

【NOI-题解】1320. 时钟旋转1323. 扩建花圃问题1462. 小明的游泳时间1565. 成绩(score)1345. 玫瑰花圃

文章目录 一、前言二、问题问题&#xff1a;1320. 时钟旋转问题&#xff1a;1323. 扩建花圃问题问题&#xff1a;1462. 小明的游泳时间问题&#xff1a;1565. 成绩&#xff08;score&#xff09;问题&#xff1a;1345. 玫瑰花圃 三、感谢 一、前言 本章节主要对基本运算中整数…