【目标跟踪】多相机环视跟踪

文章目录

  • 一、前言
  • 二、流程图
  • 三、实现原理
    • 3.1、初始化
    • 3.2、输入
    • 3.3、初始航迹
    • 3.4、航迹预测
    • 3.5、航迹匹配
    • 3.6、输出结果
  • 四、c++ 代码
  • 五、总结

一、前言

  1. 相机目标跟踪主要是为了实现 360 度跟踪。单相机检测存在左右后的盲区视野。
  2. 在智能驾驶领域,要想靠相机实现无人驾驶,相机必须 360 度无死角全覆盖。
  3. 博主提供一种非深度学习方法,采用kalman滤波+匈牙利匹配方式实现环视跟踪。有兴趣可以参考往期【目标跟踪】系列博客。
  4. 本文干货满满,可以先点赞关注收藏,以免下次找不到。欢迎各位吴彦祖私信交流学习。

二、流程图

干货怎么会少了流程图,上图!上图!上图!。流程图用 processon 制作的,不是付费软件买不起,而是免费的更有性价比。

在这里插入图片描述

这里最重要的就是航迹管理,对于四路相机(front, left, right, back) 检测的目标都需要管理。这里面不仅要对单相机目标进行跟踪,且对跨相机的目标也需要进行跟踪,还有各种匹配,初始化,开始消亡等到。想想都头皮发麻,那到底怎么做?别慌,让我娓娓道来。

街上熙熙攘攘的人群交头接耳,果然雨过天晴就会有聊不完的话题。三只白鹭停泊在河边享受着阳光的沐浴,不时煽动自己羽毛,引起阵阵涟漪,如此惬意无不让打工人憧憬。远处的山峰层峦叠嶂,仿佛去到世界尽头。命运的齿轮正在转动,会当凌绝顶,一览纵山下。

wc !!!思绪差点飘离银河系,还是敲键盘要紧。下面看看实现原理。

三、实现原理

3.1、初始化

保存四路相机参数:4路相机内参与外参。

制定表格 1920 * 1080 ,用于后续判断计算校正后的像素点。对整张图片进行校正会占用大量 CPU,我们采用对原图进行计算。

在这里插入图片描述

3.2、输入

nuscenes 是六路相机。我们这里是四路相机,全部都是 190° 鱼眼相机。

输入四路相机检测结果。当前相机当前帧的所有目标信息

  • 二维 box 检测框 (x,y,w,h)
  • 目标列表 label。如person、car等
  • 目标的置信度 score

演示这里采取的是 2D 检测。如果是 3D 检测也是类似计算,且 3D 检测定位更加精准。


3.3、初始航迹

(1) 划分 4 象限

在这里插入图片描述

(2) 划分 8 区域

前相机第4象限、前相机第1象限、右相机第3象限、右相机第4象限、后相机第2象限、后相机第3象限、左相机第1象限、左相机第2象限。

在这里插入图片描述

(3) 划分 2 类

前相机第4象限、右相机第3象限、后相机第2象限、左相机第1象限 为一类 firstBox。

右相机第4象限、后相机第3象限、左相机第2象限、前相机第1象限 为一类 secondBox。

(4) 分配 id

当目标是属于 firstBox 一类的目标时,此时直接分配 id 。分配一个 id ,则 idCount ++。

(5) 匹配

sencondBox 中的目标需要与 firstBox 目标匹配。计算距离与角度。

如果匹配上时,id = firstBox 目标 id

如果未匹配上时,id = idCount , idCount ++

3.4、航迹预测

这部分比较简单, 正常预测就行。

对每个目标的box进行预测; 对每个目标的状态,距离、速度、加速度进行预测; 得到预测后的目标状态、box、相应传感器(枚举)。

3.5、航迹匹配

(1) 预测框与检测框

预测框是上一帧所获得的预测框;检测框是当前检测信息的检测框。同时对目标有预测的距离与测量距离

(2) 匈牙利匹配矩阵

如果属于不同相机检测的目标,则设为默认最大值;如果属于同一相机检测目标,计算iou。这个是与单相机跟踪类似。

(3) 匹配修正

