目标跟踪之ECO代码运行及原理简介

论文地址:https://arxiv.org/pdf/1611.09224.pdf
代码地址:https://github.com/martin-danelljan/ECO
ECO:(Efficient Convolution Operators for Tracking)是CVPR2017的一篇基于相关滤波的文章,本文主要对其matlab版本配置运行进行介绍,并简要分析其跟踪原理,分享自己的一些心得。

一、matlab代码运行

1、matconvnet下载

下载地址: https://github.com/vlfeat/matconvnet
下载后放置到external_libs/matconvnet/目录下
在这里插入图片描述

2、PDollar Toolbox下载

下载地址:https://github.com/pdollar/toolbox
下载后放置在external_libs/pdollar_toolbox/目录下
在这里插入图片描述

3、预训练模型imagenet-vgg-m-2048.mat下载

下载地址:https://www.vlfeat.org/matconvnet/pretrained/
在这里插入图片描述
如果点击出现乱码,无法下载,建议换个浏览器下载
在feature_extraction/目录下新建文件夹networks,并将下载的网络放置底下
在这里插入图片描述

4、运行install.m

如果是第一次在matlab运行matconvnet可能会比较麻烦点,CPU版本运行详解步骤可以参考我的上一篇博客CCOT代码运行,如果是GPU版本运行可以参考我的另一篇博客SiameseFC的运行两者是一样的流程。如果不想装visual studio,也可以参考这篇博客
运行成功显示如下
在这里插入图片描述

5、跟踪

作者给了好几个版本,都可以查看效果

  1. demo_ECO----CPU版本
  2. demo_ECO_gpu----GPU版本
  3. demo_ECO_HC----不使用CNN特征,只使用HOG+CN

三者跟踪速度差距较大,在我的matlab上跟踪速度如下:
在这里插入图片描述
跟踪效果如下
在这里插入图片描述

二、ECO算法简介

ECO是在CCOT的基础上进行改进的,两者也是出自同一作者,ECO主要是作者为解决CCOT过拟合、速度慢等问题进行的改进。

2.1背景

基于相关滤波的目标跟踪可以说是这几年的一个重要分支。为提高其跟踪的精度和鲁棒性,人们普遍采用1、多维度特征;2、目标尺寸预测;3、非线性核;4、对前几帧模型的存储;5、复杂的学习模型和6、减少边缘效应等手段,但这些方法都是以牺牲跟踪速度为前提的。
这些手段虽然提高了精度和跟踪鲁棒,但也带来了过拟合的风险。
为什么会过拟合?
目标跟踪通过第一帧来训练模型,训练数据相当有限,可是为了提高跟踪性能,滤波器模板越来越复杂(尤其是深度特征,数据量相当庞大),想利用有限的训练数据形成庞大复杂的训练模型,过分的训练少量的数据,导致复杂模型存在过拟合(以CCOT算法为例,每次更新模型需要改变800,000个参数)
总结起来,影响相关滤波速度的主要有
1、滤波器模型越来越大,不仅给计算带来负担,而且容易引起过拟合。
2、训练集越来越大,训练集主要用于保存之前每一帧的跟踪结果,所以每一次更新滤波器模型时,都要用到之前的样本,那么随着跟踪的进行,训练集保存的样本将越来越多,这明显不实际。一般都是丢弃老的样本,保存新的样本,但这种取舍导致模型更新过于依赖最近几帧目标的外观形状,但出现遮挡等现象,可能会污染模型,导致失败
3、模型更新策略,每帧更新模型不仅耗时,而且容易过拟合

2.2本文的三个贡献

