对象跟踪小白?本文带你玩转OpenCV(C ++ / Python)

简介: 本文中我们将学习OpenCV 3.0中引入的OpenCV跟踪API,以及学习OpenCV 3.2中提供的6种不同的跟踪器。



作者介绍:Satya Mallick,擅长领域为计算机视觉,机器学习,人工智能。


dc299c72a2a2cdf8d401aabdde633feb4d433f8a


Linkdin:https://www.linkedin.com/in/satyamallick/zh-cn


在本教程中,我们将了解OpenCV 3.0中引入的OpenCV跟踪API。 我们将学习如何以及何时使用OpenCV 3.2中提供的6种不同的跟踪器- BOOSTINGMILKCFTLDMEDIANFLOWGOTURN。 我们还将学习现代跟踪算法背后的基本理论。

什么是对象跟踪?

简单地说,在视频的连续帧中定位对象被称为跟踪。

定义听起来很直接,但在计算机视觉和机器学习中,跟踪是一个非常宽泛的术语,涵盖概念上类似但技术上不同的理念 例如,通常在对象跟踪下研究所有以下不同但相关的理念

1. 密集光流:这些算法有助于估计视频帧中每个像素的运动矢量。

2. 稀疏光流:这些算法跟踪图像中几个特征点的位置,如Kanade-Lucas-TomashiKLT)特征跟踪器。

3. 卡尔曼滤波:用于非常流行的基于先前运动信息来预测运动对象的位置的信号处理算法。 这种算法的早期应用之一是导弹指导! 正如这里所提到的,“引导阿波罗11月球模块下降到月球的车载计算机具有卡尔曼滤波器”。

4. MeanShift算法和CamShift定位:这是一个密度函数的最大值的算法。它们也用于跟踪。

5. 单个对象跟踪器:在此类跟踪器中,第一帧使用矩形标记,以指示要跟踪的对象的位置。 然后使用跟踪算法在随后的帧中跟踪对象。 在大多数现实生活应用中,这些跟踪器与对象检测器结合使用。

6. 多目标跟踪算法:在我们有一个快速目标探测器的情况下,有意义的是检测每个帧中的多个目标,然后运行轨迹找到算法,识别一个帧中的哪个矩形对应于下一个帧中的矩形。

跟踪和检测

如果你曾经使用过OpenCV的脸部检测,你知道它是实时工作,你可以很容易地检测到每一帧的脸。 那么,为什么需要跟踪在第一个地方? 让我们来探索你可能要跟踪的视频中的对象的不同原因,而不仅仅是重复检测。

1. 跟踪速度比检测快:通常跟踪算法比检测算法快。原因很简单。当你跟踪在上一帧中检测到的对象时,你会非常了解对象的外观。你也知道在前一帧中的位置和它的运动的方向和速度。因此,在下一帧中,您可以使用所有这些信息来预测下一帧中对象的位置,并对对象的预期位置进行小型搜索,以准确定位对象。良好的跟踪算法将使用其关于对象的所有信息直到那一点,而检测算法总是从头开始。因此,在设计有效系统时,通常在每n帧上运行对象检测,而在其间的n-1帧中采用跟踪算法。为什么我们不是简单地检测第一帧中的对象并跟踪?实际上,跟踪从附加信息中获益,但是当它们在一个障碍物后面延长一段时间或者它们移动得如此之快以致跟踪算法不能赶上时,也可能失去对物体的跟踪。跟踪算法累积误差也是常见的,并且跟踪对象的边界框慢慢地偏离它跟踪的对象。为了解决跟踪算法中的这些问题,检测算法每隔一段时间运行一次。在对象的大量示例上训练检测算法。因此,它们对对象的一般类有更多的了解。另一方面,跟踪算法更多地了解它们正在跟踪的类的特定实例。

2. 当检测失败时跟踪可以起到帮助作用:如果你正在一个视频上运行一个面部检测器,人的面部被一个对象遮挡,面部检测器很可能失败。 另一方面,良好的跟踪算法将处理某种程度的遮挡。

3. 跟踪保留身份:对象检测的输出是包含对象的矩形数组。 但是,没有标识附加到对象。 例如,检测红点的检测器将输出与其在帧中检测到的所有点相对应的矩形。 在下一帧中,它将输出另一个矩形数组。 在第一帧中,特定点可以由矩阵在阵列中的位置10处表示,并且在第二帧中,其可以在位置17.当在帧上使用检测时,我们不知道哪个矩形对应于哪个对象。 另一方面,跟踪提供了一种方式来连接点。