匹配上的目标,修正预测的状态与box。此时idCount 不变。

(4) 未匹配的检测框

对于未匹配的检测框,寻找航迹中在其他相机的目标,进行再次匹配。如果匹配上,则未匹配检测框id = 其他相机目标id。否则赋予id = idCount,idCount++。

3.6、输出结果

输出俯视角下所有目标的位置(x, y)。

四、c++ 代码

这部分代码比较多,展示划分象限初始航迹代码。其他代码放到资源自行下载。

// 1、管理航迹信息
void Tracking::ManageTrack(std::vector<TrackingBox> detectData) 
{
    std::vector<StateBox> firstBox;                 // 目标所处相机与第几象限 front 4, right 3, back 2, left 1 
    std::vector<StateBox> secondBox;                // 目标所处相机与第几象限 right 4, back 3, left 2, front 1 
    // 1.1 分配id
    for (unsigned int i = 0; i < detectData.size(); i++) {
        StateBox stateBox;
        stateBox.sensor = detectData[i].sensor;                                       // 相机传感器的方位
        stateBox.label = detectData[i].label;                                         // 目标标签
        stateBox.score = detectData[i].score;                                         // 目标置信度
        stateBox.box = detectData[i].box;                                             // 检测框
        std::vector<float> p = detectData[i].position;                                // 根据图像像素获取世界位置 x,y相对于车体
        stateBox.position = p;
        stateBox.state = {(cv::Mat_<float>(6, 1) << p[0], 0, 0, p[1], 0, 0), pInit};  // 初始化distanceKalman的状态与协方差
        if ((stateBox.sensor == 0 && p[1] < 0) || (stateBox.sensor == 1 && p[0] < 0) || 
                (stateBox.sensor == 2 && p[1] > 0) || (stateBox.sensor == 3 && p[0] > 0) ) {
            stateBox.kBox = KalmanTracker(detectData[i].box);                         // KalmanTracker所需的box
            stateBox.id = countId;
            countId++;
            firstBox.push_back(stateBox);
        }
        else {
            secondBox.push_back(stateBox);
        }
    }
    for (auto box:firstBox) {
        trackers.push_back(box);
    }
    // 1.2 匹配id
    unsigned int firstNum = firstBox.size();                             // 前相机在右侧个数
	unsigned int secondNum = secondBox.size();                           // 右相机在前侧个数
    std::vector<std::vector<double>> matrix;                             // 关联矩阵->匈牙利匹配
    matrix.resize(firstNum, std::vector<double>(secondNum, 1));          // resize关联矩阵大小
    std::vector<cv::Point> matchedPairs;  
    if (firstNum != 0 && secondNum != 0) {
        for (unsigned int i = 0; i < firstNum; i++) {
            for (unsigned int j = 0; j < secondNum; j++) {
                matrix[i][j] = GetWeight(firstBox[i].position, secondBox[j].position); // 计算角度权重
            }
        }
        HungarianAlgorithm hungAlgo;
        std::vector<int> assignment; 
        hungAlgo.Solve(matrix, assignment);     // 匈牙利匹配计算
        std::set<int> unMatchedSecondBox;       // 存放未匹配的sencond 类型的框
        for (unsigned int i = 0; i < firstNum; ++i) {
            if (assignment[i] == -1) { 
                continue;                       // 过滤掉无效的值
            }
            matchedPairs.push_back(cv::Point(i, assignment[i]));
        }
    }
    // 1.3 修正id
    int firstId, secondId;
    for (unsigned int i = 0; i < matchedPairs.size(); i++) {
        firstId = matchedPairs[i].x; 
        secondId = matchedPairs[i].y; 
        if (matrix[firstId][secondId] < hungarianThreshold) {
            secondBox[secondId].kBox = KalmanTracker(detectData[i].box);
            secondBox[secondId].id = firstBox[firstId].id;
            trackers.push_back(secondBox[secondId]);
        }
    }
    for (auto secBox:secondBox) {
        if (secBox.id == -1) {
            secBox.kBox = KalmanTracker(secBox.box);
            secBox.id = countId;
            countId++;
            trackers.push_back(secBox);
        }
    }
}