本文主要是提出三个核心点,并解决了三个问题
1、Factorized Convolution Operator–特征的删减
先简要分析一下CCOT,CCOT的核心贡献在于将离散的feature map插值到连续域,解决了不同feature map的尺寸问题。
对离散feature map输入进行插值
在这里插入图片描述
b d {b_{d}} bd实际是一个sinc函数
x d [ n ] x^{d}[n] xd[n]第d维特征对应的离散输入
N d N^{d} Nd离散输入的数量,或者可以理解为feature map的分辨率
J d J^{d} Jd插值结果,第d维对应的连续的feature map
滤波器模型预测结果:
在这里插入图片描述
损失函数(共有M个训练样本)
在这里插入图片描述
变换到频域
在这里插入图片描述
对滤波器f求导,解的
在这里插入图片描述
A A A:块对角矩阵,实际就是训练样本组成的矩阵,每个对角块代表一个样本
Γ \Gamma Γ:包含每个训练样本权重 α j \alpha _{j} αj的矩阵
通过Conjugate Gradient(共轭梯度)迭代计算出使损失函数最小的 f ^ \hat{f} f^
CCOT在特征提取方面相当全面CNN+CN+HOG的组合使得其性能相当出色,但作者很快发现CCOT存在大量的过拟合,如下图
在这里插入图片描述
因此,ECO中,作者第一个贡献就是对CCOT特征提取的简化,对于CCOT,每一维特征都对应一个特定的滤波器,但通过观察可以发现,CCOT用到的滤波器很稀疏,如下图所示,绝大部分滤波器对跟踪定位没有帮助却占用计算时间,所以Factorized Convolution Operator就是为了保留对定位有重要贡献的滤波器。
在这里插入图片描述
具体步骤:
主要是引入一个常数矩阵P(尺寸为D×C),该矩阵的作用在于将高维特征进行删减,原来共有D维特征,加入P后只剩下C维(P对滤波器数量的删减可以理解为对提取特征维度的删减,因为一个滤波器对应一个特征)。
预测结果:
在这里插入图片描述
损失函数在频域中表现为:
在这里插入图片描述
这是一个非线性最小二乘问题,相比于CCOT,作者不仅用了Conjugate Gradient(共轭梯度),还引入高斯牛顿来对矩阵P,滤波器 f ^ \hat{f} f^进行展开
在这里插入图片描述
其中
在这里插入图片描述
其中高斯牛顿迭代了10次,共轭梯度迭代了20次,具体原理不明白可以不深究。
第一个贡献的效果:明显降低了滤波器的维度数量
在这里插入图片描述
2、Generative Sample Space Model----保持样本的多样性并减少其数量
这一贡献主要是针对训练集进行改进,正如上文所提,训练集数量庞大,而且简单的舍弃老样本(如下图的第二行Baseline所示)导致滤波器模型过于依赖最近几帧的目标外观模型,且存在大量冗余。
在这里插入图片描述
为此作者通过样本x和预期目标输出y的联合概率分布p(x,y),将目标函数完善为
在这里插入图片描述
原始的损失函数(公式3)只不过是 p ( x , y ) = ∑ j = 1 M α j δ x j , y j ( x , y ) p(x,y)=\sum_{j=1}^{M} \alpha _{j} \delta _{x_{j},y_{j}}(x,y) p(x,y)=j=1Mαjδxj,yj(x,y)的一个特例,另外预期目标输出y其实形状一致,只不过峰值位置发生平移,所以作者将y设置成一样,而峰值位置的平移放入x中进行考虑。所以只需要考虑p(x),此处引入高斯混合建模(GMM)

高斯混合模型,英文全称:​​Gaussian mixture model,简称GMM。高斯混合模型就是用高斯概率密度函数(二维时也称为:正态分布曲线)精确的量化事物,将一个事物分解为若干基于高斯概率密度函数行程的模型
高斯混合模型也​被视为一种聚类方法,是机器学习中对“无标签数据”进行训练得到的分类结果。其分类结果由概率表示,概率大者,则认为属于这一类。

对GMM模型的理解
类似于傅里叶变换,自然界任何复杂曲线都可以用无数个不同形状sin和cos曲线组成,高斯函数也是如此(如下图,摘自博客),只要数量够多,高斯函数可以表征任意复杂的曲线,换成高维空间也是一个道理。
在这里插入图片描述

总结一句话,通过多个不同形状的高斯函数(component对应上图中蓝色的单一高斯曲线),可以拟合任意曲线(GMM模型对应上图中红色的高斯叠加曲线)。

