1793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/video/tracking.hpp" 2793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/imgproc/imgproc.hpp" 3793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/videoio/videoio.hpp" 4793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/highgui/highgui.hpp" 5793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 6793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <iostream> 7793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <ctype.h> 8793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 9793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerusing namespace cv; 10793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerusing namespace std; 11793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 12793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void help() 13793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 14793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // print a welcome message, and the OpenCV version 15793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cout << "\nThis is a demo of Lukas-Kanade optical flow lkdemo(),\n" 16793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "Using OpenCV version " << CV_VERSION << endl; 17793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cout << "\nIt uses camera by default, but you can provide a path to video as an argument.\n"; 18793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cout << "\nHot keys: \n" 19793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "\tESC - quit the program\n" 20793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "\tr - auto-initialize tracking\n" 21793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "\tc - delete all the points\n" 22793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "\tn - switch the \"night\" mode on/off\n" 23793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "To add/remove a feature point click it\n" << endl; 24793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 25793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 26793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerPoint2f point; 27793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerbool addRemovePt = false; 28793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 29793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void onMouse( int event, int x, int y, int /*flags*/, void* /*param*/ ) 30793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 31793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( event == EVENT_LBUTTONDOWN ) 32793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 33793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler point = Point2f((float)x, (float)y); 34793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler addRemovePt = true; 35793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 36793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 37793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 38793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerint main( int argc, char** argv ) 39793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 40793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler help(); 41793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 42793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler VideoCapture cap; 43793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler TermCriteria termcrit(TermCriteria::COUNT|TermCriteria::EPS,20,0.03); 44793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Size subPixWinSize(10,10), winSize(31,31); 45793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 46793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const int MAX_COUNT = 500; 47793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool needToInit = false; 48793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool nightMode = false; 49793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 50793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0]))) 51793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cap.open(argc == 2 ? argv[1][0] - '0' : 0); 52793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else if( argc == 2 ) 53793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cap.open(argv[1]); 54793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 55793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !cap.isOpened() ) 56793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 57793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cout << "Could not initialize capturing...\n"; 58793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return 0; 59793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 60793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 61793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler namedWindow( "LK Demo", 1 ); 62793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler setMouseCallback( "LK Demo", onMouse, 0 ); 63793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 64793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Mat gray, prevGray, image, frame; 65793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler vector<Point2f> points[2]; 66793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 67793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for(;;) 68793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 69793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cap >> frame; 70793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( frame.empty() ) 71793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 72793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 73793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler frame.copyTo(image); 74793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvtColor(image, gray, COLOR_BGR2GRAY); 75793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 76793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( nightMode ) 77793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler image = Scalar::all(0); 78793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 79793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( needToInit ) 80793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 81793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // automatic initialization 82793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler goodFeaturesToTrack(gray, points[1], MAX_COUNT, 0.01, 10, Mat(), 3, 0, 0.04); 83793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cornerSubPix(gray, points[1], subPixWinSize, Size(-1,-1), termcrit); 84793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler addRemovePt = false; 85793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 86793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else if( !points[0].empty() ) 87793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 88793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler vector<uchar> status; 89793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler vector<float> err; 90793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if(prevGray.empty()) 91793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler gray.copyTo(prevGray); 92793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calcOpticalFlowPyrLK(prevGray, gray, points[0], points[1], status, err, winSize, 93793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 3, termcrit, 0, 0.001); 94793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler size_t i, k; 95793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( i = k = 0; i < points[1].size(); i++ ) 96793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 97793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( addRemovePt ) 98793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 99793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( norm(point - points[1][i]) <= 5 ) 100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler addRemovePt = false; 102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler continue; 103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !status[i] ) 107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler continue; 108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler points[1][k++] = points[1][i]; 110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler circle( image, points[1][i], 3, Scalar(0,255,0), -1, 8); 111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler points[1].resize(k); 113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( addRemovePt && points[1].size() < (size_t)MAX_COUNT ) 116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler vector<Point2f> tmp; 118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tmp.push_back(point); 119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cornerSubPix( gray, tmp, winSize, Size(-1,-1), termcrit); 120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler points[1].push_back(tmp[0]); 121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler addRemovePt = false; 122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler needToInit = false; 125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler imshow("LK Demo", image); 126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler char c = (char)waitKey(10); 128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( c == 27 ) 129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler switch( c ) 131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler case 'r': 133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler needToInit = true; 134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler case 'c': 136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler points[0].clear(); 137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler points[1].clear(); 138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler case 'n': 140793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nightMode = !nightMode; 141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::swap(points[1], points[0]); 145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::swap(prevGray, gray); 146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return 0; 149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 150