OpenCV 3跟踪API

OpenCV 3提供了一个新的跟踪API,包含许多单个对象跟踪算法的实现。 OpenCV 3.2 - BOOSTINGMILKCFTLDMEDIANFLOWGOTURN6种不同的跟踪器。

注意:OpenCV 3.1具有这5个跟踪器的实现--BOOSTINGMILKCFTLDMEDIANFLOWOpenCV 3.0具有以下4个跟踪器的实现:BOOSTINGMILTLDMEDIANFLOW

在我们提供算法的简要描述之前,让我们看看设置和用法。 在下面的注释代码中,我们首先通过选择跟踪器类型(BOOSTINGMILKCFTLDMEDIANFLOWGOTURN)设置跟踪器。 然后我们打开一个视频,抓住一个框架。 我们定义一个包含第一帧对象的边界框,并用第一个框架和边界框初始化跟踪器。 最后,我们从视频中读取帧,并且只是在循环中更新跟踪器以获得当前帧的新的边界框。 随后显示结果。

C++

 2da9be853891db3cdab80842b6f96273ee68322f

b6912249e587ab48c167ab796d1b571c562738e6

 

Python

 12f5b9d0d722657d2e2c48432e1030925470039b

9f97ef063191dc8508a548a01f4a309844ab4f63

 

对象跟踪算法

在本节中,我们将挖掘一些不同的跟踪算法。我们的目标不是对每一个跟踪器有深刻的理论理解,而是从实际的角度来理解它们。

首先先解释一下跟踪的一些基本原理。在跟踪中,我们的目标是在当前帧中找到一个对象,因为我们已经在所有(或几乎所有)先前帧中成功跟踪了对象。

由于我们已经跟踪对象直到当前帧,我们知道它是如何移动的。 换句话说,我们知道运动模型的参数。 运动模型你知道的对象在之前的帧中的位置和速度(速度+运动方向)。 如果对对象没有其他了解,你可以根据当前的运动模型预测新位置,并且将非常接近对象的新位置。

但是我们有更多关于对象运动的信息 我们知道对象在每个先前帧中的外观。 换句话说,我们可以构建一个外观模型来编码对象的外观。 该外观模型可以用于在由运动模型预测的位置的小邻域中搜索,以更精确地预测对象的位置。

运动模型预测对象的大致位置。 外观模型微调这个估计以基于外观提供更准确的估计。

如果对象很简单,没有改变它的外观很多,我们可以使用一个简单的模板作为外观模型,并寻找那个模板。 然而,现实生活不是那么简单。 对象的外观可能会发生巨大变化。 为了解决这个问题,在许多现代跟踪器中,该外观模型是以在线方式训练的分类器。

分类器的工作是将图像的矩形区域分类为对象或背景。 分类器接受图像补丁作为输入,并返回01之间的分数,以指示图像补丁包含对象的概率。 当绝对确定图像补丁是背景时,分数为0,当绝对确定补丁是对象时,分数为1

在机器学习中,我们使用“在线”这个词来指代在运行时在运行中训练的算法。 离线分类器可能需要数千个示例来训练分类器,但是在运行时通常使用非常少的示例训练在线分类器。

分类器通过馈送正(对象)和负(背景)示例来训练。 如果你想建立一个分类器来检测猫,你训练它与成千上万包含猫的图像和数千不包含猫的图像。 这样分类器学习区分什么是猫和什么不是 可以在这里了解有关图像分类的更多信息。 在建立在线分类器时,我们没有成千上万的的例子。

让我们来看看不同的跟踪算法如何处理这个在线训练问题。

BOOSTING跟踪器

此跟踪器基于AdaBoost的在线版本 - 基于HAAR级联的面部检测器在内部使用的算法。 这个分类器需要在运行时用对象的正和负例子训练。 由用户提供的初始边界框(或由另一个对象检测算法)作为对象的正例,并且边界框外部的许多图像补片被当作背景。 给定新帧,对先前位置的邻域中的每个像素运行分类器,并记录分类器的得分。 对象的新位置是得分最大的位置。 所以现在我们有一个更积极的例子为分类器。 随着更多的帧进入,分类器用该附加数据更新。

优点:无。 这个算法是十年前并且可以运用,但我找不到一个很好的理由使用它,特别是当其他高级跟踪器(MILKCF)基于类似的原可用。

