在开始跟踪前,首先要在初始帧中检测特征点,之后在下一帧中尝试跟踪这些点。你必须找到新的图像帧中这些点的位置。很明显的,由于我们处理的是视频序列,很有可能特征点所在的物体已经移动过(运动也有可能是相机引起的)。因此,你必须在特征点的先前位置附近进行搜索,以找到下一帧中它的新位置。这正是cv::calcOpticalFlowPyrLK函数所实现的工作。你输入两个连续的图像帧以及第一幅图像中检测到的特征点数组,该函数将返回一组新的特征点为位置。为了跟踪完整的序列,你需要在帧与帧之间重复这个过程,不可避免地你也会丢失其中一些点,于是被跟踪的特征点数目会减少。为了解决这个问题,我们可以不时地检测新的特征值。
// OpticalFlow.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <opencv2\opencv.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
using namespace std;
using namespace cv;
//帧处理基类
class FrameProcessor
{
public:
virtual void process(Mat &input,Mat &ouput)=0;
};
class FeatureTracker:public FrameProcessor
{
Mat gray;//当前灰度图像
Mat gray_prev;//之前灰度图像
//两幅图像间跟踪的特征点 0->1
vector<Point2f>points[2];
//跟踪的点的初始位置
vector<Point2f>initial;
vector<Point2f>features;//检测到的特征
int max_count;//需要跟踪的最大特征数目
double qlevel;//特征检测中的质量等级
double minDist;//两点之间的最小距离
vector<uchar>status;//检测到的特征的状态
vector<float>err;//跟踪过程中的错误
public:
FeatureTracker():max_count(500),qlevel(0.01),minDist(10.){}
void process(Mat &frame,Mat &output)
{
//转换为灰度图像
cvtColor(frame,gray,CV_BGR2GRAY);
frame.copyTo(output);
//1.如果需要添加新的特征点
if(addNewPoints())
{
//进行检测
detectFeaturePoints();
//添加检测到的特征到当前跟踪的特征中
points[0].insert(points[0].end(),features.