您的位置:首页 > 运维架构

光流金字塔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 )

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;

}



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: