1 #include "opencv2/video/tracking.hpp"
2 #include "opencv2/imgproc/imgproc.hpp"
3 #include "opencv2/videoio/videoio.hpp"
4 #include "opencv2/highgui/highgui.hpp"
5
6 #include <iostream>
7 #include <ctype.h>
8
9 using namespace cv;
10 using namespace std;
11
help()12 static void help()
13 {
14 // print a welcome message, and the OpenCV version
15 cout << "\nThis is a demo of Lukas-Kanade optical flow lkdemo(),\n"
16 "Using OpenCV version " << CV_VERSION << endl;
17 cout << "\nIt uses camera by default, but you can provide a path to video as an argument.\n";
18 cout << "\nHot keys: \n"
19 "\tESC - quit the program\n"
20 "\tr - auto-initialize tracking\n"
21 "\tc - delete all the points\n"
22 "\tn - switch the \"night\" mode on/off\n"
23 "To add/remove a feature point click it\n" << endl;
24 }
25
26 Point2f point;
27 bool addRemovePt = false;
28
onMouse(int event,int x,int y,int,void *)29 static void onMouse( int event, int x, int y, int /*flags*/, void* /*param*/ )
30 {
31 if( event == EVENT_LBUTTONDOWN )
32 {
33 point = Point2f((float)x, (float)y);
34 addRemovePt = true;
35 }
36 }
37
main(int argc,char ** argv)38 int main( int argc, char** argv )
39 {
40 help();
41
42 VideoCapture cap;
43 TermCriteria termcrit(TermCriteria::COUNT|TermCriteria::EPS,20,0.03);
44 Size subPixWinSize(10,10), winSize(31,31);
45
46 const int MAX_COUNT = 500;
47 bool needToInit = false;
48 bool nightMode = false;
49
50 if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
51 cap.open(argc == 2 ? argv[1][0] - '0' : 0);
52 else if( argc == 2 )
53 cap.open(argv[1]);
54
55 if( !cap.isOpened() )
56 {
57 cout << "Could not initialize capturing...\n";
58 return 0;
59 }
60
61 namedWindow( "LK Demo", 1 );
62 setMouseCallback( "LK Demo", onMouse, 0 );
63
64 Mat gray, prevGray, image, frame;
65 vector<Point2f> points[2];
66
67 for(;;)
68 {
69 cap >> frame;
70 if( frame.empty() )
71 break;
72
73 frame.copyTo(image);
74 cvtColor(image, gray, COLOR_BGR2GRAY);
75
76 if( nightMode )
77 image = Scalar::all(0);
78
79 if( needToInit )
80 {
81 // automatic initialization
82 goodFeaturesToTrack(gray, points[1], MAX_COUNT, 0.01, 10, Mat(), 3, 0, 0.04);
83 cornerSubPix(gray, points[1], subPixWinSize, Size(-1,-1), termcrit);
84 addRemovePt = false;
85 }
86 else if( !points[0].empty() )
87 {
88 vector<uchar> status;
89 vector<float> err;
90 if(prevGray.empty())
91 gray.copyTo(prevGray);
92 calcOpticalFlowPyrLK(prevGray, gray, points[0], points[1], status, err, winSize,
93 3, termcrit, 0, 0.001);
94 size_t i, k;
95 for( i = k = 0; i < points[1].size(); i++ )
96 {
97 if( addRemovePt )
98 {
99 if( norm(point - points[1][i]) <= 5 )
100 {
101 addRemovePt = false;
102 continue;
103 }
104 }
105
106 if( !status[i] )
107 continue;
108
109 points[1][k++] = points[1][i];
110 circle( image, points[1][i], 3, Scalar(0,255,0), -1, 8);
111 }
112 points[1].resize(k);
113 }
114
115 if( addRemovePt && points[1].size() < (size_t)MAX_COUNT )
116 {
117 vector<Point2f> tmp;
118 tmp.push_back(point);
119 cornerSubPix( gray, tmp, winSize, Size(-1,-1), termcrit);
120 points[1].push_back(tmp[0]);
121 addRemovePt = false;
122 }
123
124 needToInit = false;
125 imshow("LK Demo", image);
126
127 char c = (char)waitKey(10);
128 if( c == 27 )
129 break;
130 switch( c )
131 {
132 case 'r':
133 needToInit = true;
134 break;
135 case 'c':
136 points[0].clear();
137 points[1].clear();
138 break;
139 case 'n':
140 nightMode = !nightMode;
141 break;
142 }
143
144 std::swap(points[1], points[0]);
145 cv::swap(prevGray, gray);
146 }
147
148 return 0;
149 }
150