光流金字塔calcOpticalFlowPyrLK
2015-10-14 10:23
519 查看
金字塔Lucas-Kanande光流
C++: void calcOpticalFlowPyrLK(InputArray prevImg,
InputArray nextImg, InputArray prevPts, InputOutputArraynextPts,
OutputArray status, OutputArray err, Size winSize=Size(21,21),
int maxLevel=3, TermCriteriacriteria=TermCriteria(TermCriteria::COUNT+TermCriteria::EPS,
30, 0.01), int flags=0, double minEigThreshold=1e-4 )
C++: void calcOpticalFlowPyrLK(InputArray prevImg,
InputArray nextImg, InputArray prevPts, InputOutputArraynextPts,
OutputArray status, OutputArray err, Size winSize=Size(21,21),
int maxLevel=3, TermCriteriacriteria=TermCriteria(TermCriteria::COUNT+TermCriteria::EPS,
30, 0.01), int flags=0, double minEigThreshold=1e-4 )
Parameters: |
---|
prevImg – first 8-bit input image or pyramid constructed by buildOpticalFlowPyramid(). 第一个8位输入图像或者通过 buildOpticalFlowPyramid()建立的金字塔 nextImg – second input image or pyramid of the same size and the same type as prevImg. 第二个输入图像或者和prevImg相同尺寸和类型的金字塔 prevPts – vector of 2D points for which the flow needs to be found; point coordinates must be single-precision floating-point numbers. 二维点向量存储找到的光流;点坐标必须是单精度浮点数 nextPts – output vector of 2D points (with single-precision floating-point coordinates) containing the calculated new positions of input features in the second image; when OPTFLOW_USE_INITIAL_FLOW flag is passed, the vector must have the same size as in the input. 输出二维点向量(用单精度浮点坐标)包括第二幅图像中计算的输入特征的新点位置;当OPTFLOW_USE_INITIAL_FLOW 标志通过,向量必须有和输入一样的尺寸。 status – output status vector (of unsigned chars); each element of the vector is set to 1 if the flow for the corresponding features has been found, otherwise, it is set to 0. 输出状态向量(无符号char);如果相应的流特征被发现,向量的每个元素被设置为1,否则,被置为0. err – output vector of errors; each element of the vector is set to an error for the corresponding feature, type of the error measure can be set in flags parameter; if the flow wasn’t found then the error is not defined (use the status parameter to find such cases). 输出错误向量;向量的每个元素被设为相应特征的一个错误,误差测量的类型可以在flags参数中设置;如果流不被发现然后错误未被定义(使用status(状态)参数找到此情形)。 winSize – size of the search window at each pyramid level. 在每个金字塔水平搜寻窗口的尺寸。 maxLevel – 0-based maximal pyramid level number; if set to 0, pyramids are not used (single level), if set to 1, two levels are used, and so on; if pyramids are passed to input then algorithm will use as many levels as pyramids have but no more than maxLevel. criteria – parameter, specifying the termination criteria of the iterative search algorithm (after the specified maximum number of iterations criteria.maxCount or when the search window moves by less than criteria.epsilon. flags – operation flags: OPTFLOW_USE_INITIAL_FLOW uses initial estimations, stored in nextPts; if the flag is not set, then prevPts is copied to nextPts and is considered the initial estimate. OPTFLOW_LK_GET_MIN_EIGENVALS use minimum eigen values as an error measure (seeminEigThreshold description); if the flag is not set, then L1 distance between patches around the original and a moved point, divided by number of pixels in a window, is used as a error measure. minEigThreshold – the algorithm calculates the minimum eigen value of a 2x2 normal matrix of optical flow equations (this matrix is called a spatial gradient matrix in [Bouguet00]), divided by number of pixels in a window; if this value is less than minEigThreshold, then a corresponding feature is filtered out and its flow is not processed, so it allows to remove bad points and get a performance boost. #include "opencv2/video/tracking.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <iostream> #include <ctype.h> using namespace cv; using namespace std; 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 == CV_EVENT_LBUTTONDOWN ) { point = Point2f((float)x, (float)y); addRemovePt = true; } } int main( int argc, char** argv ) { help(); VideoCapture cap; TermCriteria termcrit(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS, 20, 0.03); Size subPixWinSize(10,10), winSize(31,31); const int MAX_COUNT = 500; bool needToInit = false; bool nightMode = false; if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0]))) cap.open(argc == 2 ? argv[1][0] - '0' : 0); else if( argc == 2 ) cap.open(argv[1]); if( !cap.isOpened() ) { cout << "Could not initialize capturing...\n"; return 0; } namedWindow( "LK Demo", 1 ); setMouseCallback( "LK Demo", onMouse, 0 ); Mat gray, prevGray, image; vector<Point2f> points[2]; for(;;) { Mat frame; cap >> frame; if( frame.empty() ) break; frame.copyTo(image); cvtColor(image, gray, COLOR_BGR2GRAY); if( nightMode ) image = Scalar::all(0); if( needToInit ) { // automatic initialization goodFeaturesToTrack(gray, points[1], MAX_COUNT, 0.01, 10, Mat(), 3, 0, 0.04); cornerSubPix(gray, points[1], subPixWinSize, Size(-1,-1), termcrit); addRemovePt = false; } else if( !points[0].empty() ) { vector<uchar> status; vector<float> err; if(prevGray.empty()) gray.copyTo(prevGray); calcOpticalFlowPyrLK(prevGray, gray, points[0], points[1], status, err, winSize, 3, termcrit, 0, 0.001); size_t i, k; for( i = k = 0; i < points[1].size(); i++ ) { if( addRemovePt ) { if( norm(point - points[1][i]) <= 5 ) { addRemovePt = false; continue; } } if( !status[i] ) continue; points[1][k++] = points[1][i]; circle( image, points[1][i], 3, Scalar(0,255,0), -1, 8); } points[1].resize(k); } if( addRemovePt && points[1].size() < (size_t)MAX_COUNT ) { vector<Point2f> tmp; tmp.push_back(point); cornerSubPix( gray, tmp, winSize, cvSize(-1,-1), termcrit); points[1].push_back(tmp[0]); addRemovePt = false; } needToInit = false; imshow("LK Demo", image); char c = (char)waitKey(10); if( c == 27 ) break; switch( c ) { case 'r': needToInit = true; break; case 'c': points[0].clear(); points[1].clear(); break; case 'n': nightMode = !nightMode; break; } std::swap(points[1], points[0]); cv::swap(prevGray, gray); } return 0; } |
相关文章推荐
- 10月第1周全球域名商(国际域名)新增注册量TOP15
- Expression Add Operators -- leetcode
- Centos下如何截图
- CentOS用host、dig、nslookup查询DNS命令
- VMware中CentOS设置静态IP
- Linux下Tomcat开机自动启动
- eclipse报错之Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds
- I.MX6 Linux U-boot 环境变量解析
- centos 64位系统安装
- 【nginx运维基础(3)】Nginx的编译PHP
- bash基础
- nginx+uwsgi+django+python 应用架构部署
- 【Linux常识篇(2)】理解inode
- Sqoop源码编译与分析(V1.4.6)
- Dubbo架构设计详解
- Bash的环境配置文件
- 【Linux高频命令专题(19)】vi/vim
- Linux集群系统Heartbeat
- linux下mysql的root密码忘记解决方
- centos7 搭建ntp时钟服务