Advertisement

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

阅读量:

由极市、机器之心和中科创达联合举办的“2018计算机视觉最具潜力开发者榜单”评选活动,现已接受报名,杨强教授、俞扬教授等大牛嘉宾亲自评审,高通、中科创达、微众银行等大力支持,丰厚奖励,丰富资源,千万渠道,助力您的计算机视觉工程化能力认证,提升个人价值及算法变现。极市与您一起定义自己,发现未来~点击阅读原文即可报名~

原文 :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 实现的单目标追踪器的基本原理。

1.用 OpenCV 实现目标追踪

2.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 import print_functionimport sysimport cv2from random import randinttrackerTypes = ['BOOSTING', 'MIL', 'KCF','TLD', 'MEDIANFLOW', 'GOTURN', 'MOSSE', 'CSRT']def createTrackerByName(trackerType): # Create a tracker based on tracker name if trackerType == trackerTypes[0]: tracker = cv2.TrackerBoosting_create() elif trackerType == trackerTypes[1]: tracker = cv2.TrackerMIL_create() elif trackerType == trackerTypes[2]: tracker = cv2.TrackerKCF_create() elif trackerType == trackerTypes[3]: tracker = cv2.TrackerTLD_create() elif trackerType == trackerTypes[4]: tracker = cv2.TrackerMedianFlow_create() elif trackerType == trackerTypes[5]: tracker = cv2.TrackerGOTURN_create() elif trackerType == trackerTypes[6]: tracker = cv2.TrackerMOSSE_create() elif trackerType == trackerTypes[7]: tracker = cv2.TrackerCSRT_create() else: tracker = None print('Incorrect tracker name') print('Available trackers are:') for t in trackerTypes: print(t) return tracker

C++

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

#include #include using namespace cv;using namespace std;vector trackerTypes = {"BOOSTING", "MIL", "KCF", "TLD", "MEDIANFLOW", "GOTURN", "MOSSE", "CSRT"}; // create tracker by namePtr createTrackerByName(string trackerType) { Ptr tracker; if (trackerType == trackerTypes[0]) tracker = TrackerBoosting::create(); else if (trackerType == trackerTypes[1]) tracker = TrackerMIL::create(); else if (trackerType == trackerTypes[2]) tracker = TrackerKCF::create(); else if (trackerType == trackerTypes[3]) tracker = TrackerTLD::create(); else if (trackerType == trackerTypes[4]) tracker = TrackerMedianFlow::create(); else if (trackerType == trackerTypes[5]) tracker = TrackerGOTURN::create(); else if (trackerType == trackerTypes[6]) tracker = TrackerMOSSE::create(); else if (trackerType == trackerTypes[7]) tracker = TrackerCSRT::create(); else { cout <::iterator it = trackerTypes.begin() ; it != trackerTypes.end(); ++it) std::cout <

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

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

1.视频的一帧

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

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

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

Python

Set video to load videoPath = "videos/run.mp4" # Create a video capture object to read videos cap = cv2.VideoCapture(videoPath) # Read first frame success, frame = cap.read() # quit if unable to read the video file if not success: print('Failed to read video') sys.exit(1)

C++

// set default values for tracking algorithm and video string videoPath = "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 <> frame;

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

接下来,我们需要在第一帧中定位我们想要追踪的物体。位置是一个简单的边界框。OpenCV 提供了一个叫做 selectROI 的功能,它可以弹出一个 GUI 来选择边界框(也叫做感兴趣的区域(ROI))。在C++版本中,selectROI允许你得到多个边界框,但在 Python 版本中,它会只返回一个边界框。所以,在 Python 版本中,我们需要一个循环来得到多个边界框。

对于每个目标,我们还会选择随机的颜色来显示边界框。下面就是实现代码。

Python

Select boxesbboxes = []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 objectswhile True: # 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 breakprint('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 cornerbool showCrosshair = true;bool fromCenter = false;cout < colors; getRandomColors(colors, bboxes.size());

getRandomColors 函数相当简单

// Fill the vector with random colorsvoid getRandomColors(vector& colors, int numColors){ RNG rng(0); for(int i=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 typetrackerType = "CSRT" # Create MultiTracker objectmultiTracker = cv2.MultiTracker_create()# Initialize MultiTrackerfor bbox in bboxes: multiTracker.add(createTrackerByName(trackerType), frame, bbox)

C++

// Specify the tracker typestring trackerType = "CSRT";// Create multitrackerPtrmultiTracker = cv::MultiTracker::create();// Initialize multitrackerfor(int i=0; i < bboxes.size(); i++) multiTracker->add(createTrackerByName(trackerType), frame, Rect2d(bboxes[i]));

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

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

python

Process video and track objectswhile cap.isOpened(): success, frame = cap.read() if not success: break # get updated location of objects in subsequent frames success, boxes = multiTracker.update(frame) # draw tracked objects for i, newbox in enumerate(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 if cv2.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; }

推荐阅读

杨强教授、俞扬教授等大牛嘉宾评审团,万元大奖,丰富资源,助力您的计算机视觉工程化能力认证,点击阅读原文即可报名“2018计算机视觉最具潜力开发者榜单”~

全部评论 (0)

还没有任何评论哟~