如何使用OpenCV实现对象跟踪?分步指南

2021年11月28日04:47:03 发表评论 1,465 次浏览

长期以来,工程师和计算机科学家一直试图让计算机查看和解释视觉数据,并根据收集的数据执行某些功能。这就是计算机视觉的想法出现的地方。计算机视觉旨在使机器的过程自动化,这可以由人类视觉执行。你可以说人工智能赋予了计算机思考的能力,计算机视觉赋予了它们看和解释视觉的能力。计算机视觉允许机器执行人眼和思维的功能,但这必须借助相机和算法来完成,而不是神经和视网膜。

如何使用OpenCV实现对象跟踪?在过去的二十年里,人工智能驱动的计算机视觉提供了多种方法来执行人脑可以完成的与视觉相关的单一功能。现代计算机视觉技术的实施使技术发生了指数级的革命。现在,它几乎适用于所有其他技术领域,无论是医疗诊断、自动驾驶汽车,还是从图像和视频中去除背景。继续讨论对象跟踪问题,下面的文章更深入地探讨了这个概念。我们从基础开始,将继续使用 OpenCV 全面实现对象跟踪算法。文章分为以下几个部分:

  • 什么是对象跟踪?
  • 对象跟踪方法
  • 什么是 OpenCV?
  • OpenCV如何用于对象跟踪?
  • Python OpenCV实现对象跟踪示例
  • 结论

什么是对象跟踪?

对象跟踪是计算机视觉的一个此类应用,其中在视频中检测对象,否则将其解释为一组帧,并估计对象的轨迹。例如,你有一个棒球比赛的视频,并且你希望在整个视频中不断跟踪球的位置。目标跟踪是通过估计其轨迹来实时跟踪球在屏幕上的位置的方法。

如何使用OpenCV实现对象跟踪?分步指南
对象跟踪

OpenCV如何实现对象跟踪?在抽象级别上,对象跟踪可以使用其中存在的两种方法中的任何一种来完成。一种称为单对象跟踪 (SOT),另一种称为多对象跟踪 (MOT)。正如名称本身所理解的那样,单个对象跟踪是指在视频或一组帧中仅跟踪单个特定对象。类似地,多对象跟踪是指在同一视频或一组帧中同时跟踪多个对象。出于显而易见的原因,后者比前者复杂得多。MOT 的主要困难在于要跟踪的多个对象相互之间的交互。因此,SOT 模型不能直接应用于 MOT 并导致准确性较差。

对象跟踪最近已广泛用于监视、安全、交通监控、异常检测、机器人视觉和视觉跟踪。视觉跟踪是一个令人兴奋的应用程序,无需将视频的其余部分输入算法即可估计视频中对象的未来位置。它可以被认为是展望未来。

对象跟踪的难点

尽管是一种有益的方法,但由于训练对象跟踪模型的关键障碍之一是训练和跟踪速度,因此并非每个市场和/或流程都能负担得起执行对象跟踪。预计并需要跟踪算法在几分之一秒内以高精度检测和定位视频中的对象。由于在任何情况下都有各种各样的背景干扰,这种检测速度可能会不由自主地被显着篡改。目标跟踪的另一个重大困难是空间尺度的变化。对象可以以各种大小和方向出现在图像(或视频)中。

对象跟踪的另一个问题,也是对象检测和识别中的一个重要问题,是遮挡。遮挡是指多个对象靠得太近以至于它们似乎合并在一起。这会使计算机混淆,认为合并的对象是单个对象,或者只是错误地识别了对象。

遮遮掩掩的
遮挡示例

除此之外,还有几个问题给对象跟踪带来了困难,例如交叉后身份切换、运动模糊、视点变化、背景中相似对象的混乱、低分辨率和光照变化。


对象跟踪方法

如何使用OpenCV实现对象跟踪?从现在开始,已经开发了许多对象跟踪技术,一些用于 SOT,一些用于 MOT,一些用于两者。这些技术包括经典的基于计算机视觉的架构和基于深度学习的架构。最著名的对象跟踪方法和架构如下。

