OpenCV LK光流法测试

Posted tszs_song

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV LK光流法测试相关的知识,希望对你有一定的参考价值。

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 -> 退出

 

修改后的程序:

  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 << "\\nThis is a demo of Lukas-Kanade optical flow lkdemo(),\\n"
 41             "Using OpenCV version " << CV_VERSION << endl;
 42     cout << "\\nIt uses camera by default, but you can provide a path to video as an argument.\\n";
 43     cout << "\\nHot keys: \\n"
 44             "\\tESC - quit the program\\n"
 45             "\\tr - auto-initialize tracking\\n"
 46             "\\tc - delete all the points\\n"
 47             "\\tn - switch the \\"night\\" mode on/off\\n"
 48             "To add/remove a feature point click it\\n" << 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 }
View Code

 

参考:goodFeaturesToTrack函数详细注释

以上是关于OpenCV LK光流法测试的主要内容,如果未能解决你的问题,请参考以下文章

运动目标检测——光流法与opencv代码实现

如何使用opencv实现金字塔光流lk跟踪算法

DeepFlow高效的光流匹配算法(下)

光流法详解之二(HS光流)

基于 OpenCV 图像的光流场

opencv光流法