python如何使用OpenCV实现多目标跟踪


本篇内容介绍了“python如何使用OpenCV实现多目标跟踪”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

1 背景介绍

让我们探讨一下跟踪有用的几个原因:

  • 首先,当在视频帧中检测到多个对象(比如人)时,跟踪有助于跨帧确定对象的身份。

  • 其次,在某些情况下,目标检测可能会失败,但仍可能跟踪对象,因为跟踪会考虑前一帧中对象的位置和外观。

  • 第三,一些跟踪算法非常快,因为它们进行本地搜索而不是全局搜索。因此,我们可以通过每第n帧执行目标检测并在中间帧中跟踪对象来为我们的系统获得非常高的性能。

那么,为什么不在第一次检测后无限期地跟踪对象呢?跟踪算法有时可能会丢失其正在跟踪的对象。例如,当对象的运动太大时,跟踪算法可能无法跟上。通常会在目标跟踪一段时间后再次目标检测。

在本教程中,我们将只关注跟踪部分。我们要跟踪的对象将通过指定它们周围的边界框来获取。

2 基于MultiTracker的多目标跟踪

OpenCV中的多目标跟踪器MultiTracker类提供了多目标跟踪的实现。但是这只是一个初步的实现,因为它只处理跟踪对象,而不对被跟踪对象进行任何优化。

2.1 创建单个对象跟踪器

多对象跟踪器只是单个对象跟踪器的集合。我们首先定义一个将跟踪器类型作为输入并创建跟踪器对象的函数。

OpenCV有8种不同的跟踪器类型:BOOSTING,MIL,KCF,TLD,MEDIANFLOW,GOTURN,MOSSE,CSRT。本文不使用GOTURN跟踪器。一般我们先给定跟踪器类的名称,再返回单跟踪器对象,然后建立多跟踪器类。

C++代码:

vector<string>trackerTypes={"BOOSTING","MIL","KCF","TLD","MEDIANFLOW","GOTURN","MOSSE","CSRT"};/***@briefCreateaTrackerByNameobject根据设定的类型初始化跟踪器**@paramtrackerType*@returnPtr<Tracker>*/Ptr<Tracker>createTrackerByName(stringtrackerType){Ptr<Tracker>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<<"Incorrecttrackername"<<endl;cout<<"Availabletrackersare:"<<endl;for(vector<string>::iteratorit=trackerTypes.begin();it!=trackerTypes.end();++it){std::cout<<""<<*it<<endl;}}returntracker;}

python代码:

from__future__importprint_functionimportsysimportcv2fromrandomimportrandinttrackerTypes=['BOOSTING','MIL','KCF','TLD','MEDIANFLOW','GOTURN','MOSSE','CSRT']defcreateTrackerByName(trackerType):#CreateatrackerbasedontrackernameiftrackerType==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=Noneprint('Incorrecttrackername')print('Availabletrackersare:')fortintrackerTypes:print(t)returntracker
2.2 读取视频的第一帧

多对象跟踪器需要两个输入即一个视频帧和我们想要跟踪的所有对象的位置(边界框)。

给定此信息,跟踪器在所有后续帧中跟踪这些指定对象的位置。在下面的代码中,我们首先使用VideoCapture类加载视频并读取第一帧。稍后将使用它来初始化MultiTracker。

C++代码:

//Settrackertype.Changethistotrydifferenttrackers.选择追踪器类型stringtrackerType=trackerTypes[6];//setdefaultvaluesfortrackingalgorithmandvideo视频读取stringvideoPath="video/run.mp4";//InitializeMultiTrackerwithtrackingalgo边界框vector<Rect>bboxes;//createavideocaptureobjecttoreadvideos读视频cv::VideoCapturecap(videoPath);Matframe;//quitifunabletoreadvideofileif(!cap.isOpened()){cout<<"Erroropeningvideofile"<<videoPath<<endl;return-1;}//readfirstframe读第一帧cap>>frame;

python代码:

#SetvideotoloadvideoPath="video/run.mp4"#Createavideocaptureobjecttoreadvideoscap=cv2.VideoCapture(videoPath)#Readfirstframesuccess,frame=cap.read()#quitifunabletoreadthevideofileifnotsuccess:print('Failedtoreadvideo')sys.exit(1)
2.3 在第一帧中确定我们跟踪的对象