基于 OpenCV 的对象跟踪

OpenCV实现对象跟踪示例:使用 OpenCV 进行对象跟踪是一种在该领域广泛使用的流行方法。OpenCV 有许多专门为对象跟踪而设计的内置函数。OpenCV 中的一些对象跟踪器包括 MIL、CSRT、GOTURN 和 MediandFlow。选择特定的跟踪器取决于你尝试设计的应用程序。每个跟踪器都有其优点和缺点,在所有应用中都不需要单一类型的跟踪器。

MDNet

MDNet 是多域卷积神经网络跟踪器的缩写。它是基于卷积神经网络的最先进的视觉跟踪器。它也是VOT2015挑战赛的获胜者。它由多个共享层和特定领域层的分支组成。层堆栈底部的卷积层学习与域无关的特征,并且该特征提取在整个视频序列中共享。至于顶部的全连接层,它对每一帧都是唯一的,它学习特定于域的特征,即它所应用的视频序列的特定帧所固有的高级抽象特征。要了解有关 MODNet 的更多信息,请参阅学习用于视觉跟踪的多域卷积神经网络。

深度排序

DeepSort 是使用最广泛的对象跟踪架构之一。它使用 YOLO v3 来计算视频中对象周围的边界框。它是(简单在线和实时跟踪)SORT 算法的扩展。它使用来自 SORT 算法的卡尔曼滤波器,并使用称为 ReID 的识别模型将边界框与估计的对象轨迹联系起来。如果没有 ID 与轨道匹配,则为对象和轨道分配一个新 ID。DeepSort 允许通过更长时间的遮挡来跟踪对象。要进一步了解 DeepSort,请访问具有深度关联度量的简单在线和实时跟踪 。关于算法的实现,请参见其GitHub 存储库 。

ROLO

OpenCV如何实现对象跟踪?使用长短期记忆 (LSTM) 网络和卷积神经网络进行对象跟踪。该方法的一个著名例子是 ROLO,它代表 Recurrent YOLO。You Only Look Once (YOLO) 是非常著名的物体检测和识别算法。ROLO 使用 YOLO 进行对象检测,使用 LSTM 来估计对象的轨迹。借助 LSTM 在空间和时间上的回归能力,ROLO 可以将一系列高级视觉特征直接解释为跟踪对象的坐标。

除了上述方法之外,还开发了许多其他方法用于对象跟踪。在本文中,我们将深入探讨使用 OpenCV 进行对象跟踪的过程。


什么是 OpenCV?

OpenCV 是一个著名的开源库,主要用于各种计算机视觉应用程序。它也被广泛应用于机器学习、深度学习和图像处理。它有助于处理包含图像和视频的数据。从今天起,OpenCV 已被用于多个主流应用,包括对象检测和识别、自动驾驶汽车和机器人、自动化监控、异常检测、视频和图像搜索检索、医学图像分析和对象跟踪。它还可以与其他库集成,可以处理 NumPy 等库的数组结构。从功能和扩展的角度来看,它都是一个广泛的库;除了拥有庞大的函数和算法工具箱;它不仅支持 Python,还支持 C、C++ 和 Java。而且,

如今,作为计算机视觉库的 OpenCV 大部分时间用于人工智能及其现代应用程序,包括图像和视频等视觉数据。各种基于卷积神经网络的架构都需要 OpenCV 的支持来进行预处理和后处理。要了解有关 OpenCV 的更多信息,请参阅我们对让你开始使用计算机视觉的基本 OpenCV 函数的研究 。


OpenCV如何用于对象跟踪?

如何使用OpenCV实现对象跟踪?OpenCV 提供了许多为对象跟踪而明确开发的预构建算法。以下跟踪器是 OpenCV 中可用的跟踪器:

提升追踪器:

