Subversion Repositories OpenCV2-Cookbook

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 PointedEar 1
/*------------------------------------------------------------------------------------------*\
2
   This file contains material supporting chapter 10 of the cookbook:  
3
   Computer Vision Programming using the OpenCV Library.
4
   by Robert Laganiere, Packt Publishing, 2011.
5
 
6
   This program is free software; permission is hereby granted to use, copy, modify,
7
   and distribute this source code, or portions thereof, for any purpose, without fee,
8
   subject to the restriction that the copyright notice may not be removed
9
   or altered from any source or altered source distribution.
10
   The software is released on an as-is basis and without any warranties of any kind.
11
   In particular, the software is not guaranteed to be fault-tolerant or free from failure.
12
   The author disclaims all warranties with regard to this software, any use,
13
   and any consequent failure, is purely the responsibility of the user.
14
 
15
   Copyright (C) 2010-2011 Robert Laganiere, www.laganiere.name
16
\*------------------------------------------------------------------------------------------*/
17
 
18
#if !defined FTRACKER
19
#define FTRACKER
20
 
21
#include <string>
22
#include <vector>
23
#include <opencv2/core/core.hpp>
24
#include <opencv2/highgui/highgui.hpp>
25
#include <opencv2/imgproc/imgproc.hpp>
26
#include <opencv2/features2d/features2d.hpp>
27
#include <opencv2/video/tracking.hpp>
28
 
29
#include "videoprocessor.h"
30
 
31
class FeatureTracker : public FrameProcessor {
32
 
33
        cv::Mat gray;                   // current gray-level image
34
        cv::Mat gray_prev;              // previous gray-level image
35
        std::vector<cv::Point2f> points[2]; // tracked features from 0->1
36
        std::vector<cv::Point2f> initial;   // initial position of tracked points
37
        std::vector<cv::Point2f> features;  // detected features
38
        int max_count;    // maximum number of features to detect
39
        double qlevel;    // quality level for feature detection
40
        double minDist;   // minimum distance between two feature points
41
        std::vector<uchar> status; // status of tracked features
42
    std::vector<float> err;    // error in tracking
43
 
44
  public:
45
 
46
        FeatureTracker() : max_count(500), qlevel(0.01), minDist(10.) {}
47
 
48
        // processing method
49
        void process(cv:: Mat &frame, cv:: Mat &output) {
50
 
51
                // convert to gray-level image
52
                cv::cvtColor(frame, gray, CV_BGR2GRAY);
53
                frame.copyTo(output);
54
 
55
                // 1. if new feature points must be added
56
                if(addNewPoints())
57
                {
58
                        // detect feature points
59
                        detectFeaturePoints();
60
                        // add the detected features to the currently tracked features
61
                        points[0].insert(points[0].end(),features.begin(),features.end());
62
                        initial.insert(initial.end(),features.begin(),features.end());
63
                }
64
 
65
                // for first image of the sequence
66
                if(gray_prev.empty())
67
           gray.copyTo(gray_prev);
68
 
69
                // 2. track features
70
                cv::calcOpticalFlowPyrLK(gray_prev, gray, // 2 consecutive images
71
                        points[0], // input point position in first image
72
                        points[1], // output point postion in the second image
73
                        status,    // tracking success
74
                        err);      // tracking error
75
 
76
                // 2. loop over the tracked points to reject the undesirables
77
                int k=0;
78
                for( int i= 0; i < points[1].size(); i++ ) {
79
 
80
                        // do we keep this point?
81
                        if (acceptTrackedPoint(i)) {
82
 
83
                                // keep this point in vector
84
                                initial[k]= initial[i];
85
                                points[1][k++] = points[1][i];
86
                        }
87
                }
88
 
89
                // eliminate unsuccesful points
90
        points[1].resize(k);
91
                initial.resize(k);
92
 
93
                // 3. handle the accepted tracked points
94
                handleTrackedPoints(frame, output);
95
 
96
                // 4. current points and image become previous ones
97
                std::swap(points[1], points[0]);
98
        cv::swap(gray_prev, gray);
99
        }
100
 
101
        // feature point detection
102
        void detectFeaturePoints() {
103
 
104
                // detect the features
105
                cv::goodFeaturesToTrack(gray, // the image 
106
                        features,   // the output detected features
107
                        max_count,  // the maximum number of features 
108
                        qlevel,     // quality level
109
                        minDist);   // min distance between two features
110
        }
111
 
112
        // determine if new points should be added
113
        bool addNewPoints() {
114
 
115
                // if too few points
116
                return points[0].size()<=10;
117
        }
118
 
119
        // determine which tracked point should be accepted
120
        bool acceptTrackedPoint(int i) {
121
 
122
                return status[i] &&
123
                        // if point has moved
124
                        (abs(points[0][i].x-points[1][i].x)+
125
                        (abs(points[0][i].y-points[1][i].y))>2);
126
        }
127
 
128
        // handle the currently tracked points
129
        void handleTrackedPoints(cv:: Mat &frame, cv:: Mat &output) {
130
 
131
                // for all tracked points
132
                for(int i= 0; i < points[1].size(); i++ ) {
133
 
134
                        // draw line and circle
135
                    cv::line(output, initial[i], points[1][i], cv::Scalar(255,255,255));
136
                        cv::circle(output, points[1][i], 3, cv::Scalar(255,255,255),-1);
137
                }
138
        }
139
};
140
 
141
#endif