接下来,我们需要在第一帧中找到我们想要跟踪的对象。OpenCV提供了一个名为selectROIs的函数,它弹出一个GUI来选择边界框(也称为感兴趣区域(ROI))。在C++版本中可以通过selectROIs允许您获取多个边界框,但在Python版本中,只能通过selectROI获得一个边界框。因此,在Python版本中,我们需要一个循环来获取多个边界框。对于每个对象,我们还选择随机颜色来显示边界框。selectROI函数步骤为先在图像上画框,然后按ENTER确定完成画框画下一个框。按ESC退出画框开始执行程序

C++代码:

//Getboundingboxesforfirstframe//selectROI'sdefaultbehaviouristodrawboxstartingfromthecenter//whenfromCenterissettofalse,youcandrawboxstartingfromtopleftcornerboolshowCrosshair=true;boolfromCenter=false;cout&lt;&lt;"\n==========================================================\n";cout&lt;&lt;"OpenCVsayspressctocancelobjectsselectionprocess"&lt;&lt;endl;cout&lt;&lt;"Itdoesn'twork.PressEscapetoexitselectionprocess"&lt;&lt;endl;cout&lt;&lt;"\n==========================================================\n";cv::selectROIs("MultiTracker",frame,bboxes,showCrosshair,fromCenter);//quitiftherearenoobjectstotrackif(bboxes.size()&lt;1)return0;vector&lt;Scalar&gt;colors;getRandomColors(colors,bboxes.size());
//FillthevectorwithrandomcolorsvoidgetRandomColors(vector<Scalar>&colors,intnumColors){RNGrng(0);for(inti=0;i<numColors;i++)colors.push_back(Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255)));}

python代码:

##Selectboxesbboxes=[]colors=[]#OpenCV'sselectROIfunctiondoesn'tworkforselectingmultipleobjectsinPython#SowewillcallthisfunctioninalooptillwearedoneselectingallobjectswhileTrue:#drawboundingboxesoverobjects#selectROI'sdefaultbehaviouristodrawboxstartingfromthecenter#whenfromCenterissettofalse,youcandrawboxstartingfromtopleftcornerbbox=cv2.selectROI('MultiTracker',frame)bboxes.append(bbox)colors.append((randint(0,255),randint(0,255),randint(0,255)))print("Pressqtoquitselectingboxesandstarttracking")print("Pressanyotherkeytoselectnextobject")k=cv2.waitKey(0)&amp;0xFFif(k==113):#qispressedbreakprint('Selectedboundingboxes{}'.format(bboxes))
2.4 初始化MultiTrackerer

到目前为止,我们已经读取了第一帧并获得了对象周围的边界框。这是我们初始化多对象跟踪器所需的所有信息。我们首先创建一个MultiTracker对象,并添加你要跟踪目标数的单个对象跟踪器。在此示例中,我们使用CSRT单个对象跟踪器,但您可以通过将下面的trackerType变量更改为本文开头提到的8个跟踪器时间之一来尝试其他跟踪器类型。该CSRT跟踪器是不是最快的,但它产生在我们尝试很多情况下,最好的结果。

您也可以使用包含在同一MultiTracker中的不同跟踪器,但当然,它没有多大意义。能用的不多。CSRT精度最高,KCF速度精度综合最好,MOSSE速度最快。

MultiTracker类只是这些单个对象跟踪器的包装器。正如我们在上一篇文章中所知道的那样,使用第一帧和边界框初始化单个对象跟踪器,该边界框指示我们想要跟踪的对象的位置。MultiTracker将此信息传递给它内部包装的单个目标跟踪器。

C++代码:

//Createmultitracker创建多目标跟踪类Ptr&lt;MultiTracker&gt;multiTracker=cv::MultiTracker::create();//initializemultitracker初始化for(inti=0;i&lt;bboxes.size();i++){multiTracker-&gt;add(createTrackerByName(trackerType),frame,Rect2d(bboxes[i]));}

python代码:

#SpecifythetrackertypetrackerType="CSRT"#CreateMultiTrackerobjectmultiTracker=cv2.MultiTracker_create()#InitializeMultiTrackerforbboxinbboxes:multiTracker.add(createTrackerByName(trackerType),frame,bbox)
2.5 更新MultiTracker和显示结果

最后,我们的MultiTracker准备就绪,我们可以在新的帧中跟踪多个对象。我们使用MultiTracker类的update方法在新帧中定位对象。每个被跟踪对象的每个边界框都使用不同的颜色绘制。

