【论文解读】Observation-Centric SORT:Rethinking SORT for Robust Multi-Object Tracking

news2024/11/19 13:31:47

一.介绍

1.1 之前卡尔曼方法存在的问题:

  • 1.长时间的运动的线性估计可能是非常不准确的。
  • 2.当没有可用于更新卡尔曼滤波器参数的测量时,标准惯例是信任先验状态估计进行后验更新,这导致了在一段时间内错误的积累。

1.2 基于假设

假设跟踪目标在一定时间间隔内速度恒定,称为线性运动假设。

1.3 SORT的局限性

(1)状态估计噪声的敏感性:尽管高帧率是将物体运动近似为线性的关键,但它也放大了模型对状态估计噪声的敏感性。(噪声和物体的移动是同一量级)

(2)误差随时间的累积:当在KF的更新阶段中没有可用的观测时,通过KF的状态估计的噪声沿着时间累积。

(3)以估计为中心:SORT被设计为通过状态估计而不是观察来延长物体的轨迹。

1.4 本项工作的创新点

(1)设计了一个模块,使用对象状态观察来减少轨迹丢失期间的累积误差

  • 在传统的预测和更新阶段之外,增加了“重更新”阶段来修正累积误差。重更新是在经过一段时间的未跟踪后,通过与观测相关联而重新激活跟踪时触发的。重更新使用对历史时间步长的虚拟观测来防止错误积累。
  • 虚拟观测来自一个轨迹,该轨迹是由未跟踪前最后一次观测重新激活该轨迹的最新观测作为锚点生成的。我们将其命名为以观察为中心的重新更新(ORU)。

(2)以为观测中心的动量(OCM)

  • 将跟踪一致性纳入关联的成本矩阵中

二. OCSort

 2.1  Observation-centric Re-Update (ORU)

将未跟踪前最后看到的观测值记为z_{t1},将触发重新关联的观测值记为z_{t2},从而构建虚拟轨迹

 沿着上述轨迹进行预测-再更新的循环,再更新 的步骤如下:

2.2 Observation-Centric Momentum (OCM)

通过使用观测值去替代估计值,避免了估计值会出现的误差放大问题。

