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 -> 退出
修改后的程序:
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp" #include <iostream>
#include <ctype.h>
#include <fstream>
#include <algorithm>
using namespace std; using namespace cv;
void LoadImages(const string &strImagePath, const string &strPathTimes,
vector<string> &vstrImages, vector<double> &vTimeStamps)
{
ifstream fTimes;
fTimes.open(strPathTimes.c_str());
vTimeStamps.reserve();
vstrImages.reserve();
while(!fTimes.eof())
{
string s;
getline(fTimes,s);
if(!s.empty())
{
stringstream ss;
ss << s;
vstrImages.push_back(strImagePath + "/" + ss.str() + ".png");
double t;
ss >> t;
vTimeStamps.push_back(t/1e9); }
}
}
static void help()
{
// print a welcome message, and the OpenCV version
cout << "\nThis is a demo of Lukas-Kanade optical flow lkdemo(),\n"
"Using OpenCV version " << CV_VERSION << endl;
cout << "\nIt uses camera by default, but you can provide a path to video as an argument.\n";
cout << "\nHot keys: \n"
"\tESC - quit the program\n"
"\tr - auto-initialize tracking\n"
"\tc - delete all the points\n"
"\tn - switch the \"night\" mode on/off\n"
"To add/remove a feature point click it\n" << endl;
} Point2f point;
bool addRemovePt = false; static void onMouse( int event, int x, int y, int /*flags*/, void* /*param*/ )
{
if( event == EVENT_LBUTTONDOWN )
{
point = Point2f((float)x, (float)y);
addRemovePt = true;
}
} int main( int argc, char** argv )
{
VideoCapture cap;
TermCriteria termcrit(TermCriteria::COUNT|TermCriteria::EPS,,0.03);
Size subPixWinSize(,), winSize(,); const int MAX_COUNT = ;
bool needToInit = false;
bool nightMode = false; namedWindow( "LK Demo", );
setMouseCallback( "LK Demo", onMouse, ); Mat gray, prevGray, image, frame;
vector<Point2f> points[]; vector<string> vstrImageFilenames;
vector<double> vstrstamps;
LoadImages(string(argv[]), string(argv[]), vstrImageFilenames, vstrstamps);
for(int i=;i<vstrImageFilenames.size();i++)
{ image = imread(vstrImageFilenames[i],IMREAD_COLOR);
cvtColor(image, gray, COLOR_BGR2GRAY); if( nightMode )
image = Scalar::all(); if( needToInit )
{
// automatic initialization
goodFeaturesToTrack(gray, points[], MAX_COUNT, 0.01, , Mat(), , , 0.04);
cornerSubPix(gray, points[], subPixWinSize, Size(-,-), termcrit);
addRemovePt = false;
}
else if( !points[].empty() )
{
vector<uchar> status;
vector<float> err;
if(prevGray.empty())
gray.copyTo(prevGray);
calcOpticalFlowPyrLK(prevGray, gray, points[], points[], status, err, winSize,
, termcrit, , 0.001);
size_t i, k;
for( i = k = ; i < points[].size(); i++ )
{
if( addRemovePt )
{
if( norm(point - points[][i]) <= )
{
addRemovePt = false;
continue;
}
} if( !status[i] )
continue; points[][k++] = points[][i];
circle( image, points[][i], , Scalar(,,), -, );
}
points[].resize(k);
} if( addRemovePt && points[].size() < (size_t)MAX_COUNT )
{
vector<Point2f> tmp;
tmp.push_back(point);
cornerSubPix( gray, tmp, winSize, Size(-,-), termcrit);
points[].push_back(tmp[]);
addRemovePt = false;
} needToInit = false;
imshow("LK Demo", image); char c = (char)waitKey();
if( c == )
break;
switch( c )
{
case 'r':
needToInit = true;
break;
case 'c':
points[].clear();
points[].clear();
break;
case 'n':
nightMode = !nightMode;
break;
} std::swap(points[], points[]);
cv::swap(prevGray, gray);
} return ;
}