原标题:多目标追踪器:用OpenCV实现多目标追踪(C++/Python)

MultiTracker : Multiple Object Tracking using OpenCV (C++/Python)

翻译 | 燕婕 校对 | 酱番梨 整理 | 菠萝妹

https://www.learnopencv.com/multitracker-multiple-object-tracking-using-opencv-c-python/

在本文中,我们将谈到如何用 OpenCV 的多目标追踪API,通过使用 MultiTracker 类来实现。我们将分享用 C++ 和用 Python 实现的代码。

在我们深入探讨细节之前,请检查下边列出来的之前的关于目标追踪的帖子,理解用 OpenCV 实现的单目标追踪器的基本原理。

用 OpenCV 实现目标追踪

GOTURN: 基于深度学习的目标追踪

为什么我们需要多目标追踪

大多数计算机视觉和机器学习的入门者都学习目标识别。如果你是一个初学者,你可能会思考我们到底为什么需要目标追踪。我们为什么不能只是在每一帧检测目标?

然我们来探索追踪很有用的几个原因。

首先,当视频的一帧中有多个目标(这里指人)时,追踪帮助建立帧之间的目标同一性。

第二,在一些情况下,目标检测可能失败但是仍有可能追踪目标,因为追踪考虑到目标在前一帧中的位置和外观。

第三,一些追踪算法是非常快的,因为他们做局部搜索而非全局搜索。所以通过每隔 n 帧做目标检测并在中间的帧做目标追踪,我们的系统可以获得很高的帧速。

所以,为什么不在第一次检测后无限期地跟踪这个对象呢?一个追踪算法有时可能会丢掉它所追踪的目标的轨迹。例如,当目标的移动太大,一个追踪算法可能不能保持一直追踪。所以现实中许多应用将检测和追踪一起使用。

在这个教程中,我们将只关注追踪这部分,我们将通过在对象周围放置一个边界框来指定想要跟踪的对象。

多目标追踪:OpenCV 的多目标追踪器

OpenCV 中的 MultiTracker 类提供了多目标追踪的实施方法。他是一个简单的实施方法因为他独立地处理被追踪的目标,不需要在多个被追踪对象之间做任何优化。

让我们一步步查看代码,学习我们如何用 OpenCV 的多目标追踪 API。

下载代码

为了能容易地跟着这个教程学习,请点击下面的按钮,下载代码。代码是免费的!

代码下载链接:https://bigvisionllc.leadpages.net/leadbox/143948b73f72a2%3A173c9390c346dc/5649050225344512/

第一步:创建单目标追踪器

一个多目标追踪器是由一系列简单的单目标追踪器组成的。一开始,我们先定义一个函数,用追踪器类型作为输入并创建一个追踪器对象。OpenCV 有八个不同的追踪器类型:BOOSTING, MTL, KCF, TLD, MEDIANFLOW, GOTURN, MOSSE, CSRT.

如果你想用 GOTURN 追踪器,请确保阅读这篇文章并下载caffe模型。

在下面的代码中,给出追踪器类别的名字,我们返回追踪器对象。这个追踪器会用于多目标追踪器。

Python

from__future__ importprint_function

importsys

importcv2

fromrandom importrandint

trackerTypes = ['BOOSTING', 'MIL', 'KCF','TLD', 'MEDIANFLOW', 'GOTURN', 'MOSSE', 'CSRT']

defcreateTrackerByName(trackerType):

# Create a tracker based on tracker name

iftrackerType == trackerTypes[0]:

tracker = cv2.TrackerBoosting_create()

eliftrackerType == trackerTypes[1]:

tracker = cv2.TrackerMIL_create()

eliftrackerType == trackerTypes[2]:

tracker = cv2.TrackerKCF_create()

eliftrackerType == trackerTypes[3]:

tracker = cv2.TrackerTLD_create()

eliftrackerType == trackerTypes[4]:

tracker = cv2.TrackerMedianFlow_create()

eliftrackerType == trackerTypes[5]:

tracker = cv2.TrackerGOTURN_create()

eliftrackerType == trackerTypes[6]:

tracker = cv2.TrackerMOSSE_create()

eliftrackerType == trackerTypes[7]:

tracker = cv2.TrackerCSRT_create()

else:

tracker = None

print('Incorrect tracker name')

print('Available trackers are:')

fort intrackerTypes:

print(t)

returntracker

C++

注意:除了需要 include opencv2 / opencv.hpp 之外,你还需要 include opencv2 / tracking.hpp 。

#include

#include

usingnamespacecv;

usingnamespacestd;

vector trackerTypes = {"BOOSTING", "MIL", "KCF", "TLD", "MEDIANFLOW", "GOTURN", "MOSSE", "CSRT"};

// create tracker by name

Ptr createTrackerByName(stringtrackerType)

