OpenCV  3.1.0
Open Source Computer Vision
Customizing the CN Tracker

Goal

In this tutorial you will learn how to

This document contains tutorial for the cv::TrackerKCF.

Source Code

2 #include <opencv2/tracking.hpp>
3 #include <opencv2/videoio.hpp>
4 #include <opencv2/highgui.hpp>
5 #include <iostream>
6 #include <cstring>
7 
8 using namespace std;
9 using namespace cv;
10 
11 // prototype of the functino for feature extractor
12 void sobelExtractor(const Mat img, const Rect roi, Mat& feat);
13 
14 int main( int argc, char** argv ){
15  // show help
16  if(argc<2){
17  cout<<
18  " Usage: tracker <video_name>\n"
19  " examples:\n"
20  " example_tracking_kcf Bolt/img/%04d.jpg\n"
21  " example_tracking_kcf faceocc2.webm\n"
22  << endl;
23  return 0;
24  }
25 
26  // declares all required variables
27  Rect2d roi;
28  Mat frame;
29 
31  TrackerKCF::Params param;
32  param.desc_pca = TrackerKCF::GRAY | TrackerKCF::CN;
33  param.desc_npca = 0;
34  param.compress_feature = true;
35  param.compressed_size = 2;
37 
38  // create a tracker object
40  Ptr<TrackerKCF> tracker = TrackerKCF::createTracker(param);
42 
44  tracker->setFeatureExtractor(sobelExtractor);
46 
47  // set input video
48  std::string video = argv[1];
49  VideoCapture cap(video);
50 
51  // get bounding box
52  cap >> frame;
53  roi=selectROI("tracker",frame);
54 
55  //quit if ROI was not selected
56  if(roi.width==0 || roi.height==0)
57  return 0;
58 
59  // initialize the tracker
60  tracker->init(frame,roi);
61 
62  // perform the tracking process
63  printf("Start the tracking process, press ESC to quit.\n");
64  for ( ;; ){
65  // get frame from the video
66  cap >> frame;
67 
68  // stop the program if no more images
69  if(frame.rows==0 || frame.cols==0)
70  break;
71 
72  // update the tracking result
73  tracker->update(frame,roi);
74 
75  // draw the tracked object
76  rectangle( frame, roi, Scalar( 255, 0, 0 ), 2, 1 );
77 
78  // show image with the tracked object
79  imshow("tracker",frame);
80 
81  //quit on ESC button
82  if(waitKey(1)==27)break;
83  }
84 
85  return 0;
86 }
87 
88 void sobelExtractor(const Mat img, const Rect roi, Mat& feat){
89  Mat sobel[2];
90  Mat patch;
91  Rect region=roi;
92 
94  // extract patch inside the image
95  if(roi.x<0){region.x=0;region.width+=roi.x;}
96  if(roi.y<0){region.y=0;region.height+=roi.y;}
97  if(roi.x+roi.width>img.cols)region.width=img.cols-roi.x;
98  if(roi.y+roi.height>img.rows)region.height=img.rows-roi.y;
99  if(region.width>img.cols)region.width=img.cols;
100  if(region.height>img.rows)region.height=img.rows;
102 
103  patch=img(region).clone();
104  cvtColor(patch,patch, CV_BGR2GRAY);
105 
107  // add some padding to compensate when the patch is outside image border
108  int addTop,addBottom, addLeft, addRight;
109  addTop=region.y-roi.y;
110  addBottom=(roi.height+roi.y>img.rows?roi.height+roi.y-img.rows:0);
111  addLeft=region.x-roi.x;
112  addRight=(roi.width+roi.x>img.cols?roi.width+roi.x-img.cols:0);
113 
114  copyMakeBorder(patch,patch,addTop,addBottom,addLeft,addRight,BORDER_REPLICATE);
116 
118  Sobel(patch, sobel[0], CV_32F,1,0,1);
119  Sobel(patch, sobel[1], CV_32F,0,1,1);
120 
121  merge(sobel,2,feat);
123 
125  feat.convertTo(feat,CV_64F);
126  feat=feat/255.0-0.5; // normalize to range -0.5 .. 0.5
128 }
Scalar_< double > Scalar
Definition: types.hpp:597
void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0)
Converts an image from one color space to another.
aaaaaa|abcdefgh|hhhhhhh
Definition: base.hpp:253
_Tp x
Definition: types.hpp:403
int rows
the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions ...
Definition: mat.hpp:1885
Definition: types_c.h:121
void convertTo(OutputArray m, int rtype, double alpha=1, double beta=0) const
Converts an array to another data type with optional scaling.
STL namespace.
void rectangle(InputOutputArray img, Point pt1, Point pt2, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
Draws a simple, thick, or filled up-right rectangle.
void imshow(const String &winname, InputArray mat)
Displays an image in the specified window.
#define CV_32F
Definition: cvdef.h:369
#define CV_64F
Definition: cvdef.h:370
Definition: affine.hpp:51
Class for video capturing from video files, image sequences or cameras. The class provides C++ API fo...
Definition: videoio.hpp:389
_Tp y
Definition: types.hpp:403
unsigned int desc_npca
non-compressed descriptors of TrackerKCF::MODE
Definition: tracker.hpp:1249
void Sobel(InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize=3, double scale=1, double delta=0, int borderType=BORDER_DEFAULT)
Calculates the first, second, third, or mixed image derivatives using an extended Sobel operator...
void copyMakeBorder(InputArray src, OutputArray dst, int top, int bottom, int left, int right, int borderType, const Scalar &value=Scalar())
Forms a border around an image.
bool init(const Mat &image, const Rect2d &boundingBox)
Initialize the tracker with a know bounding box that surrounding the target.
_Tp height
Definition: types.hpp:403
unsigned int desc_pca
compressed descriptors of TrackerKCF::MODE
Definition: tracker.hpp:1248
int cols
Definition: mat.hpp:1885
Mat clone() const
Creates a full copy of the array and the underlying data.
bool compress_feature
activate the pca method to compress the features
Definition: tracker.hpp:1245
Template class for 2D rectangles.
Definition: types.hpp:374
Template class for smart pointers with shared ownership.
Definition: cvstd.hpp:283
Rect2d selectROI(Mat img, bool fromCenter=true)
void merge(const Mat *mv, size_t count, OutputArray dst)
Creates one multi-channel array out of several single-channel ones.
virtual void setFeatureExtractor(void(*)(const Mat, const Rect, Mat &), bool pca_func=false)
_Tp width
Definition: types.hpp:403
int compressed_size
feature size after compression
Definition: tracker.hpp:1247
bool update(const Mat &image, Rect2d &boundingBox)
Update the tracker, find the new most likely bounding box for the target.
Definition: tracker.hpp:1220
int waitKey(int delay=0)
Waits for a pressed key.

Explanation

This part explains how to set custom parameters and use your own feature-extractor function for the CN tracker. If you need a more detailed information to use cv::Tracker, please refer to Introduction to OpenCV Tracker.

  1. Set Custom Parameters

    TrackerKCF::Params param;
    param.desc_pca = TrackerKCF::GRAY | TrackerKCF::CN;
    param.desc_npca = 0;
    param.compress_feature = true;
    param.compressed_size = 2;

    To set custom paramters, an object should be created. Each tracker algorithm has their own parameter format. So, in this case we should use parameter from cv::TrackerKCF since we are interested in modifying the parameter of this tracker algorithm.

    There are several parameters that can be configured as explained in cv::TrackerKCF::Params. For this tutorial, we focussed on the feature extractor functions.

    Several feature types can be used in cv::TrackerKCF. In this case, the grayscale value (1 dimension) and color-names features (10 dimension), will be merged as 11 dimension feature and then compressed into 2 dimension as specified in the code.

    If you want to use another type of pre-defined feature-extractor function, you can check in cv::TrackerKCF::MODE. We will leave the non-compressed feature as 0 since we want to use a customized function.

  2. Using a custom function

    You can define your own feature-extractor function for the CN tracker. However, you need to take care about several things:

    • The extracted feature should have the same size as the size of the given bounding box (width and height). For the number of channels you can check the limitation in cv::Mat.
    • You can only use features that can be compared using Euclidean distance. Features like local binary pattern (LBP) may not be suitable since it should be compared using Hamming distance.

    Since the size of the extracted feature should be in the same size with the given bounding box, we need to take care whenever the given bounding box is partially out of range. In this case, we can copy part of image contained in the bounding box as shown in the snippet below.

    // extract patch inside the image
    if(roi.x<0){region.x=0;region.width+=roi.x;}
    if(roi.y<0){region.y=0;region.height+=roi.y;}
    if(roi.x+roi.width>img.cols)region.width=img.cols-roi.x;
    if(roi.y+roi.height>img.rows)region.height=img.rows-roi.y;
    if(region.width>img.cols)region.width=img.cols;
    if(region.height>img.rows)region.height=img.rows;

    Whenever the copied image is smaller than the given bounding box, padding should be given to the sides where the bounding box is partially out of frame.

    // add some padding to compensate when the patch is outside image border
    int addTop,addBottom, addLeft, addRight;
    addTop=region.y-roi.y;
    addBottom=(roi.height+roi.y>img.rows?roi.height+roi.y-img.rows:0);
    addLeft=region.x-roi.x;
    addRight=(roi.width+roi.x>img.cols?roi.width+roi.x-img.cols:0);
    copyMakeBorder(patch,patch,addTop,addBottom,addLeft,addRight,BORDER_REPLICATE);
  3. Defining the feature

    In this tutorial, the extracted feature is reponse of the Sobel filter in x and y direction. Those Sobel filter responses are concatenated, resulting a feature with 2 channels.

    Sobel(patch, sobel[0], CV_32F,1,0,1);
    Sobel(patch, sobel[1], CV_32F,0,1,1);
    merge(sobel,2,feat);
  4. Post processing

    Make sure to convert the feature into cv::CV_64F data format and normalize its value with range -0.5 to 0.5

    feat.convertTo(feat,CV_64F);
    feat=feat/255.0-0.5; // normalize to range -0.5 .. 0.5