缺点:跟踪性能平庸。

MIL跟踪器

此跟踪器在概念上类似于上述的BOOSTING跟踪器。 最大的区别在于,代替仅考虑对象的当前位置作为积极示例,它在当前位置周围的小邻域中查找以生成若干潜在的正例子。 你可能认为这是一个坏主意,因为在大多数这些“积极”的例子中,对象不是中心。

 MIL中,你没有指定正和负例子,但是有正和负”。 正包中的图像集合并不都是积极的例子。 相反,只有一个图像在积极的里需要一个积极的例子在我们的示例中,正包含以对象的当前位置为中心的补丁,以及在其周围的小邻域中的补丁。 即使被跟踪对象的当前位置不准确,当来自当前位置的邻域的样本被放入正中时,很有可能这个包含至少一个图像,其中对象被良好地置于居中。

优点:性能相当不错。 它不像BOOSTING跟踪器那样漂移,它在部分遮挡合理工作。如果使用OpenCV 3.0,这可能是可用最好的跟踪。 但是如果你使用更高版本,考虑KCF

缺点:跟踪失败报告不可靠。不能从完全闭塞恢复。

KCF跟踪

KFC代表内核化相关滤波器。 这个跟踪器建立在前两个跟踪器提出的想法。 该跟踪器利用了这样的事实,即在MIL跟踪器中使用的多个正样本具有大的重叠区域。 这种重叠的数据导致一些良好的数学特性,利用这个跟踪器,使跟踪更快,同时更准确。

优点:准确度和速度都比MIL更好,它报告跟踪失败比BOOSTINGMIL更好。 如果您使用OpenCV 3.1和更高版本,我建议对于大多数应用程序使用这个。

缺点:不能从完全闭塞恢复。 未在OpenCV 3.0中实现。

Bug警告:在OpenCV 3.1(仅限Python)中有一个错误,因为返回了不正确的边界框。 参见错误报告。

TLD跟踪器

TLD代表跟踪,学习和检测。 顾名思义,该跟踪器将长期跟踪任务分解为三个组件 - (短期)跟踪,学习和检测。 从作者的论文,“跟踪器跟踪对象从一帧到帧。 检测器定位到目前为止观察到的所有外观,并在必要时校正跟踪器。 学习估计检测器的错误并更新它以避免未来的这些错误。“这个跟踪器的输出往往会跳一下。 例如,如果你正在跟踪行人,并且场景中还有其他行人,则该跟踪器有时可以临时跟踪与您要跟踪的行人不同的行人。 在积极的一面,这条轨道似乎在更大的规模,运动和遮挡下跟踪物体。 如果你有一个视频序列,其中的对象隐藏在另一个对象后面,这个跟踪器可能是一个不错的选择。

优点:在多个帧的遮挡下工作最好。 此外,跟踪最佳的规模变化。

缺点:很多误报,使它几乎不可用。

MEDIANFLOW跟踪器

在内部,该跟踪器在时间上向前和向后方向上跟踪对象,并且测量这两个轨迹之间的差异。 最小化该ForwardBackward错误使它们能够可靠地检测跟踪失败并在视频序列中选择可靠的轨迹。

在我的测试中,我发现这个跟踪器在运动是可预测和小规模的时候效果最好。 与其他跟踪器不同,即使跟踪明显失败,该跟踪器知道跟踪失败的时间。

优点:优秀的跟踪失败报告。 当运动是可预测的并且没有遮挡时工作得很好。

缺点:在大规模运动下失败。

GOTURN跟踪器

在跟踪器类中的所有跟踪算法中,这是基于卷积神经网络(CNN)的唯一一种。 它也是唯一一个使用离线训练模型,因为它比其他跟踪器更快。 从OpenCV文档,我们知道它“对视点变化,照明变化和变形是强大的”。 但它不能很好地处理遮挡。

Bug警告:不幸的是,在写这篇文章的时候,在使用Goturn时有一个错误在OpenCV 3.2实现使程序崩溃。


数十款阿里云产品限时折扣中,赶紧点击领劵开始云上实践吧!

以上为译文

本文由北邮@爱可可-爱生活 老师推荐,阿里云云栖社区组织翻译。

文章原标题《Object Tracking using OpenCV (C++/Python)》,作者:Satya Mallick,译者:tiamo_zn

文章为简译,更为详细的内容,请查看原文