{

Ptr tracker;

if(trackerType == trackerTypes[0])

tracker = TrackerBoosting::create();

elseif(trackerType == trackerTypes[1])

tracker = TrackerMIL::create();

elseif(trackerType == trackerTypes[2])

tracker = TrackerKCF::create();

elseif(trackerType == trackerTypes[3])

tracker = TrackerTLD::create();

elseif(trackerType == trackerTypes[4])

tracker = TrackerMedianFlow::create();

elseif(trackerType == trackerTypes[5])

tracker = TrackerGOTURN::create();

elseif(trackerType == trackerTypes[6])

tracker = TrackerMOSSE::create();

elseif(trackerType == trackerTypes[7])

tracker = TrackerCSRT::create();

else{

cout<< "Incorrect tracker name"<< endl;

cout<< "Available trackers are: "<< endl;

for(vector::iterator it = trackerTypes.begin() ; it != trackerTypes.end(); ++it)

std::cout<< " "<< *it << endl;

}

returntracker;

}

第二步:读取视频的第一帧

一个多目标追踪器需要两个输入

视频的一帧

你想要追踪的所有目标的位置(边界框)

给定这些信息,追踪器会在多有子序列帧中追踪这些特定目标的位置。

在下面的代码中,我们先用 VidoeCapture 类加载视频,读取第一帧。这一帧将会用于之后的 MultiTracker 的初始化。

Python

# Set video toload

videoPath = "videos/run.mp4"

# Create avideo capture object toreadvideos

cap = cv2.VideoCapture(videoPath)

# Read firstframe

success, frame = cap.read()

# quitifunable toreadthe video file

ifnot success:

print('Failed to read video')

sys.exit(1)

C++

// set default values for tracking algorithm and video

stringvideoPath = "videos/run.mp4";

// Initialize MultiTracker with tracking algo

vector bboxes;

// create a video capture object to read videos

cv::VideoCapture cap(videoPath);

Mat frame;

// quit if unabke to read video file

if(!cap.isOpened())

{

cout<< "Error opening video file "<< videoPath << endl;

return-1;

}

// read first frame

cap >> frame;

第三步:在第一帧中定位物体

接下来,我们需要在第一帧中定位我们想要追踪的物体。位置是一个简单的边界框。

OpenCV 提供了一个叫做 selectROI 的功能,它可以弹出一个 GUI 来选择边界框(也叫做感兴趣的区域(ROI))。

在C++版本中,selectROI允许你得到多个边界框,但在 Python 版本中,它会只返回一个边界框。所以,在 Python 版本中,我们需要一个循环来得到多个边界框。

对于每个目标,我们还会选择随机的颜色来显示边界框。

下面就是实现代码。

Python

## Select boxes

bboxes = []

colors = []

# OpenCV's selectROI function doesn't work for selecting multiple objects in Python

# So we will call this function in a loop till we are done selecting all objects

whileTrue:

# draw bounding boxes over objects

# selectROI's default behaviour is to draw box starting from the center

# when fromCenter is set to false, you can draw box starting from top left corner

bbox = cv2.selectROI('MultiTracker', frame)

bboxes.append(bbox)

colors.append((randint(0, 255), randint(0, 255), randint(0, 255)))

print("Press q to quit selecting boxes and start tracking")

print("Press any other key to select next object")

k = cv2.waitKey(0) & 0xFF

if(k == 113): # q is pressed

break

print('Selected bounding boxes {}'.format(bboxes))

C++

// Get bounding boxes for first frame

// selectROI's default behaviour is to draw box starting from the center

// when fromCenter is set to false, you can draw box starting from top left corner

boolshowCrosshair = true;

boolfromCenter = false;

cout<< "n==========================================================n";

cout<< "OpenCV says press c to cancel objects selection process"<< endl;

cout<< "It doesn't work. Press Escape to exit selection process"<< endl;

cout<< "n==========================================================n";

cv::selectROIs("MultiTracker", frame, bboxes, showCrosshair, fromCenter);

// quit if there are no objects to track

if(bboxes.size() < 1)

return0;

vector colors;

getRandomColors(colors, bboxes.size());

getRandomColors 函数相当简单

// Fill the vector with random colors

voidgetRandomColors(vector& colors, intnumColors)

{

RNG rng(0);

for(inti=0; i < numColors; i++)

colors.push_back(Scalar(rng.uniform(0,255), rng.uniform(0, 255), rng.uniform(0, 255)));

}

第三步:初始化多目标追踪器

直到目前,我们读到了第一帧并且得到了目标周围的边界框。这些是我们需要初始化多目标追踪器所需的全部信息。