关联的代价矩阵引入状态观测值的一致性项 ,表述为:

  • C_{iou}计算负的两两IoU(Intersection over Union)
  •  C_v计算①连接现有轨道(\theta^{track})上的两个观测值 和 ②连接轨道的历史观测值和新观测值(\theta^{intention}方向之间的一致性。
  • Cv包含所有对\Delta \theta = \left | \theta^{track}- \theta^{intention} \right |。在我们的实现中,我们以弧度计算运动方向,即\theta =arctan(\frac{v_1 - v_2}{u_1 - u_2}),其中(u1, v1)和(u2, v2)是两个不同时间步长的观测值。

在线性运动模型下,方向估计噪声的尺度与两个观测点之间的时间差呈负相关,即∆t。这表明增加∆t可以实现对θ的低噪声估计。然而,线性运动的假设通常只在∆t足够小时成立。因此,∆t的选择需要权衡。

2.3 heuristic Observation-Centric Recovery (OCR) 

OCR将开始第二次尝试将上次观测到的不匹配轨迹与不匹配的观测相关联。

三. 代码

3.1 整体代码架构

整体代码架构类似于bytetrack

3.2 OCM

将运动方向引入了代价矩阵作为关联,即

\Delta \theta = \left | \theta^{track}- \theta^{intention} \right | 表示历史运动方向和当前观测的运动方向的弧度的差值

3.2.1 关联函数associate

3.2.1.1 传入参数含义

 #dets:高置信度检测结果
remain_inds = scores > self.det_thresh
dets = dets[remain_inds]
#trks:之前的跟踪轨迹
#iou_threshold:iou匹配阈值
#velocities:之前所有轨迹的跟踪结果
velocities = np.array([trk.velocity if trk.velocity is not None else np.array((0, 0)) for trk in self.trackers])
#k_observations:最新的观测
#k_previous_obs用于返回最新age最大的观测数据
k_observations = np.array([k_previous_obs(trk.observations, trk.age, self.delta_t) for trk in self.trackers])
#inertia:权重
       
matched, unmatched_dets, unmatched_trks = associate(
            dets, trks, self.iou_threshold, velocities, k_observations, self.inertia)

3.2.1.2 associate函数

(代码略有缩减)

(1)angle_diff_cost
Y, X = speed_direction_batch(detections, previous_obs)

def speed_direction_batch(dets, tracks):
    tracks = tracks[..., np.newaxis]
    CX1, CY1 = (dets[:,0] + dets[:,2])/2.0, (dets[:,1]+dets[:,3])/2.0
    CX2, CY2 = (tracks[:,0] + tracks[:,2]) /2.0, (tracks[:,1]+tracks[:,3])/2.0
    dx = CX1 - CX2 
    dy = CY1 - CY2 
    norm = np.sqrt(dx**2 + dy**2) + 1e-6
    dx = dx / norm 
    dy = dy / norm
    return dy, dx # size: num_track x num_det

通过观测数据和轨迹数据获得在x和y方向上像素位置的变化量并对输出数据进行正则化

    inertia_Y, inertia_X = velocities[:,0], velocities[:,1]
    inertia_Y = np.repeat(inertia_Y[:, np.newaxis], Y.shape[1], axis=1)
    inertia_X = np.repeat(inertia_X[:, np.newaxis], X.shape[1], axis=1)

 获得速度在x,y方向上的变化量

 diff_angle_cos = inertia_X * X + inertia_Y * Y

cos(\theta ) =\frac{\vec{a} *\vec{ b}}{\left | \vec{a} \right |*\left | \vec{b} \right |},传入的inertia_X , X , inertia_Y , Y都是已经正则化的数据 

(2)iou_matrix

iou_matrix代价矩阵的计算也不是新东西了

def iou_batch(bboxes1, bboxes2):
    """
    From SORT: Computes IOU between two bboxes in the form [x1,y1,x2,y2]
    """
    bboxes2 = np.expand_dims(bboxes2, 0)
    bboxes1 = np.expand_dims(bboxes1, 1)
    
    xx1 = np.maximum(bboxes1[..., 0], bboxes2[..., 0])
    yy1 = np.maximum(bboxes1[..., 1], bboxes2[..., 1])
    xx2 = np.minimum(bboxes1[..., 2], bboxes2[..., 2])
    yy2 = np.minimum(bboxes1[..., 3], bboxes2[..., 3])
    w = np.maximum(0., xx2 - xx1)
    h = np.maximum(0., yy2 - yy1)
    wh = w * h
    o = wh / ((bboxes1[..., 2] - bboxes1[..., 0]) * (bboxes1[..., 3] - bboxes1[..., 1])                                      
        + (bboxes2[..., 2] - bboxes2[..., 0]) * (bboxes2[..., 3] - bboxes2[..., 1]) - wh)                                              
    return(o)  
 (3)匹配和对应数据分配

3.3 ORU

3.3.1 关于时间的计算

在OCsort中并没有真正的传入花费的时间,而是通过数据的序号来计算时间

            indices = np.where(np.array(occur)==0)[0]
            index1 = indices[-2]
            index2 = indices[-1]
            time_gap = index2 - index1

3.3.2 生成虚拟路径

3.3.2.1  时间步下的变化

通过未跟踪前最后看到的观测和触发重新关联的观测之间经过的时间步,算出每个时间步下的变化

            time_gap = index2 - index1
            dx = (x2-x1)/time_gap
            dy = (y2-y1)/time_gap 
            dw = (w2-w1)/time_gap 
            dh = (h2-h1)/time_gap

3.3.2.2 恒速运动生成虚拟轨迹

            for i in range(index2 - index1):

                x = x1 + (i+1) * dx 
                y = y1 + (i+1) * dy 
                w = w1 + (i+1) * dw 
                h = h1 + (i+1) * dh
                s = w * h 
                r = w / float(h)
                new_box = np.array([x, y, s, r]).reshape((4, 1))

                self.update(new_box)
                if not i == (index2-index1-1):
                    self.predict()

3.3.2 ORU触发

(1) 没有观测数据保存当前卡尔曼参数

        if z is None:
            if self.observed:
                """
                    Got no observation so freeze the current parameters for future
                    potential online smoothing.
                """
                self.freeze()
            self.observed = False 
            self.z = np.array([[None]*self.dim_z]).T
            self.x_post = self.x.copy()
            self.P_post = self.P.copy()
            self.y = zeros((self.dim_z, 1))
            return

 (2) 重新跟踪到

        if not self.observed:
            """
                Get observation, use online smoothing to re-update parameters
            """
            self.unfreeze()

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

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

相关文章

ARM体系结构学习笔记:位操作和灵活的2nd操作数

位操作 移位运算 数据传输指令 灵活的2nd操作数 Set a bit a | (1 << 5)Clear a bit a & ~(1 << 5)Toggling a bt a ^ 1<<5

IDEA开发项目时一直出现http404错误的解决方法

系列文章目录 安装cv2库时出现错误的一般解决方法_cv2库安装失败 SQL&#xff1e; conn sys/root as sysdbaERROR:ORA-12560: TNS: 协议适配器错误的解决方案 虚拟机启动时出现“已启用侧通道缓解”的解决方法 Hypervisor launch failed&#xff1b; Processor does not pr…

数据的绘画工场:Python绘图库Pyecharts,打造引人入胜的可视化效果

欢迎阅读本篇文章&#xff0c;本文将带您从零开始&#xff0c;逐步掌握使用Pyecharts库进行数据可视化的技能。Pyecharts是一个基于Echarts的Python可视化库&#xff0c;能够轻松创建各种交互式图表和地图&#xff0c;无论您是数据分析新手还是有经验的开发者&#xff0c;本文都…

【计算机视觉】相机基本知识(还在更新)

1.面阵工业相机与线阵工业相机 1.1 基本概念区别 面阵相机则主要采用的连续的、面状扫描光线来实现产品的检测&#xff1b; 线阵相机即利用单束扫描光来进行物体扫描的工作的。 1.2 优缺点 &#xff08;1&#xff09;面阵CCD工业相机&#xff1a; 优点&#xff1a;应用面…

ZooKeeper集群服务器启动

在本文中&#xff0c;我们将对集群版ZooKeeper服务器的启动过程做详细讲解。集群和单机ZooKeeper服务器的启动过程在很多地方都是一致的&#xff0c;因此本节只会对有差异的地方展开进行讲解。下图所示是集群版ZooKeeper服务器的启动流程图。 预启动 预启动的步骤如下。 (1)统…

财报解读:上半年业绩实现增长,药师帮业务飞轮已经开始旋转?

今年6月底登陆港股的药师帮&#xff0c;近日发布了上市后的首份财务报告。 财报显示&#xff0c;2023年上半年&#xff0c;药师帮实现营收增长、经调整后净利润转正的成果&#xff0c;再次验证了二级市场对于其发展潜力的看好——6月底上市以来&#xff0c;药师帮股价涨幅接近…

Mybatis的学习笔记(IDEA快捷键,参数占位符,转义符)

一、IDEA快捷键&#xff1a; IDEA多行注释&#xff1a;ctrlShift/ 单行注释&#xff1a;ctrl/ 导入包&#xff0c;自动修正代码&#xff1a;altenter 自动生成代码&#xff1a;altinsert 二、Mybatis重要知识点&#xff1a; 2.1 参数占位符 一共分为2种&#xff1a;#{}和…

idea2023 springboot+mybatis+jsp 初学单表增删改查

创建项目 因为2.7.14使用量较少&#xff0c;特更改spring-boot为2.7.5版本 配置端口号 打开Sm01Application类&#xff0c;右键运行启动项目&#xff0c;或者按照如下箭头启动 启动后&#xff0c;控制台提示如下信息表示成功 此刻在浏览器中输入&#xff1a;http://lo…

盘点市面上的ipad协议对比

友情链接 geweapi.com 点击即可访问! Web网页端&#xff1a;2017年后不再支持新号登录&#xff0c;仅支持老号&#xff0c;并且掉线严重&#xff0c;功能缺失严重。 Xposed技术&#xff1a;在2019年6月份&#xff0c;微信官方在行业重点打击Xposed&#xff0c;自此行业内一片…

企望制造ERP系统 RCE漏洞[2023-HW]

企望制造ERP系统 RCE漏洞 一、 产品简介二、 漏洞概述三、 复现环境四、 漏洞复现小龙POC检测 五、 修复建议 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;…

IO day 4

1、使用两个进程完成两个文件的拷贝&#xff0c;父进程拷贝前一半内容&#xff0c;子进程拷贝后一半内容&#xff0c;并且父进程要阻塞回收子进程资源 #include <myhead.h>int main(int argc, const char *argv[]) {char a[1] {0};pid_t pid;pid fork();//创建一个子进…

马哈鱼数据血缘工具背后的项目: gsp_demo_java 项目简单介绍与使用

0.背景 马哈鱼数据血缘工具(https://www.sqlflow.cn/)是SQLflow工具的中文译名,实际就是sqlflow. 对于SQL flow来说,底层调用的是General SQL Parser(GSP https://sqlparser.com) 的库. 这个gsp有开源的java demo项目:https://github.com/sqlparser/gsp_demo_java 1.快速使用…

Focus-DETR利用双重注意力机制重建编码器,打造最强目标检测模型

前期的文章我们介绍了DETR模型,我们知道DETR模型首先使用CNN卷积神经网络搜集图片的核心特征点,然后把这些特征点整合起来,通过embedding方法,把特征图片转换到特征向量空间。然后根据标准Transformer模型的编码器与解码器进行注意力机制的计算,最后把计算后的数据进行图片…

vue3+ts+vite使用el-breadcrumb实现面包屑组件,实现面包屑过渡动画

简介 使用 element-plus 的 el-breadcrumb 组件&#xff0c;实现根据页面路由动态生成面包屑导航&#xff0c;并实现面包屑导航的切换过渡动画 一、先看效果加粗样式 1.1 静态效果 1.2 动态效果 二、全量代码 <script lang"ts" setup> import { ref, watch…

5个高清视频素材网站

推荐5个高清视频素材网站&#xff0c;免费、付费、商用的都有&#xff0c;可根据自己需求去选择&#xff0c;赶紧收藏吧&#xff01; 菜鸟图库 https://www.sucai999.com/video.html?vNTYxMjky ​ 菜鸟图库网素材非常丰富&#xff0c;网站主要还是以设计类素材为主&#xff…

RCE远程命令执行

逻辑运算符:: &&&#xff1a;代表首先执行命令a&#xff0c;若成功再执行命令b&#xff0c;又被称为短路运算符。 &&#xff1a;代表首先执行命令a再执行命令b&#xff0c;不管a是否成功&#xff0c;都会执行命令b。在执行效率上来说“&&”更加高效。 ||&a…

合宙Air724UG LuatOS-Air LVGL API--简介

为何是 LVGL LVGL 是一个开源的图形库&#xff0c;它提供了创建嵌入式 GUI 所需的一切&#xff0c;具有易于使用的图形元素、漂亮的视觉效果和低内存占用的特点。 LVGL特点&#xff1a; 强大的 控件 &#xff1a;按钮、图表、列表、滑动条、图像等 高级图形引擎&#xff1a;动…

AIGC之文本内容生成概述(下)—— BERT

关于AIGC系列的文章内容&#xff0c;我们在上一期介绍了基础模型Transformer&#xff0c;本期将会继续介绍基于Transformer模型改进的BERT&#xff08;双向编码器表示Transformer&#xff09;模型。如果想要查之前的介绍内容&#xff0c;可以关注本号&#xff0c;翻看之前的文章…

九耶丨阁瑞钛伦特-在项目中找到的经典BUG是什么?

在项目中找到的经典BUG有很多种&#xff0c;以下是其中一些常见的例子&#xff1a; 空指针异常&#xff08;NullPointerException&#xff09;&#xff1a;当程序试图访问一个空对象或未初始化的变量时&#xff0c;会抛出空指针异常。这通常是由于缺少对变量的正确初始化或检查…

知识继承概述

文章目录 知识继承第一章 知识继承概述1.背景介绍第一页 背景第二页 大模型训练成本示例第三页 知识继承的动机 2.知识继承的主要方法 第二章 基于知识蒸馏的知识继承预页 方法概览 1.知识蒸馏概述第一页 知识蒸馏概述第二页 知识蒸馏第三页 什么是知识第四页 知识蒸馏的核心目…