BOOSTING 跟踪器基于机器学习的 AdaBoost 算法。分类器将在运行时对要跟踪的对象的正面和负面示例进行学习学习。它已经十多年了。它很慢并且效果不佳,即使是针对一些相对更肤浅的数据也是如此。

军用追踪器:

它在概念上类似于 BOOSTING 跟踪器,唯一的区别是它不仅使用对象的当前位置作为分类器的正面示例,还查看事物邻域的一小部分。MIL 跟踪器比 BOOSTING 具有更好的准确性,但它在报告失败方面做得很差。

KCF追踪器:

它代表Kernelized Correlation Filters。KCF 建立在一个概念上,即单个 MIL 跟踪器包中的多个正例具有大的重叠区域。重叠为 KCF 跟踪器提供了一些直观的数学方法。

CSRT跟踪器:

CSRT,也称为具有通道和空间可靠性的判别相关滤波器 (DCF-CSR),它使用空间可靠性图将滤波器调整到所选帧的一部分进行跟踪。这有助于定位感兴趣的对象。它还为相对较低的 fps (25 fps) 提供高精度。

中值流量跟踪器:

该跟踪器实时跟踪对象的向前和向后位移,并测量两个轨迹之间的误差和差异。最小化此错误使其能够检测跟踪失败并选择最可靠的轨迹。

顶级域名追踪器:

它代表跟踪、学习和检测。该跟踪器逐帧跟踪对象并定位其从先前跟踪中学到的位置,并在必要时同时校正跟踪器。

莫斯追踪器:

它代表平方误差的最小输出总和。它使用自适应相关进行跟踪,输出稳定的相关滤波器。它对缩放、姿势、非刚性变形和光照变化具有鲁棒性。它还可以处理遮挡,并可以在对象重新出现时立即恢复跟踪。但在绩效规模上,它落后于基于深度收益的 GOTURN。

GOTURN 追踪器:

这是唯一基于深度学习方法的跟踪器。它是使用卷积神经网络开发的。它的准确性在于它对变形、光照变化和视点变化具有鲁棒性;同时,缺点是不能很好地处理遮挡。


Python OpenCV实现对象跟踪示例

OpenCV如何实现对象跟踪?既然我们已经浏览了有关在 OpenCV 中专门实现的对象跟踪的所有基本概念,让我们转到本文的编码部分。

我们将分部分构建脚本,但你可以在 GitHub 上访问完整代码 。

安装依赖

在我们开始编写代码之前,你需要在 Python 环境中安装一些先决条件。你需要安装该opencv-contrib-python软件包。

pip install opencv-contrib-python

设置跟踪器。

import cv2
import sys

(major_ver, minor_ver, subminor_ver) = (cv2.__version__).split('.')
 
if __name__ == '__main__' :
 
    # Set up tracker.
    # Instead of CSRT, you can also use
 
    tracker_types = ['BOOSTING', 'MIL','KCF', 'TLD', 'MEDIANFLOW', 'GOTURN', 'MOSSE', 'CSRT']
    tracker_type = tracker_types[7]
 
    if int(minor_ver) < 3:
        tracker = cv2.Tracker_create(tracker_type)
    else:
        if tracker_type == 'BOOSTING':
            tracker = cv2.TrackerBoosting_create()
        elif tracker_type == 'MIL':
            tracker = cv2.TrackerMIL_create()
        elif tracker_type == 'KCF':
            tracker = cv2.TrackerKCF_create()
        elif tracker_type == 'TLD':
            tracker = cv2.TrackerTLD_create()
        elif tracker_type == 'MEDIANFLOW':
            tracker = cv2.TrackerMedianFlow_create()
        elif tracker_type == 'GOTURN':
             tracker = cv2.TrackerGOTURN_create()
        elif tracker_type == 'MOSSE':
            tracker = cv2.TrackerMOSSE_create()
        elif tracker_type == "CSRT":
            tracker = cv2.TrackerCSRT_create()