我们首先创建一个 MuliTracker 对象并且增加和单个目标追踪器一样多的边界框。在这个例子中,我们用 CSRT 单目标追踪器,但是你尝试可以通过将 trackerTyper 变量改变为这篇文章一开始提到的8种追踪器中的一种,来尝试其使用他类型的追踪器。CSRT 追踪器不是最快的,但它在我们尝试的许多情况下都能生成最好的结果。

你可以用封装在同一个 MultiTracker 中的不同的追踪器,但是当然,这意义不大。

MultiTracker 类是一个简单的单目标追踪器的封装器。我们从前边的文章种知道,初始化单目标追踪器,我们需要视频第一帧和用来标定我们想要追踪的目标位置的边界框。多目标追踪器将这些信息传递给它内部封装的单目标追踪器。

Python

# Specify the tracker type

trackerType = "CSRT"

# Create MultiTracker object

multiTracker = cv2.MultiTracker_create()

# Initialize MultiTracker

forbbox inbboxes:

multiTracker.add(createTrackerByName(trackerType), frame, bbox)

C++

// Specify the tracker type

string trackerType = "CSRT";

// Create multitracker

PtrmultiTracker = cv::MultiTracker::create();

// Initialize multitracker

for(int i=0; i < bboxes.size(); i++)

multiTracker->add(createTrackerByName(trackerType), frame, Rect2d(bboxes[i]));

第四步:更新多目标追踪器并展示结果

最后,我们的多目标追踪器已经准备好了,我们可以在新的帧中追踪多个目标。我们用 MultiTracker 类中的 update 的方法来定位新一帧中的目标。每个用来追踪目标的边界框都用不同颜色来画。

python

# Process video and track objects

whilecap.isOpened():

success, frame = cap.read()

ifnot success:

break

# get updated location of objects in subsequent frames

success, boxes = multiTracker.update(frame)

# draw tracked objects

fori, newbox inenumerate(boxes):

p1 = (int(newbox[0]), int(newbox[1]))

p2 = (int(newbox[0] + newbox[2]), int(newbox[1] + newbox[3]))

cv2.rectangle(frame, p1, p2, colors[i], 2, 1)

# show frame

cv2.imshow('MultiTracker', frame)

# quit on ESC button

ifcv2.waitKey(1) & 0xFF== 27: # Esc pressed

break

C++

while(cap.isOpened())

{

// get frame from the video

cap >> frame;

// Stop the program if reached end of video

if(frame.empty()) break;

//Update the tracking result with new frame

multiTracker->update(frame);

// Draw tracked objects

for(unsigned i=0; igetObjects().size(); i++)

{

rectangle(frame, multiTracker->getObjects()[i], colors[i], 2, 1);

}

// Show frame

imshow("MultiTracker", frame);

// quit on x button

if(waitKey(1) == 27) break;

}

订阅 & 下载代码

如果你喜欢这篇文章并且你想要下载代码(C++ 和 Python)和这篇文章中用到的例子图片,请订阅我们。你还将收到免费的计算机视觉知道。我们会分享用C++/ Python写的 OpenCV 的教程和例子,还有计算机视觉和机器学习的算法和新闻。

戳链接:

http://www.gair.link/page/TextTranslation/1047

AI研习社每日更新精彩内容,点击文末【阅读原文】即可观看更多精彩内容:

悼念保罗·艾伦,除了他科技圈还有哪些大佬值得信仰?

如何开发多步空气污染时间序列预测的自回归预测模型

用 4 种卷积神经网络,轻松分类时尚图像

使用 SKIL 和 YOLO 构建产品级目标检测系统

很有启发性的25个开源机器学习项目