五、总结

在计算过程中,特别注意边缘目标处理。由远到近目标航迹管理需要当心判断。还有马氏距离匹配参数、距离权重、kalamn参数需要自行调整。在宽阔场景,跨相机重要目标匹配成功率可以高达 80%

代码仅供参考,禁止商业用途。欢迎私信交流。

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

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

相关文章

Ps:根据 HSB 调色(以可选颜色命令为例)

在数字色彩中&#xff0c;RGB 和 HSV&#xff08;又称 HSB&#xff09;是两种常用的颜色表示方式&#xff08;颜色模型&#xff09;。 在 RGB 颜色模式下&#xff0c;Photoshop 的红&#xff08;Red&#xff09;、绿&#xff08;Green&#xff09;、蓝&#xff08;Blue&#xf…

空气质量预测 | Python实现基于线性回归、Lasso回归、岭回归、决策树回归的空气质量预测模型

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 政府机构使用空气质量指数 (AQI) 向公众传达当前空气污染程度或预测空气污染程度。 随着 AQI 的上升,公共卫生风险也会增加。 不同国家有自己的空气质量指数,对应不同国家的空气质量标准。 对于空气质量预测,…

SpringBoot将第三方的jar中的bean对象自动注入到ioc容器中

新建一个模块&#xff0c;做自动配置 config&#xff1a;需要准备两个类&#xff0c;一个自动配置类&#xff0c;一个配置类 CommonAutoConfig&#xff1a;此类用于做自动配置类它会去读取resoutces下的META-INF.spring下的org.springframework.boot.autoconfigure.AutoConfig…

EDEM仿真导入stl文件慢的原因

我在将solidworks导出为STL文件后&#xff0c;再导入EDEM软件进行离散元仿真时&#xff0c;导入速度特别慢&#xff0c;发现是因为stl文件分辨率设置的过于精细&#xff0c;将文件分辨率设置为粗糙后&#xff0c;导入速度就快了。

SSH客户端 Termius for Mac 中文激活版

Termius for Mac是一款强大的终端和SSH客户端&#xff0c;为开发人员、系统管理员和网络工程师提供了全面的远程访问和管理工具。 软件下载&#xff1a;Termius for Mac 中文激活版下载 无论您是在使用Mac、Windows还是Linux系统&#xff0c;Termius都能提供出色的功能和用户体…

一、计算机组成与体系结构【7分】

一、课程内容 二、分值 三、数据表示 1、进制转换 其他进制转换为十进制 十进制转换为其他进制 二进制转换为八进制与十六进制 2、码制 这一块目前不是很懂 3、浮点数表示 4、算数与逻辑运算 四、校验码 1、奇偶校验码&#xff08;只能检测出奇位的错误&#xff0c;…

mac上搭建hbase伪集群

1. 前言 之前我们已经搭建过了 hbase单点环境&#xff0c;(单机版搭建参见&#xff1a; https://blog.csdn.net/a15835774652/article/details/135569456) 但是 为了模拟一把集群环境 我们还是尝试搭建一个伪集群版 2. 环境准备 jdk环境 1.8hdfs &#xff08;hadoop环境 可选…

如何保证缓存与数据库双写时的数据一致性?

背景&#xff1a;使用到缓存&#xff0c;无论是本地内存做缓存还是使用 Redis 做缓存&#xff0c;那么就会存在数据同步的问题&#xff0c;因为配置信息缓存在内存中&#xff0c;而内存时无法感知到数据在数据库的修改。这样就会造成数据库中的数据与缓存中数据不一致的问题。 …

使用py-spy对python程序进行性能诊断学习

py-spy简介 py-spy是一个用Rust编写的轻量级Python分析工具&#xff0c;它能够监视正在运行的Python程序&#xff0c;而不需要修改代码或者重新启动程序。Py-spy可以在不影响程序运行的情况下&#xff0c;采集程序运行时的信息&#xff0c;生成火焰图&#xff08;flame graph&…

MYSQL表的约束详解!