Update函数会返回true和false。update如果跟踪失败会返回false,C++代码加了判断,Python没有加。但是要注意的是update函数哪怕返回了false,也会继续更新函数,给出边界框。所以返回false,建议停止追踪。

C++代码:

while(cap.isOpened()){//getframefromthevideo逐帧处理cap>>frame;//stoptheprogramifreachedendofvideoif(frame.empty()){break;}//updatethetrackingresultwithnewframe更新每一帧boolok=multiTracker->update(frame);if(ok==true){cout<<"Trackingsuccess"<<endl;}else{cout<<"Trackingfailure"<<endl;}//drawtrackedobjects画框for(unsignedi=0;i<multiTracker->getObjects().size();i++){rectangle(frame,multiTracker->getObjects()[i],colors[i],2,1);}//showframeimshow("MultiTracker",frame);//quitonxbuttonif(waitKey(1)==27){break;}}

python代码:

#Processvideoandtrackobjectswhilecap.isOpened():success,frame=cap.read()ifnotsuccess:break#getupdatedlocationofobjectsinsubsequentframessuccess,boxes=multiTracker.update(frame)#drawtrackedobjectsfori,newboxinenumerate(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)#showframecv2.imshow('MultiTracker',frame)#quitonESCbuttonifcv2.waitKey(1)&amp;0xFF==27:#Escpressedbreak

3 结果和代码

就结果而言,多目标跟踪就是生成多个单目标跟踪器,每个单目标跟踪器跟踪一个对象。如果你想和目标检测结合,其中的对象框如果要自己设定,push一个Rect对象就行了。

总体来说精度和单目标跟踪器差不多,所耗时间差不多5到7倍,不同算法不同。

完整代码如下:

C++:

//Opencv_MultiTracker.cpp:此文件包含"main"函数。程序执行将在此处开始并结束。//#include"pch.h"#include<iostream>#include<opencv2/opencv.hpp>#include<opencv2/tracking.hpp>usingnamespacecv;usingnamespacestd;vector<string>trackerTypes={"BOOSTING","MIL","KCF","TLD","MEDIANFLOW","GOTURN","MOSSE","CSRT"};/***@briefCreateaTrackerByNameobject根据设定的类型初始化跟踪器**@paramtrackerType*@returnPtr<Tracker>*/Ptr<Tracker>createTrackerByName(stringtrackerType){Ptr<Tracker>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<<"Incorrecttrackername"<<endl;cout<<"Availabletrackersare:"<<endl;for(vector<string>::iteratorit=trackerTypes.begin();it!=trackerTypes.end();++it){std::cout<<""<<*it<<endl;}}returntracker;}/***@briefGettheRandomColorsobject随机涂色**@paramcolors*@paramnumColors*/voidgetRandomColors(vector<Scalar>&colors,intnumColors){RNGrng(0);for(inti=0;i<numColors;i++){colors.push_back(Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255)));}}intmain(intargc,char*argv[]){//Settrackertype.Changethistotrydifferenttrackers.选择追踪器类型stringtrackerType=trackerTypes[7];//setdefaultvaluesfortrackingalgorithmandvideo视频读取stringvideoPath="video/run.mp4";//InitializeMultiTrackerwithtrackingalgo边界框vector<Rect>bboxes;//createavideocaptureobjecttoreadvideos读视频cv::VideoCapturecap(videoPath);Matframe;//quitifunabletoreadvideofileif(!cap.isOpened()){cout<<"Erroropeningvideofile"<<videoPath<<endl;return-1;}//readfirstframe读第一帧cap>>frame;//drawboundingboxesoverobjects在第一帧内确定对象框/*先在图像上画框,然后按ENTER确定画下一个框。按ESC退出画框开始执行程序*/cout<<"\n==========================================================\n";cout<<"OpenCVsayspressctocancelobjectsselectionprocess"<<endl;cout<<"Itdoesn'twork.PressEsctoexitselectionprocess"<<endl;cout<<"\n==========================================================\n";cv::selectROIs("MultiTracker",frame,bboxes,false);//自己设定对象的检测框//x,y,width,height//bboxes.push_back(Rect(388,155,30,40));//bboxes.push_back(Rect(492,205,50,80));//quitiftherearenoobjectstotrack如果没有选择对象if(bboxes.size()<1){return0;}vector<Scalar>colors;//给各个框涂色getRandomColors(colors,bboxes.size());//Createmultitracker创建多目标跟踪类Ptr<MultiTracker>multiTracker=cv::MultiTracker::create();//initializemultitracker初始化for(inti=0;i<bboxes.size();i++){multiTracker->add(createTrackerByName(trackerType),frame,Rect2d(bboxes[i]));}//processvideoandtrackobjects开始处理图像cout<<"\n==========================================================\n";cout<<"Startedtracking,pressESCtoquit."<<endl;while(cap.isOpened()){//getframefromthevideo逐帧处理cap>>frame;//stoptheprogramifreachedendofvideoif(frame.empty()){break;}//updatethetrackingresultwithnewframe更新每一帧boolok=multiTracker->update(frame);if(ok==true){cout<<"Trackingsuccess"<<endl;}else{cout<<"Trackingfailure"<<endl;}//drawtrackedobjects画框for(unsignedi=0;i<multiTracker->getObjects().size();i++){rectangle(frame,multiTracker->getObjects()[i],colors[i],2,1);}//showframeimshow("MultiTracker",frame);//quitonxbuttonif(waitKey(1)==27){break;}}waitKey(0);return0;}

Python:

from__future__importprint_functionimportsysimportcv2fromrandomimportrandinttrackerTypes=['BOOSTING','MIL','KCF','TLD','MEDIANFLOW','GOTURN','MOSSE','CSRT']defcreateTrackerByName(trackerType):#CreateatrackerbasedontrackernameiftrackerType==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=Noneprint('Incorrecttrackername')print('Availabletrackersare:')fortintrackerTypes:print(t)returntrackerif__name__=='__main__':print("DefaulttrackingalgoritmisCSRT\n""Availabletrackingalgorithmsare:\n")fortintrackerTypes:print(t)trackerType="CSRT"#SetvideotoloadvideoPath="video/run.mp4"#Createavideocaptureobjecttoreadvideoscap=cv2.VideoCapture(videoPath)#Readfirstframesuccess,frame=cap.read()#quitifunabletoreadthevideofileifnotsuccess:print('Failedtoreadvideo')sys.exit(1)##Selectboxesbboxes=[]colors=[]#OpenCV'sselectROIfunctiondoesn'tworkforselectingmultipleobjectsinPython#SowewillcallthisfunctioninalooptillwearedoneselectingallobjectswhileTrue:#drawboundingboxesoverobjects#selectROI'sdefaultbehaviouristodrawboxstartingfromthecenter#whenfromCenterissettofalse,youcandrawboxstartingfromtopleftcornerbbox=cv2.selectROI('MultiTracker',frame)bboxes.append(bbox)colors.append((randint(64,255),randint(64,255),randint(64,255)))print("Pressqtoquitselectingboxesandstarttracking")print("Pressanyotherkeytoselectnextobject")k=cv2.waitKey(0)&amp;0xFFif(k==113):#qispressedbreakprint('Selectedboundingboxes{}'.format(bboxes))##InitializeMultiTracker#Therearetwowaysyoucaninitializemultitracker#1.tracker=cv2.MultiTracker("CSRT")#Allthetrackersaddedtothismultitracker#willuseCSRTalgorithmasdefault#2.tracker=cv2.MultiTracker()#Nodefaultalgorithmspecified#InitializeMultiTrackerwithtrackingalgo#Specifytrackertype#CreateMultiTrackerobjectmultiTracker=cv2.MultiTracker_create()#InitializeMultiTrackerforbboxinbboxes:multiTracker.add(createTrackerByName(trackerType),frame,bbox)#Processvideoandtrackobjectswhilecap.isOpened():success,frame=cap.read()ifnotsuccess:break#getupdatedlocationofobjectsinsubsequentframessuccess,boxes=multiTracker.update(frame)#drawtrackedobjectsfori,newboxinenumerate(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)#showframecv2.imshow('MultiTracker',frame)#quitonESCbuttonifcv2.waitKey(1)&amp;0xFF==27:#Escpressedbreak

“python如何使用OpenCV实现多目标跟踪”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注主机评测网网站,小编将为大家输出更多高质量的实用文章!


上一篇:python高阶函数functools模块如何使用

下一篇:Python的PIP如何使用


Copyright © 2002-2019 测速网 https://www.inhv.cn/ 皖ICP备2023010105号 城市 地区 街道
温馨提示:部分文章图片数据来源与网络,仅供参考!版权归原作者所有,如有侵权请联系删除!
热门搜索