训练集采集样本步骤:

  1. 每来一帧新图片,使用 π m = γ \pi_{m}=\gamma πm=γ μ m = x j \mu_{m}=x_{j} μm=xj(训练样本输入)来初始化一个新component m
  2. 如果此时component的数量超过L(事先设定的值),开始简化GMM模型,反之,直接进行保存
  3. 简化GMM,比较GMM各个components的 μ m \mu_{m} μm,根据两者之间的距离 ∣ ∣ μ k − μ l ||\mu_{k}-\mu_{l} μkμl,找出距离最近的两个components,并将其合为一个component,该component的 μ \mu μ π \pi π由下可计算得
    在这里插入图片描述
  4. 持续更新,直到M个训练样本都结束完

损失函数为
在这里插入图片描述
相比原来的损失函数,滤波器由M减为L(文中L=M/8)
3、Model Update Strategy----每6帧更新一次模型
模型更新没什么难理解,每隔 N s = 6 N_{s}=6 Ns=6更新一次。
但这里有的需要注意得,那就是训练集样本component仍然是每帧更新的,但是GMM模型是每 N s N_{s} Ns更新一次

2.3跟踪效果

相比于CCOT,其精度更佳,速度更快,三个贡献都相当有效
在这里插入图片描述
参考博客
深度理解高斯混合模型(GMM)
目标跟踪算法二:ECO: Efficient Convolution Operators for Tracking(2016年11月)

  • 12
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
好的,ECO是一种用于编写智能合约的编程语言,它是基于C++语言开发的。因此,你可以使用C++编写ECO智能合约代码,并使用ECO编译器将其编译为字节码,然后在ECO虚拟机上运行。 以下是一个简单的ECO智能合约代码示例,它实现了一个简单的转账功能: ``` #include <eco.hpp> using namespace eco; class transfer_contract : public contract { public: transfer_contract(account_name self) : contract(self) {} void transfer(account_name from, account_name to, uint64_t amount) { require_auth(from); auto from_balance = get_balance(from); eosio_assert(from_balance >= amount, "Insufficient balance"); sub_balance(from, amount); add_balance(to, amount); } private: void sub_balance(account_name owner, uint64_t value) { auto balance = get_balance(owner); eosio_assert(balance >= value, "Insufficient balance"); balance -= value; set_balance(owner, balance); } void add_balance(account_name owner, uint64_t value) { auto balance = get_balance(owner); balance += value; set_balance(owner, balance); } uint64_t get_balance(account_name owner) { accounts accountstable(_self, owner); auto it = accountstable.find(symbol_code("ECO").raw()); return it != accountstable.end() ? it->balance : 0; } void set_balance(account_name owner, uint64_t value) { accounts accountstable(_self, owner); auto it = accountstable.find(symbol_code("ECO").raw()); if (it == accountstable.end()) { accountstable.emplace(_self, [&](auto& a) { a.balance.symbol = symbol("ECO", 4); a.balance.amount = value; a.owner = owner; }); } else { accountstable.modify(it, _self, [&](auto& a) { a.balance.amount = value; }); } } struct [[eosio::table]] account { asset balance; account_name owner; uint64_t primary_key() const { return balance.symbol.code().raw(); } }; typedef eosio::multi_index<"accounts"_n, account> accounts; }; extern "C" { void apply(uint64_t receiver, uint64_t code, uint64_t action) { if (code == receiver) { switch (action) { EOSIO_DISPATCH_HELPER(transfer_contract, (transfer)) } } } } ``` 在这个示例中,我们定义了一个名为`transfer_contract`的智能合约类,它继承自`contract`类。`transfer_contract`类中定义了一个名为`transfer`的公共函数,用于实现转账功能。该函数接受三个参数:转账发起人的账户名、接收方的账户名和转账金额。 在`transfer`函数中,我们首先使用`require_auth`函数验证转账发起人的身份。然后,我们检查发起人的余额是否足够支付转账金额,如果不足,则抛出异常。接着,我们从发起人的余额中减去转账金额,并将相应的金额添加到接收方的余额中。 `transfer_contract`类中还定义了一些私有函数,用于获取、设置账户余额等操作。此外,我们还定义了一个名为`account`的结构体,用于存储账户余额信息。最后,我们使用`EOSIO_DISPATCH_HELPER`宏将`transfer_contract`类中的`transfer`函数注册为智能合约的操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值