现在我们有一个视频流,可以拆解出 N 个帧出来,这时候初始帧/某一帧中出现了一个我们感兴趣目标,我们希望在后续帧中对这个目标进行追踪,这时候就需要 CV 中的目标追踪;

目标追踪的效果如下:

虽然效果看起来和实时人脸检测效果一样,但是只对初始帧进行了人脸检测/识别,后续帧不需要再进行检测/识别,这也是目标跟踪可以提高程序性能的优势所在;

因为做目标追踪所需要的计算时间成本,要低于进行检测/识别的;

为了实现目标追踪,我们按照以下步骤进行:

  1. 对于初始帧(视频流中的第一帧),输入/通过检测算法,得到一系列目标的位置坐标;
  2. 为这些 ROI 创建 ID;
  3. 在视频流中的后续帧,寻找帧之间目标对象的关系,将帧之间的目标关联起来;

目标跟踪可以让我们对于每一个追踪的目标指定一个唯一的 ID,所以让我们可以对视频中的跟踪物体进行计数,应用于计算人数的场景;

一个理想化的目标追踪算法能够实现:

  1. 只需要初始化的时候进行目标检测;
  2. 处理速度能够很快;
  3. 可以处理被跟踪目标,消失或者超过边界的情况;
  4. 可以处理帧之间目标消失,然后再出现的特殊情况;

上图 gif 中只有一个目标,所以其实后续帧中的检测出来的目标,如果还是一个,肯定就是我们第一帧中识别出来的 person_X;

但是往往是一帧中出现多目标,我们就需要对于前后帧中的多目标进行比对匹配;

以下图为例,比如左边是第 N 帧 ,有两个目标,我们检测识别出来是 ID#1 和 ID#2,在 N+1 帧中,也检查出来两个目标,我们知道这两个目标就是 ID#1 和 ID#2,但是不知道到底哪个是 ID#1 哪个是 ID#2;

所以就需要 质心追踪算法(Centroid Tracking)来进行判定后续帧中的 ID:

 质心追踪算法(Centroid Tracking,依赖于在视频流的连续帧中,比较已知目标和新出现目标之间质心的欧氏距离;

步骤一:取特征框并计算质心

对于视频流,通过检测算法对于每帧图像进行检测;

比如上图中有两个特征框 / 或者我们假定两个特征框给它,分别为 ID #1 和 ID #2,可以计算出两个特征框的质心,分别得到位置坐标 (x,y);

以实际视频流为例:

步骤二:计算新旧目标特征框质心的欧氏距离

对于视频流中的后续帧,我们利用检测算法来计算特征框,但是我们不会再去给对于每一个检测到的物体,添加新的 ID 或者标记什么的,而是希望将新的目标能够和旧目标联系起来;

我们通过计算每对新旧目标的欧式距离来得到这些目标之间的关系;

如下图所示,比如帧 N 时候有两个目标(绿色),帧 N+1 时候有三个目标(红色),所以对于我们希望知道,这两个旧目标(绿色),在后续帧中变成了哪一个新目标(红色);

所以我们想知道如下质心之间的关系:

  • 绿1->红1,绿1->红2,绿1->红3;
  • 绿2->红1,绿2->红2,绿2->红3;

步骤三:更新已知目标的质心坐标

质心追踪算法的前提是:对于一个给定目标,将会在后续帧中都出现,而且在第 N 帧和 N+1 帧中的质心欧氏距离,要小于不同目标之间的欧式距离;

因此我们在视频流的连续帧之间,根据欧氏距离最小原则,将这些帧中特征框的质心联系起来,可以得到一个目标 X 在这些连续帧中的变化联系,就达到了我们目标追踪的目的;

步骤四:注册新目标

有时候会有新目标的加入,比如帧 N 的时候有 x 个目标,而帧 N+1 的时候有 x+1 个目标,增加了一个目标;

所以对于这个新增的目标,我们按照以下顺序进行注册:

  1. 给这个新目标一个目标 ID;
  2. 储存这个目标特征框的质心位置;

然后从步骤二开始,对于视频流中的每一帧进行计算欧氏距离,更新坐标等步骤;

步骤五:注销旧目标

一个目标在后续帧中可能会消失,我们的目标追踪算法也要能够处理这种情况;

但是对于消失目标的处理方法,要根据于你实际部署应用的场景;

  • 第 N 帧丢失目标,注销旧目标
  • 第 N 帧丢失目标,而且第 N 帧中的后续 n 帧中都没有找回来,那就注销旧目标

因为每次重新注册的成本(进行检测/识别)的成本要大于欧氏距离比对进行目标追踪的成本;

# 请尊重他人劳动成果,转载或者使用源码请注明出处:http://www.cnblogs.com/AdaminXie

# 欢迎关注我的 Github:https://github.com/coneypo/

# 如有问题请留言或者联系邮箱: coneypo@foxmail.com

最新文章

  1. C++:名字查找先于类型检查
  2. Ubuntu下eclipse开发hadoop应用程序环境配置
  3. Unity3d 鼠标拣选小功能集合
  4. C++ STL string
  5. FileStream和StreamWriter配合写数据流时,出现数据写不进去的问题
  6. JavaScript DOM编程艺术学习笔记(一)
  7. Build Settings
  8. 让你的.NET程序支持多语言
  9. 转:.Net程序员学习Linux最简单的方法
  10. Jar包转成Dll的方式(带嵌套的jar也能做)
  11. __stack_chk_fail栈检查失败
  12. ASP.NET MVC AJAX的调用示例
  13. Django的Models
  14. SQLALchemy中关于复杂关系表模型的映射处理
  15. Java之旅_面向对象_重写和重载
  16. 微信小程序开发动感十足的加载动画--都在这里!
  17. Lua 中pairs与ipairs区别
  18. 01.MyBatis入门
  19. 从LayoutInflater分析XML布局解析成View的树形结构的过程
  20. Makefile生成器,使用C++和Boost实现

热门文章

  1. 如何部署redis服务
  2. PHP 是什么?简介下
  3. ElasticSearch 基础入门 and 操作索引 and 操作文档
  4. Spring Cloud Data Flow初体验,以Local模式运行
  5. ios_UITextField右侧小圆叉
  6. 为写程序而生的连字字体 Fira Code
  7. 用 Python 写个消消乐小游戏
  8. Python编写的桌面图形界面程序实现更新检测和下载安装
  9. 用Python绘制一套“会跳舞”的动态图形给你看看
  10. VMware启动CentOS出错,提示"该虚拟机似乎正在使用中"