mirror of
https://github.com/opencv/opencv_contrib.git
synced 2025-10-19 02:16:34 +08:00

Now initial bounding frame can be given in command-line, as an alternative to manual selection via mouse. Bounding frame is given as optional last argument in the format "x1,y1,x2,y2" where x's and y's are integers, symbolizing bounding box with opposite vertices (x1,y1) and (x2,y2).
200 lines
5.5 KiB
C++
200 lines
5.5 KiB
C++
#include <opencv2/core/utility.hpp>
|
|
#include <opencv2/tracking.hpp>
|
|
#include <opencv2/highgui.hpp>
|
|
#include <iostream>
|
|
|
|
using namespace std;
|
|
using namespace cv;
|
|
|
|
static Mat image;
|
|
static Rect boundingBox;
|
|
static bool paused;
|
|
static bool selectObject = false;
|
|
static bool startSelection = false;
|
|
|
|
static const char* keys =
|
|
{ "{@tracker_algorithm | | Tracker algorithm }"
|
|
"{@video_name | | video name }"
|
|
"{@start_frame |1| Start frame }"
|
|
"{@bounding_frame |0,0,0,0| Initial bounding frame}"};
|
|
|
|
static void help()
|
|
{
|
|
cout << "\nThis example shows the functionality of \"Long-term optical tracking API\""
|
|
"-- pause video [p] and draw a bounding box around the target to start the tracker\n"
|
|
"Example of <video_name> is in opencv_extra/testdata/cv/tracking/\n"
|
|
"Call:\n"
|
|
"./tracker <tracker_algorithm> <video_name> <start_frame> [<bounding_frame>]\n"
|
|
<< endl;
|
|
|
|
cout << "\n\nHot keys: \n"
|
|
"\tq - quit the program\n"
|
|
"\tp - pause video\n";
|
|
}
|
|
|
|
static void onMouse( int event, int x, int y, int, void* )
|
|
{
|
|
if( !selectObject )
|
|
{
|
|
switch ( event )
|
|
{
|
|
case EVENT_LBUTTONDOWN:
|
|
//set origin of the bounding box
|
|
startSelection = true;
|
|
boundingBox.x = x;
|
|
boundingBox.y = y;
|
|
break;
|
|
case EVENT_LBUTTONUP:
|
|
//sei with and height of the bounding box
|
|
boundingBox.width = std::abs( x - boundingBox.x );
|
|
boundingBox.height = std::abs( y - boundingBox.y );
|
|
paused = false;
|
|
selectObject = true;
|
|
break;
|
|
case EVENT_MOUSEMOVE:
|
|
|
|
if( startSelection && !selectObject )
|
|
{
|
|
//draw the bounding box
|
|
Mat currentFrame;
|
|
image.copyTo( currentFrame );
|
|
rectangle( currentFrame, Point( boundingBox.x, boundingBox.y ), Point( x, y ), Scalar( 255, 0, 0 ), 2, 1 );
|
|
imshow( "Tracking API", currentFrame );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
int main( int argc, char** argv )
|
|
{
|
|
CommandLineParser parser( argc, argv, keys );
|
|
|
|
String tracker_algorithm = parser.get<String>( 0 );
|
|
String video_name = parser.get<String>( 1 );
|
|
int start_frame = parser.get<int>( 2 );
|
|
|
|
if( tracker_algorithm.empty() || video_name.empty() )
|
|
{
|
|
help();
|
|
return -1;
|
|
}
|
|
|
|
int coords[4]={0,0,0,0};
|
|
bool initFrameWasGivenInCommandLine=false;
|
|
do{
|
|
String initBoundingBox=parser.get<String>(3);
|
|
for(size_t pos=0,ctr=0;ctr<4;ctr++){
|
|
size_t npos=initBoundingBox.find_first_of(',',pos);
|
|
if(npos==string::npos && ctr<3){
|
|
printf("bounding box should be given in format \"x1,y1,x2,y2\",where x's and y's are integer cordinates of opposed corners of bdd box\n");
|
|
printf("got: %s\n",initBoundingBox.substr(pos,string::npos).c_str());
|
|
printf("manual selection of bounding box will be employed\n");
|
|
break;
|
|
}
|
|
int num=atoi(initBoundingBox.substr(pos,(ctr==3)?(string::npos):(npos-pos)).c_str());
|
|
if(num<=0){
|
|
printf("bounding box should be given in format \"x1,y1,x2,y2\",where x's and y's are integer cordinates of opposed corners of bdd box\n");
|
|
printf("got: %s\n",initBoundingBox.substr(pos,npos-pos).c_str());
|
|
printf("manual selection of bounding box will be employed\n");
|
|
break;
|
|
}
|
|
coords[ctr]=num;
|
|
pos=npos+1;
|
|
}
|
|
if(coords[0]>0 && coords[1]>0 && coords[2]>0 && coords[3]>0){
|
|
initFrameWasGivenInCommandLine=true;
|
|
}
|
|
}while(0);
|
|
|
|
//open the capture
|
|
VideoCapture cap;
|
|
cap.open( video_name );
|
|
cap.set( CAP_PROP_POS_FRAMES, start_frame );
|
|
|
|
if( !cap.isOpened() )
|
|
{
|
|
help();
|
|
cout << "***Could not initialize capturing...***\n";
|
|
cout << "Current parameter's value: \n";
|
|
parser.printMessage();
|
|
return -1;
|
|
}
|
|
|
|
Mat frame;
|
|
paused = true;
|
|
namedWindow( "Tracking API", 1 );
|
|
setMouseCallback( "Tracking API", onMouse, 0 );
|
|
|
|
//instantiates the specific Tracker
|
|
Ptr<Tracker> tracker = Tracker::create( tracker_algorithm );
|
|
if( tracker == NULL )
|
|
{
|
|
cout << "***Error in the instantiation of the tracker...***\n";
|
|
return -1;
|
|
}
|
|
|
|
//get the first frame
|
|
cap >> frame;
|
|
frame.copyTo( image );
|
|
if(initFrameWasGivenInCommandLine){
|
|
selectObject=true;
|
|
paused=false;
|
|
boundingBox.x = coords[0];
|
|
boundingBox.y = coords[1];
|
|
boundingBox.width = std::abs( coords[2] - coords[0] );
|
|
boundingBox.height = std::abs( coords[3]-coords[1]);
|
|
printf("bounding box with vertices (%d,%d) and (%d,%d) was given in command line\n",coords[0],coords[1],coords[2],coords[3]);
|
|
rectangle( image, boundingBox, Scalar( 255, 0, 0 ), 2, 1 );
|
|
}
|
|
imshow( "Tracking API", image );
|
|
|
|
bool initialized = false;
|
|
int frameCounter = 0;
|
|
|
|
for ( ;; )
|
|
{
|
|
if( !paused )
|
|
{
|
|
cap >> frame;
|
|
|
|
if( frame.empty() )
|
|
{
|
|
break;
|
|
}
|
|
|
|
frame.copyTo( image );
|
|
|
|
if( !initialized && selectObject )
|
|
{
|
|
//initializes the tracker
|
|
if( !tracker->init( frame, boundingBox ) )
|
|
{
|
|
cout << "***Could not initialize tracker...***\n";
|
|
return -1;
|
|
}
|
|
initialized = true;
|
|
}
|
|
else if( initialized )
|
|
{
|
|
//updates the tracker
|
|
if( tracker->update( frame, boundingBox ) )
|
|
{
|
|
rectangle( image, boundingBox, Scalar( 255, 0, 0 ), 2, 1 );
|
|
}
|
|
}
|
|
imshow( "Tracking API", image );
|
|
frameCounter++;
|
|
}
|
|
|
|
char c = (char) waitKey( 2 );
|
|
if( c == 'q' )
|
|
break;
|
|
if( c == 'p' )
|
|
paused = !paused;
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|