Merge pull request #300 from kurnianggoro:multitracker
commit
ffa6637b94
5 changed files with 592 additions and 0 deletions
@ -0,0 +1,145 @@ |
||||
/*----------------------------------------------
|
||||
* Usage: |
||||
* example_tracking_multitracker <video_name> [algorithm] |
||||
* |
||||
* example: |
||||
* example_tracking_multitracker Bolt/img/%04d.jpg |
||||
* example_tracking_multitracker faceocc2.webm KCF |
||||
* |
||||
* Note: after the OpenCV libary is installed, |
||||
* please re-compile this code with "HAVE_OPENCV" parameter activated |
||||
* to enable the high precission of fps computation |
||||
*--------------------------------------------------*/ |
||||
|
||||
/* after the OpenCV libary is installed
|
||||
* please uncomment the the line below and re-compile this code |
||||
* to enable high precission of fps computation |
||||
*/ |
||||
//#define HAVE_OPENCV
|
||||
|
||||
#include <opencv2/core/utility.hpp> |
||||
#include <opencv2/tracking.hpp> |
||||
#include <opencv2/videoio.hpp> |
||||
#include <opencv2/highgui.hpp> |
||||
#include <iostream> |
||||
#include <cstring> |
||||
#include <ctime> |
||||
|
||||
#ifdef HAVE_OPENCV |
||||
#include <opencv2/flann.hpp> |
||||
#endif |
||||
|
||||
#define RESET "\033[0m" |
||||
#define RED "\033[31m" /* Red */ |
||||
#define GREEN "\033[32m" /* Green */ |
||||
|
||||
using namespace std; |
||||
using namespace cv; |
||||
|
||||
int main( int argc, char** argv ){ |
||||
// show help
|
||||
if(argc<2){ |
||||
cout<< |
||||
" Usage: example_tracking_multitracker <video_name> [algorithm]\n" |
||||
" examples:\n" |
||||
" example_tracking_multitracker Bolt/img/%04d.jpg\n" |
||||
" example_tracking_multitracker faceocc2.webm MEDIANFLOW\n" |
||||
" \n" |
||||
" Note: after the OpenCV libary is installed,\n" |
||||
" please re-compile with the HAVE_OPENCV parameter activated\n" |
||||
" to enable the high precission of fps computation.\n" |
||||
<< endl; |
||||
return 0; |
||||
} |
||||
|
||||
// timer
|
||||
#ifdef HAVE_OPENCV |
||||
cvflann::StartStopTimer timer; |
||||
#else |
||||
clock_t timer; |
||||
#endif |
||||
|
||||
// for showing the speed
|
||||
double fps; |
||||
std::string text; |
||||
char buffer [50]; |
||||
|
||||
// set the default tracking algorithm
|
||||
std::string trackingAlg = "KCF"; |
||||
|
||||
// set the tracking algorithm from parameter
|
||||
if(argc>2) |
||||
trackingAlg = argv[2]; |
||||
|
||||
// create the tracker
|
||||
MultiTracker trackers(trackingAlg); |
||||
|
||||
// container of the tracked objects
|
||||
vector<Rect2d> objects; |
||||
|
||||
// set input video
|
||||
std::string video = argv[1]; |
||||
VideoCapture cap(video); |
||||
|
||||
Mat frame; |
||||
|
||||
// get bounding box
|
||||
cap >> frame; |
||||
selectROI("tracker",frame,objects); |
||||
|
||||
//quit when the tracked object(s) is not provided
|
||||
if(objects.size()<1) |
||||
return 0; |
||||
|
||||
// initialize the tracker
|
||||
trackers.add(frame,objects); |
||||
|
||||
// do the tracking
|
||||
printf(GREEN "Start the tracking process, press ESC to quit.\n" RESET); |
||||
for ( ;; ){ |
||||
// get frame from the video
|
||||
cap >> frame; |
||||
|
||||
// stop the program if no more images
|
||||
if(frame.rows==0 || frame.cols==0) |
||||
break; |
||||
|
||||
// start the timer
|
||||
#ifdef HAVE_OPENCV |
||||
timer.start(); |
||||
#else |
||||
timer=clock(); |
||||
#endif |
||||
|
||||
//update the tracking result
|
||||
trackers.update(frame); |
||||
|
||||
// calculate the processing speed
|
||||
#ifdef HAVE_OPENCV |
||||
timer.stop(); |
||||
fps=1.0/timer.value; |
||||
timer.reset(); |
||||
#else |
||||
timer=clock(); |
||||
trackers.update(frame); |
||||
timer=clock()-timer; |
||||
fps=(double)CLOCKS_PER_SEC/(double)timer; |
||||
#endif |
||||
|
||||
// draw the tracked object
|
||||
for(unsigned i=0;i<trackers.objects.size();i++) |
||||
rectangle( frame, trackers.objects[i], Scalar( 255, 0, 0 ), 2, 1 ); |
||||
|
||||
// draw the processing speed
|
||||
sprintf (buffer, "speed: %.0f fps", fps); |
||||
text = buffer; |
||||
putText(frame, text, Point(20,20), FONT_HERSHEY_PLAIN, 1, Scalar(255,255,255)); |
||||
|
||||
// show image with the tracked object
|
||||
imshow("tracker",frame); |
||||
|
||||
//quit on ESC button
|
||||
if(waitKey(1)==27)break; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,120 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp" |
||||
|
||||
namespace cv { |
||||
|
||||
// constructor
|
||||
MultiTracker::MultiTracker(const String& trackerType):defaultAlgorithm(trackerType){}; |
||||
|
||||
// destructor
|
||||
MultiTracker::~MultiTracker(){}; |
||||
|
||||
// add an object to be tracked, defaultAlgorithm is used
|
||||
bool MultiTracker::add(const Mat& image, const Rect2d& boundingBox){ |
||||
// quit if defaultAlgorithm has not been configured
|
||||
if(defaultAlgorithm==""){ |
||||
printf("Default algorithm was not defined!\n"); |
||||
return false; |
||||
} |
||||
|
||||
// add a new tracked object
|
||||
return add(defaultAlgorithm.c_str(), image, boundingBox); |
||||
}; |
||||
|
||||
// add a new tracked object
|
||||
bool MultiTracker::add( const String& trackerType, const Mat& image, const Rect2d& boundingBox ){ |
||||
// declare a new tracker
|
||||
Ptr<Tracker> newTracker = Tracker::create( trackerType ); |
||||
|
||||
// add the created tracker algorithm to the trackers list
|
||||
trackerList.push_back(newTracker); |
||||
|
||||
// add the ROI to the bounding box list
|
||||
objects.push_back(boundingBox); |
||||
|
||||
// initialize the created tracker
|
||||
return trackerList.back()->init(image, boundingBox); |
||||
}; |
||||
|
||||
// add a set of objects to be tracked
|
||||
bool MultiTracker::add(const String& trackerType, const Mat& image, std::vector<Rect2d> boundingBox){ |
||||
// status of the tracker addition
|
||||
bool stat=false; |
||||
|
||||
// add tracker for all input objects
|
||||
for(unsigned i =0;i<boundingBox.size();i++){ |
||||
stat=add(trackerType,image,boundingBox[i]); |
||||
if(!stat)break; |
||||
} |
||||
|
||||
// return the status
|
||||
return stat; |
||||
}; |
||||
|
||||
// add a set of object to be tracked, defaultAlgorithm is used.
|
||||
bool MultiTracker::add(const Mat& image, std::vector<Rect2d> boundingBox){ |
||||
// quit if defaultAlgorithm has not been configured
|
||||
if(defaultAlgorithm==""){ |
||||
printf("Default algorithm was not defined!\n"); |
||||
return false; |
||||
} |
||||
|
||||
return add(defaultAlgorithm.c_str(), image, boundingBox); |
||||
}; |
||||
|
||||
// update position of the tracked objects, the result is stored in internal storage
|
||||
bool MultiTracker::update( const Mat& image){ |
||||
for(unsigned i=0;i< trackerList.size(); i++){ |
||||
trackerList[i]->update(image, objects[i]); |
||||
} |
||||
return true; |
||||
}; |
||||
|
||||
// update position of the tracked objects, the result is copied to external variable
|
||||
bool MultiTracker::update( const Mat& image, std::vector<Rect2d> & boundingBox ){ |
||||
update(image); |
||||
boundingBox=objects; |
||||
return true; |
||||
}; |
||||
|
||||
} /* namespace cv */ |
@ -0,0 +1,184 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp" |
||||
|
||||
namespace cv { |
||||
void ROISelector::mouseHandler(int event, int x, int y, int flags, void *param){ |
||||
ROISelector *self =static_cast<ROISelector*>(param); |
||||
self->opencv_mouse_callback(event,x,y,flags,param); |
||||
} |
||||
|
||||
void ROISelector::opencv_mouse_callback( int event, int x, int y, int , void *param ){ |
||||
handlerT * data = (handlerT*)param; |
||||
switch( event ){ |
||||
// update the selected bounding box
|
||||
case EVENT_MOUSEMOVE: |
||||
if( data->isDrawing ){ |
||||
if(data->drawFromCenter){ |
||||
data->box.width = 2*(x-data->center.x)/*data->box.x*/; |
||||
data->box.height = 2*(y-data->center.y)/*data->box.y*/; |
||||
data->box.x = data->center.x-data->box.width/2.0; |
||||
data->box.y = data->center.y-data->box.height/2.0; |
||||
}else{ |
||||
data->box.width = x-data->box.x; |
||||
data->box.height = y-data->box.y; |
||||
} |
||||
} |
||||
break; |
||||
|
||||
// start to select the bounding box
|
||||
case EVENT_LBUTTONDOWN: |
||||
data->isDrawing = true; |
||||
data->box = cvRect( x, y, 0, 0 ); |
||||
data->center = Point2f((float)x,(float)y); |
||||
break; |
||||
|
||||
// cleaning up the selected bounding box
|
||||
case EVENT_LBUTTONUP: |
||||
data->isDrawing = false; |
||||
if( data->box.width < 0 ){ |
||||
data->box.x += data->box.width; |
||||
data->box.width *= -1; |
||||
} |
||||
if( data->box.height < 0 ){ |
||||
data->box.y += data->box.height; |
||||
data->box.height *= -1; |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
|
||||
Rect2d ROISelector::select(Mat img, bool fromCenter){ |
||||
return select("ROI selector", img, fromCenter); |
||||
} |
||||
|
||||
Rect2d ROISelector::select(const std::string& windowName, Mat img, bool showCrossair, bool fromCenter){ |
||||
|
||||
key=0; |
||||
|
||||
// set the drawing mode
|
||||
selectorParams.drawFromCenter = fromCenter; |
||||
|
||||
// show the image and give feedback to user
|
||||
imshow(windowName,img); |
||||
|
||||
// copy the data, rectangle should be drawn in the fresh image
|
||||
selectorParams.image=img.clone(); |
||||
|
||||
// select the object
|
||||
setMouseCallback( windowName, mouseHandler, (void *)&selectorParams ); |
||||
|
||||
// end selection process on SPACE (32) BACKSPACE (27) or ENTER (13)
|
||||
while(!(key==32 || key==27 || key==13)){ |
||||
// draw the selected object
|
||||
rectangle( |
||||
selectorParams.image, |
||||
selectorParams.box, |
||||
Scalar(255,0,0),2,1 |
||||
); |
||||
|
||||
// draw cross air in the middle of bounding box
|
||||
if(showCrossair){ |
||||
// horizontal line
|
||||
line( |
||||
selectorParams.image, |
||||
Point((int)selectorParams.box.x,(int)(selectorParams.box.y+selectorParams.box.height/2)), |
||||
Point((int)(selectorParams.box.x+selectorParams.box.width),(int)(selectorParams.box.y+selectorParams.box.height/2)), |
||||
Scalar(255,0,0),2,1 |
||||
); |
||||
|
||||
// vertical line
|
||||
line( |
||||
selectorParams.image, |
||||
Point((int)(selectorParams.box.x+selectorParams.box.width/2),(int)selectorParams.box.y), |
||||
Point((int)(selectorParams.box.x+selectorParams.box.width/2),(int)(selectorParams.box.y+selectorParams.box.height)), |
||||
Scalar(255,0,0),2,1 |
||||
); |
||||
} |
||||
|
||||
// show the image bouding box
|
||||
imshow(windowName,selectorParams.image); |
||||
|
||||
// reset the image
|
||||
selectorParams.image=img.clone(); |
||||
|
||||
//get keyboard event
|
||||
key=waitKey(1); |
||||
} |
||||
|
||||
|
||||
return selectorParams.box; |
||||
} |
||||
|
||||
void ROISelector::select(const std::string& windowName, Mat img, std::vector<Rect2d> & boundingBox, bool fromCenter){ |
||||
std::vector<Rect2d> box; |
||||
Rect2d temp; |
||||
key=0; |
||||
|
||||
// show notice to user
|
||||
printf("Select an object to track and then press SPACE or ENTER button!\n" ); |
||||
printf("Finish the selection process by pressing BACKSPACE button!\n" ); |
||||
|
||||
// while key is not Backspace
|
||||
while(key!=27){ |
||||
temp=select(windowName, img, true, fromCenter); |
||||
if(temp.width>0 && temp.height>0) |
||||
box.push_back(temp); |
||||
} |
||||
boundingBox=box; |
||||
} |
||||
|
||||
ROISelector _selector; |
||||
Rect2d selectROI(Mat img, bool fromCenter){ |
||||
return _selector.select("ROI selector", img, true, fromCenter); |
||||
}; |
||||
|
||||
Rect2d selectROI(const std::string& windowName, Mat img, bool showCrossair, bool fromCenter){ |
||||
printf("Select an object to track and then press SPACE or ENTER button!\n" ); |
||||
return _selector.select(windowName,img, showCrossair, fromCenter); |
||||
}; |
||||
|
||||
void selectROI(const std::string& windowName, Mat img, std::vector<Rect2d> & boundingBox, bool fromCenter){ |
||||
return _selector.select(windowName, img, boundingBox, fromCenter); |
||||
} |
||||
|
||||
} /* namespace cv */ |
Loading…
Reference in new issue