Advertisement

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

阅读量:

原标题:多目标追踪器:用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)下载喔~返回搜狐,查看更多

责任编辑:

全部评论 (0)

还没有任何评论哟~