OpenCV版本: 3.2.0
例程文件目录/samples/cpp/lkdemo.cpp
原始程序是采集相机数据,台式机没有摄像头,用Euroc测试集,偷ORB_SLAM2 /Examples/Monocular/mono_euroc.cc里的LoadImages函数读取数据
在cpp目录下新建一个自己的目录mylk,拷贝lkdemo和example_cmake目录下的CMakeLists.txt并修改:
add_executable(lk_example lkdemo.cpp)
target_link_libraries(lk_example ${OpenCV_LIBS})
新建目录build,进入后cmake .. + make 编译运行即可。run.sh如下:
./lkdemo ~/slamData/EuRoC/mav02/cam0/data ~/ORB_SLAM2/Examples/Stereo/EuRoC_TimeStamps/MH02.txt
先提取角点,亚像素精度提炼角点,光流跟踪。
运行过程中会监控鼠标和键盘:
按下鼠标左键 -> 添加一个角点
按下r -> 初始化角点
按下c -> 清除角点
按下n -> 只显示角点(右图)
按下esc -> 退出
修改后的程序:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include "opencv2/video/tracking.hpp" 2 #include "opencv2/imgproc.hpp" 3 #include "opencv2/videoio.hpp" 4 #include "opencv2/highgui.hpp" 5 6 #include <iostream> 7 #include <ctype.h> 8 #include <fstream> 9 #include <algorithm> 10 using namespace std; 11 12 13 using namespace cv; 14 void LoadImages(const string &strImagePath, const string &strPathTimes, 15 vector<string> &vstrImages, vector<double> &vTimeStamps) 16 { 17 ifstream fTimes; 18 fTimes.open(strPathTimes.c_str()); 19 vTimeStamps.reserve(5000); 20 vstrImages.reserve(5000); 21 while(!fTimes.eof()) 22 { 23 string s; 24 getline(fTimes,s); 25 if(!s.empty()) 26 { 27 stringstream ss; 28 ss << s; 29 vstrImages.push_back(strImagePath + "/" + ss.str() + ".png"); 30 double t; 31 ss >> t; 32 vTimeStamps.push_back(t/1e9); 33 34 } 35 } 36 } 37 static void help() 38 { 39 // print a welcome message, and the OpenCV version 40 cout << " This is a demo of Lukas-Kanade optical flow lkdemo(), " 41 "Using OpenCV version " << CV_VERSION << endl; 42 cout << " It uses camera by default, but you can provide a path to video as an argument. "; 43 cout << " Hot keys: " 44 " ESC - quit the program " 45 " r - auto-initialize tracking " 46 " c - delete all the points " 47 " n - switch the "night" mode on/off " 48 "To add/remove a feature point click it " << endl; 49 } 50 51 Point2f point; 52 bool addRemovePt = false; 53 54 static void onMouse( int event, int x, int y, int /*flags*/, void* /*param*/ ) 55 { 56 if( event == EVENT_LBUTTONDOWN ) 57 { 58 point = Point2f((float)x, (float)y); 59 addRemovePt = true; 60 } 61 } 62 63 int main( int argc, char** argv ) 64 { 65 VideoCapture cap; 66 TermCriteria termcrit(TermCriteria::COUNT|TermCriteria::EPS,20,0.03); 67 Size subPixWinSize(10,10), winSize(31,31); 68 69 const int MAX_COUNT = 500; 70 bool needToInit = false; 71 bool nightMode = false; 72 73 74 namedWindow( "LK Demo", 1 ); 75 setMouseCallback( "LK Demo", onMouse, 0 ); 76 77 Mat gray, prevGray, image, frame; 78 vector<Point2f> points[2]; 79 80 vector<string> vstrImageFilenames; 81 vector<double> vstrstamps; 82 LoadImages(string(argv[1]), string(argv[2]), vstrImageFilenames, vstrstamps); 83 for(int i=0;i<vstrImageFilenames.size();i++) 84 { 85 86 image = imread(vstrImageFilenames[i],IMREAD_COLOR); 87 cvtColor(image, gray, COLOR_BGR2GRAY); 88 89 if( nightMode ) 90 image = Scalar::all(0); 91 92 if( needToInit ) 93 { 94 // automatic initialization 95 goodFeaturesToTrack(gray, points[1], MAX_COUNT, 0.01, 10, Mat(), 3, 0, 0.04); 96 cornerSubPix(gray, points[1], subPixWinSize, Size(-1,-1), termcrit); 97 addRemovePt = false; 98 } 99 else if( !points[0].empty() ) 100 { 101 vector<uchar> status; 102 vector<float> err; 103 if(prevGray.empty()) 104 gray.copyTo(prevGray); 105 calcOpticalFlowPyrLK(prevGray, gray, points[0], points[1], status, err, winSize, 106 3, termcrit, 0, 0.001); 107 size_t i, k; 108 for( i = k = 0; i < points[1].size(); i++ ) 109 { 110 if( addRemovePt ) 111 { 112 if( norm(point - points[1][i]) <= 5 ) 113 { 114 addRemovePt = false; 115 continue; 116 } 117 } 118 119 if( !status[i] ) 120 continue; 121 122 points[1][k++] = points[1][i]; 123 circle( image, points[1][i], 3, Scalar(0,255,0), -1, 8); 124 } 125 points[1].resize(k); 126 } 127 128 if( addRemovePt && points[1].size() < (size_t)MAX_COUNT ) 129 { 130 vector<Point2f> tmp; 131 tmp.push_back(point); 132 cornerSubPix( gray, tmp, winSize, Size(-1,-1), termcrit); 133 points[1].push_back(tmp[0]); 134 addRemovePt = false; 135 } 136 137 needToInit = false; 138 imshow("LK Demo", image); 139 140 char c = (char)waitKey(10); 141 if( c == 27 ) 142 break; 143 switch( c ) 144 { 145 case 'r': 146 needToInit = true; 147 break; 148 case 'c': 149 points[0].clear(); 150 points[1].clear(); 151 break; 152 case 'n': 153 nightMode = !nightMode; 154 break; 155 } 156 157 std::swap(points[1], points[0]); 158 cv::swap(prevGray, gray); 159 } 160 161 return 0; 162 }