tracker.cpp 5.64 KB
Newer Older
1 2
#include <opencv2/core/utility.hpp>
#include <opencv2/tracking.hpp>
3
#include <opencv2/videoio.hpp>
4 5
#include <opencv2/highgui.hpp>
#include <iostream>
6
#include <cstring>
7 8 9 10 11

using namespace std;
using namespace cv;

static Mat image;
12
static Rect2d boundingBox;
13 14 15 16 17
static bool paused;
static bool selectObject = false;
static bool startSelection = false;

static const char* keys =
18 19
{ "{@tracker_algorithm | | Tracker algorithm }"
    "{@video_name      | | video name        }"
20
    "{@start_frame     |0| Start frame       }" 
21
    "{@bounding_frame  |0,0,0,0| Initial bounding frame}"};
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

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 );
Alex Leontiev's avatar
Alex Leontiev committed
49
          rectangle( currentFrame, Point((int) boundingBox.x, (int)boundingBox.y ), Point( x, y ), Scalar( 255, 0, 0 ), 2, 1 );
50 51 52 53 54 55 56
          imshow( "Tracking API", currentFrame );
        }
        break;
    }
  }
}

57
static void help()
58
{
59 60 61 62 63
  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"
64
       "tracker_algorithm can be: MIL, BOOSTING, MEDIANFLOW, TLD\n"
65 66 67 68 69 70 71 72
       << endl;

  cout << "\n\nHot keys: \n"
       "\tq - quit the program\n"
       "\tp - pause video\n";
}

int main( int argc, char** argv ){
73 74 75 76
  CommandLineParser parser( argc, argv, keys );

  String tracker_algorithm = parser.get<String>( 0 );
  String video_name = parser.get<String>( 1 );
77
  int start_frame = parser.get<int>( 2 );
78 79 80 81 82 83 84

  if( tracker_algorithm.empty() || video_name.empty() )
  {
    help();
    return -1;
  }

85
  int coords[4]={0,0,0,0};
86
  bool initBoxWasGivenInCommandLine=false;
Alex Leontiev's avatar
Alex Leontiev committed
87
  {
88
      String initBoundingBox=parser.get<String>(3);
89 90 91
      for(size_t npos=0,pos=0,ctr=0;ctr<4;ctr++){
        npos=initBoundingBox.find_first_of(',',pos);
        if(npos==string::npos && ctr<3){
92 93 94 95 96 97
           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());
98
        if(num<=0){
99 100 101 102 103 104 105 106
           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;
      }
107 108 109
      if(coords[0]>0 && coords[1]>0 && coords[2]>0 && coords[3]>0){
          initBoxWasGivenInCommandLine=true;
      }
Alex Leontiev's avatar
Alex Leontiev committed
110
  }
111

112 113 114
  //open the capture
  VideoCapture cap;
  cap.open( video_name );
115
  cap.set( CAP_PROP_POS_FRAMES, start_frame );
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141

  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 );
142
  if(initBoxWasGivenInCommandLine){
143 144 145 146 147 148 149 150 151
      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 );
  }
152 153 154
  imshow( "Tracking API", image );

  bool initialized = false;
155 156
  int frameCounter = 0;

157 158 159 160
  for ( ;; )
  {
    if( !paused )
    {
161 162 163 164 165 166
      if(initialized){
          cap >> frame;
          if(frame.empty()){
            break;
          }
          frame.copyTo( image );
167 168
      }

169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
      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 );
188
      frameCounter++;
189 190 191 192 193 194 195 196 197 198 199 200
    }

    char c = (char) waitKey( 2 );
    if( c == 'q' )
      break;
    if( c == 'p' )
      paused = !paused;

  }

  return 0;
}