OpenCV 4.10.0-dev
Open Source Computer Vision
Loading...
Searching...
No Matches
Customizing the CN Tracker

Goal

In this tutorial you will learn how to

  • Set custom parameters for CN tracker.
  • Use your own feature-extractor function for the CN tracker.

This document contains tutorial for the cv::TrackerKCF.

Source Code

3#include <opencv2/videoio.hpp>
4#include <opencv2/highgui.hpp>
5#include <iostream>
6#include <cstring>
7#include "samples_utility.hpp"
8
9using namespace std;
10using namespace cv;
11
12// prototype of the functino for feature extractor
13void sobelExtractor(const Mat img, const Rect roi, Mat& feat);
14
15int main( int argc, char** argv ){
16 // show help
17 if(argc<2){
18 cout<<
19 " Usage: tracker <video_name>\n"
20 " examples:\n"
21 " example_tracking_kcf Bolt/img/%04d.jpg\n"
22 " example_tracking_kcf faceocc2.webm\n"
23 << endl;
24 return 0;
25 }
26
27 // declares all required variables
28 Rect roi;
29 Mat frame;
30
33 param.desc_pca = TrackerKCF::GRAY | TrackerKCF::CN;
34 param.desc_npca = 0;
35 param.compress_feature = true;
36 param.compressed_size = 2;
38
39 // create a tracker object
41 Ptr<TrackerKCF> tracker = TrackerKCF::create(param);
43
45 tracker->setFeatureExtractor(sobelExtractor);
47
48 // set input video
49 std::string video = argv[1];
50 VideoCapture cap(video);
51
52 // get bounding box
53 cap >> frame;
54 roi=selectROI("tracker",frame);
55
56 //quit if ROI was not selected
57 if(roi.width==0 || roi.height==0)
58 return 0;
59
60 // initialize the tracker
61 tracker->init(frame,roi);
62
63 // perform the tracking process
64 printf("Start the tracking process, press ESC to quit.\n");
65 for ( ;; ){
66 // get frame from the video
67 cap >> frame;
68
69 // stop the program if no more images
70 if(frame.rows==0 || frame.cols==0)
71 break;
72
73 // update the tracking result
74 tracker->update(frame,roi);
75
76 // draw the tracked object
77 rectangle( frame, roi, Scalar( 255, 0, 0 ), 2, 1 );
78
79 // show image with the tracked object
80 imshow("tracker",frame);
81
82 //quit on ESC button
83 if(waitKey(1)==27)break;
84 }
85
86 return 0;
87}
88
89void sobelExtractor(const Mat img, const Rect roi, Mat& feat){
90 Mat sobel[2];
91 Mat patch;
92 Rect region=roi;
93
95 // extract patch inside the image
96 if(roi.x<0){region.x=0;region.width+=roi.x;}
97 if(roi.y<0){region.y=0;region.height+=roi.y;}
98 if(roi.x+roi.width>img.cols)region.width=img.cols-roi.x;
99 if(roi.y+roi.height>img.rows)region.height=img.rows-roi.y;
100 if(region.width>img.cols)region.width=img.cols;
101 if(region.height>img.rows)region.height=img.rows;
103
104 patch=img(region).clone();
105 cvtColor(patch,patch, COLOR_BGR2GRAY);
106
108 // add some padding to compensate when the patch is outside image border
109 int addTop,addBottom, addLeft, addRight;
110 addTop=region.y-roi.y;
111 addBottom=(roi.height+roi.y>img.rows?roi.height+roi.y-img.rows:0);
112 addLeft=region.x-roi.x;
113 addRight=(roi.width+roi.x>img.cols?roi.width+roi.x-img.cols:0);
114
115 copyMakeBorder(patch,patch,addTop,addBottom,addLeft,addRight,BORDER_REPLICATE);
117
119 Sobel(patch, sobel[0], CV_32F,1,0,1);
120 Sobel(patch, sobel[1], CV_32F,0,1,1);
121
122 merge(sobel,2,feat);
124
126 feat=feat/255.0-0.5; // normalize to range -0.5 .. 0.5
128}
n-dimensional dense array class
Definition mat.hpp:829
CV_NODISCARD_STD Mat clone() const
Creates a full copy of the array and the underlying data.
int cols
Definition mat.hpp:2155
int rows
the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
Definition mat.hpp:2155
Template class for 2D rectangles.
Definition types.hpp:444
_Tp x
x coordinate of the top-left corner
Definition types.hpp:487
_Tp y
y coordinate of the top-left corner
Definition types.hpp:488
_Tp width
width of the rectangle
Definition types.hpp:489
_Tp height
height of the rectangle
Definition types.hpp:490
Class for video capturing from video files, image sequences or cameras.
Definition videoio.hpp:747
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.
void merge(const Mat *mv, size_t count, OutputArray dst)
Creates one multi-channel array out of several single-channel ones.
std::shared_ptr< _Tp > Ptr
Definition cvstd_wrapper.hpp:23
#define CV_32F
Definition interface.h:78
void sobel(InputArray _src, OutputArray _dx, OutputArray _dy, int kernel_size, int borderType, int borderValue)
Creates a 2D gradient image from source luminance data without normalization. Calculate X direction 1...
void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0, AlgorithmHint hint=cv::ALGO_HINT_DEFAULT)
Converts an image from one color space to another.
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.
int main(int argc, char *argv[])
Definition highgui_qt.cpp:3
Definition core.hpp:107
STL namespace.
Definition tracking.hpp:118
bool compress_feature
activate the pca method to compress the features
Definition tracking.hpp:130
int desc_pca
compressed descriptors of TrackerKCF::MODE
Definition tracking.hpp:133
int desc_npca
non-compressed descriptors of TrackerKCF::MODE
Definition tracking.hpp:134
int compressed_size
feature size after compression
Definition tracking.hpp:132

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

    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 response 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 normalize the feature with range -0.5 to 0.5

    feat=feat/255.0-0.5; // normalize to range -0.5 .. 0.5