(http://www.gair.link/page/resources)下载喔~返回搜狐,查看更多

责任编辑:

python机器识别追踪_多目标追踪器:用OpenCV实现多目标追踪(C++/Python)相关推荐

  1. 如何成为python 数据分析师_如何七周成为数据分析师20:了解和掌握Python的函数...

    本文是<如何七周成为数据分析师>的第二十教程,如果想要了解写作初衷,可以先行阅读七周指南.温馨提示:如果您已经熟悉Python,大可不必再看这篇文章,或只挑选部分. Python之所以灵活 ...

  2. python简单目标检测代码_Python Opencv实现单目标检测的示例代码

    一 简介 目标检测即为在图像中找到自己感兴趣的部分,将其分割出来进行下一步操作,可避免背景的干扰.以下介绍几种基于opencv的单目标检测算法,算法总体思想先尽量将目标区域的像素值全置为1,背景区域全 ...

  3. 编程python自学课程_就算你是文科生,也能轻松自学编程——《Python 自学手册》正式上线...

    说起来也有趣,谁能想到我身为一个文科生,最后却走上了 Coder 的道路. 中学时候,我对物理就抱有深深的恐惧,它一度让我在高二年级分班的时候毅然决然地选择了文科:高考后录取的学校也是文科院校,似乎跟 ...

  4. python商业分析_科研进阶 | 纽约大学 | 商业分析、量化金融:基于Python的商业分析工具...

    科研进阶 | 纽约大学 | 商业分析.量化金融:基于Python的商业分析工具(8.22开课)​mp.weixin.qq.com 课题名称 = 基于Python的商业分析工具 = 项目背景 数据分析为 ...

  5. 业余学习python有用吗_对于那些不做编程工作的小伙伴来说,学习Python有什么用呢?...

    很多同学会说Python那么火,铺天盖地的都是他的广告,可是我的平时工作和学习又接触不到编程之类的东西,那来学习它又有什么用呢? 有没有这个必要呢?在此,小编对于有这种疑问的同学呢想对你们说,其实即便 ...

  6. python打包命令_三个你必须要记住的Pyinstaller打包命令——利用Python实现打包exe...

    /1 前言/ 嘿,各位小伙伴,晚上好呀,我相信各位小伙伴都是python的爱好者.也许我们不一定是专业的程序员,但是我们仍然可以通过代码提高我们的效率,尽量少加班,多陪陪媳妇.再不行,让代码替我们干着 ...

  7. 潭州教育可以学python爬虫吗?_什么是爬虫?其运行原理是什么?只有Python才可以吗?...

    爬虫是什么? 本文所说的爬虫不是自然界中的爬行动物,而是运行在网络中的一个自动处理信息的程序. 爬虫是一个程序,该程序利用网络请求(HTTP/HTTPS)进行数据的筛选和录入.因为网络信息维度很广泛, ...

  8. python server酱_面向回家编程!GitHub标星两万的quot;Python抢票神器”快用起来!...

    作者 |曹培信.池俊辉 来源 |公众号大数据文摘 盼望着,盼望着, 春节的脚步近了, 然而,每年到这个时候, 最难的, 莫过于一张回家的火车票. 据悉, 今年春运期间, 全国铁路发送旅客人次同比将增长 ...

  9. python低代码_几行代码搞定ML模型,低代码机器学习Python库正式开源

    PyCaret 库支持在「低代码」环境中训练和部署有监督以及无监督的机器学习模型,提升机器学习实验的效率. 想提高机器学习实验的效率,把更多精力放在解决业务问题而不是写代码上?低代码平台或许是个不错的 ...

  10. python脚本编写_【PyQGIS】编写用于处理框架(QGIS3)的Python脚本

    可以编写可通过QGIS中的Python控制台运行的独立pyqgis脚本.进行一些调整,即可使您的独立脚本通过处理框架运行.这具有几个优点.首先,获取用户输入和写入输出文件要容易得多,因为Process ...

最新文章

  1. 数学建模中的matlab实例,matlab数学建模实例
  2. E: Could not get lock /var/lib/dpkg/lock解决
  3. vb制作可输出函数的通用DLL---VB_DLL_Link用法
  4. MYSQL 表的修复(不断更新)
  5. 神经网络为什么需要随机初始化模型参数
  6. JAVA springboot ssm b2b2c多用户商城系统源码(三)SpringBoot用JdbcTemplates访问Mysql
  7. [Java] 蓝桥杯ADV-170 算法提高 数字黑洞
  8. 一步步构造自己的vue2.0+webpack环境
  9. python unpack_Python使用struct处理二进制(pack和unpack用法)
  10. python运算符手写笔记_Python笔记(四)-运算符
  11. 快解析:NAT移动版结合管家婆使用操作
  12. 如何屏蔽 iOS 软件自动更新,去除更新通知和标记
  13. 苹果企业开发者账号证书申请(保姆级)
  14. android USB OTG功能如何打开及实现
  15. ip关联是什么意思,亚马逊如何防止ip关联(ip关联过多是什么意思)
  16. 字符全角半角转换及特殊符号转换
  17. luckysheet实现在线编辑Excel
  18. 全国省市县三级级联SQL数据库内容
  19. 生活随记 - 上海普通百姓一个月的开销记录
  20. 技术、产业、人才三管齐下,数字人民币渐行渐近 | 产业区块链发展周报

热门文章

  1. 超级账本北京 MEET UP 在北京大学成功举办,这7位行业大咖究竟讲了啥?
  2. selenium打不开Ie浏览器的解决办法
  3. 数据流图、数据流程图、程序流程图的区别与联系
  4. 晨兴刘芹:避开同质化竞争 看好云适配技术创新
  5. windows注册表自定义添加右键菜单
  6. 2022 年卡塔尔世界杯冠军可能是谁?
  7. mel表达式_mel语言~`详解
  8. camera.swf java,ipcamera-for-android 手机变成IP Camera
  9. 【转】Java并发编程:并发容器之ConcurrentHashMap
  10. 一些软件所有版本下载地址 (第一期)