文章目录 前言一、空属性二、默认值三、列描述四、zerofill五、主键六、自增长七、唯一键八、外键 前言 真正约束字段的是数据类型&#xff0c;但是数据类型约束很单一&#xff0c;需要有一些额外的约束&#xff0c;更好的保证数据的合法性&#xff0c;从业务逻辑角度保证数据…

【CANoe使用大全】——Logging窗口

&#x1f64b;‍♂️【CANoe使用大全】系列&#x1f481;‍♂️点击跳转 文章目录 1.概述2.Logging窗口打开方式3.创建Logging4.配置4.1. 命名4.2.格式选择4.3. 路径选择与命名4.3.1.Logging文件命名_自定义4.3.2.Logging文件命名_系统内选择 5.Logging触发方式5.1 Logging模块…

QT实现USB摄像头接入显示

一、UVC协议简介 UVC全称是USB Video Class&#xff08;USB视频类&#xff09;&#xff0c;是一种标准化的USB视频设备通信协议&#xff0c;它定义了摄像头与主机之间的数据传输协议和格式。 UVC协议的出现&#xff0c;解决了摄像头厂商之间互不兼容&#xff0c;以及摄像头应…

win10通过ssh链接deepin23并开启x11转发

前提 主机环境&#xff1a;win10 lstc 虚拟机环境&#xff1a;deepin23beta2 终端&#xff1a;tabby x11服务器: vcxsrv 安装ssh sudo apt install ssh开启root登录(看你需求&#xff09; 首先你要给root账号设置密码 sudo passwd root修改配置文件 sudo vim /etc/ssh/ss…

MongoDB本地部署并结合内网穿透实现公网访问本地数据库

文章目录 前言1. 安装数据库2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射2.3 测试随机公网地址远程连接 3. 配置固定TCP端口地址3.1 保留一个固定的公网TCP端口地址3.2 配置固定公网TCP端口地址3.3 测试固定地址公网远程访问 4. 结语 前言 MongoDB是一个基于分布式文件…

Linux-ROS学习之旅-话题编程(二)

##承接上一篇文章的知识&#xff0c;有下面的实例操作 通过代码新生一个海龟&#xff0c;放置在(5,5)点&#xff0c;命名为turtle2&#xff0c;通过代码订阅turtle2的实时位置并打印在终端&#xff0c;控制turtle2实现旋转运动 步骤&#xff1a; 1.创建一个工作空间和一个功…

【GitHub项目推荐--30 天学会XXX(HTML/React/Python/JavaScript)】【转载】

30 天学会 React 这个项目是《30 天 React 挑战》&#xff0c;是在 30 天内学习 React 的分步指南。它需要你学习 React 之前具备 HTML、CSS 和 JavaScript 知识储备。 除了 30 天学会 React&#xff0c;开发者还发布过 30 天学会 JavaScript 等项目。 开源地址&#xff1a;…

MySQL数据操纵语言DML

MySQL数据操纵语言DML(SELECT,UPDATE,INSERT INTO,DELETE) 目录 MySQL数据操纵语言DML(SELECT,UPDATE,INSERT INTO,DELETE)DML关键字数据操纵语言DML1.查表2.插入数据3.更新数据4.删除数据 DML关键字 DML关键字含义SELECT从数据库中检索数据INSERT INTO向数据库表中插入新的行…

什么是协方差矩阵?

协方差矩阵&#xff08;Covariance Matrix&#xff09;是一个用于衡量多个变量之间相互关系的工具&#xff0c;在统计学和数据分析领域中非常重要。这个矩阵展现了每一对变量之间的协方差。协方差是衡量两个变量如何一起变化的度量&#xff1b;如果两个变量的协方差是正的&…

基于springboot+vue的美容院管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 研究背景…

运维SRE-01 目录结构体系、find

1. Linux目录结构体系 Linux 核心目录的核心文件概述 1&#xff09; /etc下面 a) /etc/hosts 主机ip地址与域名(主机名)对应关系 b&#xff09; /etc/hostname 主机名 c) /etc/sysconfig/network-scripts/ifcfg-ens33或ifcfg-eth0 Linux网卡配置文件 d&#xff09;了解 /etc/i…