目录
打赏
0
0
0
0
1807
分享
相关文章
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
[oeasy]python083_类_对象_成员方法_method_函数_function_isinstance
本文介绍了Python中类、对象、成员方法及函数的概念。通过超市商品分类的例子,形象地解释了“类型”的概念,如整型(int)和字符串(str)是两种不同的数据类型。整型对象支持数字求和,字符串对象支持拼接。使用`isinstance`函数可以判断对象是否属于特定类型,例如判断变量是否为整型。此外,还探讨了面向对象编程(OOP)与面向过程编程的区别,并简要介绍了`type`和`help`函数的用法。最后总结指出,不同类型的对象有不同的运算和方法,如字符串有`find`和`index`方法,而整型没有。更多内容可参考文末提供的蓝桥、GitHub和Gitee链接。
34 11
类和对象(中 )C++
本文详细讲解了C++中的默认成员函数,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载和取地址运算符重载等内容。重点分析了各函数的特点、使用场景及相互关系,如构造函数的主要任务是初始化对象,而非创建空间;析构函数用于清理资源;拷贝构造与赋值运算符的区别在于前者用于创建新对象,后者用于已存在的对象赋值。同时,文章还探讨了运算符重载的规则及其应用场景,并通过实例加深理解。最后强调,若类中存在资源管理,需显式定义拷贝构造和赋值运算符以避免浅拷贝问题。
类和对象(上)(C++)
本篇内容主要讲解了C++中类的相关知识,包括类的定义、实例化及this指针的作用。详细说明了类的定义格式、成员函数默认为inline、访问限定符(public、protected、private)的使用规则,以及class与struct的区别。同时分析了类实例化的概念,对象大小的计算规则和内存对齐原则。最后介绍了this指针的工作机制,解释了成员函数如何通过隐含的this指针区分不同对象的数据。这些知识点帮助我们更好地理解C++中类的封装性和对象的实现原理。
从集思录可转债数据探秘:Python与C++实现的移动平均算法应用
本文探讨了如何利用移动平均算法分析集思录提供的可转债数据,帮助投资者把握价格趋势。通过Python和C++两种编程语言实现简单移动平均(SMA),展示了数据处理的具体方法。Python代码借助`pandas`库轻松计算5日SMA,而C++代码则通过高效的数据处理展示了SMA的计算过程。集思录平台提供了详尽且及时的可转债数据,助力投资者结合算法与社区讨论,做出更明智的投资决策。掌握这些工具和技术,有助于在复杂多变的金融市场中挖掘更多价值。
70 12
类和对象(下)C++
本内容主要讲解C++中的初始化列表、类型转换、静态成员、友元、内部类、匿名对象及对象拷贝时的编译器优化。初始化列表用于成员变量定义初始化,尤其对引用、const及无默认构造函数的类类型变量至关重要。类型转换中,`explicit`可禁用隐式转换。静态成员属类而非对象,受访问限定符约束。内部类是独立类,可增强封装性。匿名对象生命周期短,常用于临时场景。编译器会优化对象拷贝以提高效率。最后,鼓励大家通过重复练习提升技能!
使用 OpenCV 和 Python 轻松实现人脸检测
本文介绍如何使用OpenCV和Python实现人脸检测。首先,确保安装了OpenCV库并加载预训练的Haar特征模型。接着,通过读取图像或视频帧,将其转换为灰度图并使用`detectMultiScale`方法进行人脸检测。检测到的人脸用矩形框标出并显示。优化方法包括调整参数、多尺度检测及使用更先进模型。人脸检测是计算机视觉的基础技术,具有广泛应用前景。
99 10
|
3月前
|
【C++面向对象——类与对象】Computer类(头歌实践教学平台习题)【合集】
声明一个简单的Computer类,含有数据成员芯片(cpu)、内存(ram)、光驱(cdrom)等等,以及两个公有成员函数run、stop。只能在类的内部访问。这是一种数据隐藏的机制,用于保护类的数据不被外部随意修改。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。成员可以在派生类(继承该类的子类)中访问。成员,在类的外部不能直接访问。可以在类的外部直接访问。为了完成本关任务,你需要掌握。
109 19
【C++篇】深度解析类与对象(中)
在上一篇博客中,我们学习了C++类与对象的基础内容。这一次,我们将深入探讨C++类的关键特性,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载、以及取地址运算符的重载。这些内容是理解面向对象编程的关键,也帮助我们更好地掌握C++内存管理的细节和编码的高级技巧。
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等