cv2.version函数返回安装在你的环境中的 OpenCV 库的版本号。在创建跟踪器对象之前必须进行此检查。这是因为任何低于 3 的 OpenCV 版本都有不同的模块来创建特定类型的跟踪器。我们首先将八个跟踪器的名称保存在一个列表中。然后我们检查我们正在使用的 OpenCV 版本,然后根据版本号创建跟踪器对象。

捕获视频输入

# Read video
video = cv2.VideoCapture("input.mp4")
#video = cv2.VideoCapture(0) # for using CAM

# Exit if video not opened.
if not video.isOpened():
  print("Could not open video")
  sys.exit()

# Read first frame.
ok, frame = video.read()
if not ok:
  print ('Cannot read video file')
  sys.exit()

VideoCapture 类可用于从与你的机器集成的网络摄像头或保存在本地设备中的视频文件捕获视频文件。在第 2 行的 VideoCapture 参数中给出视频的路径。如果你想使用网络摄像头进行跟踪,请在第二行注释并取消对第三行的注释。我们进一步进行了一些检查,以查看视频文件是否正常工作。

创建边界框并初始化跟踪器

# Define an initial bounding box
bbox = (287, 23, 86, 320)

# Uncomment the line below to select a different bounding box
bbox = cv2.selectROI(frame, False)

# Initialize tracker with first frame and bounding box
ok = tracker.init(frame, bbox)

如何使用OpenCV实现对象跟踪?我们在视频中定义了一个初始的随机边界框,或者我们可以选择一个我们自己选择的边界框。这个边界框将包含我们要跟踪的对象。

用鼠标选择要查找的图像区域
用鼠标选择要跟踪的图像区域

OpenCV如何实现对象跟踪:启动跟踪器并查看输出

while True:
     # Read a new frame
     ok, frame = video.read()
     if not ok:
         break
      
     # Start timer
     timer = cv2.getTickCount()

     # Update tracker
     ok, bbox = tracker.update(frame)

     # Calculate Frames per second (FPS)
     fps = cv2.getTickFrequency() / (cv2.getTickCount() - timer);

     # Draw bounding box
     if ok:
         # Tracking success
         p1 = (int(bbox[0]), int(bbox[1]))
         p2 = (int(bbox[0] + bbox[2]), int(bbox[1] + bbox[3]))
         cv2.rectangle(frame, p1, p2, (255,0,0), 2, 1)
     else :
         # Tracking failure
         cv2.putText(frame, "Tracking failure detected", (100,80), cv2.FONT_HERSHEY_SIMPLEX, 0.75,(0,0,255),2)

     # Display tracker type on frame
     cv2.putText(frame, tracker_type + " Tracker", (100,20), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (50,170,50),2);
  
     # Display FPS on frame
     cv2.putText(frame, "FPS : " + str(int(fps)), (100,50), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (50,170,50), 2);
     # Display result
     cv2.imshow("Tracking", frame)

     # Exit if ESC pressed
     if cv2.waitKey(1) & 0xFF == ord('q'): # if press SPACE bar
         break

 video.release()
 cv2.destroyAllWindows()

OpenCV实现对象跟踪示例解析:我们首先阅读正在播放的视频的每一帧。我们启动计时器并使用跟踪器来估计视频中物体的轨迹。我们使用跟踪器的估计轨迹来绘制感兴趣对象周围的边界框。程序永远继续,等待空格键被按下;只要按下空格键,while 循环就会中断,并且跟踪停止。

CSRT追踪器在运行
OpenCV实现对象跟踪示例:CSRT 跟踪器在运行

结论

如何使用OpenCV实现对象跟踪?对象跟踪是许多应用程序的宝贵工具,尤其是计算机视觉和人工智能。有几种工具可用于对象跟踪;OpenCV 就是其中之一。OpenCV 有几个专门为对象跟踪而开发的内置算法。我们可以使用这些预先训练好的算法来跟踪我们自己选择的对象。每种算法都有其优点和缺点。

木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: