#include<opencv2/opencv.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
using namespace cv;
using namespace std;
using namespace std;
void track(Mat& frame, Mat& result);
bool addNewPoint();
bool acceptTrackPoint(int i);
bool addNewPoint();
bool acceptTrackPoint(int i);
Mat curgray;//当前图片
Mat pregray;//先前图片
vector<Point2f> point[2];//point[0]是特征点的原来位置,point[1]是特征点的新位置
vector<Point2f> initpoint;//初始化跟踪点的位置
vector<Point> features;//检测到的特征点
int maxCounts=500;//检测的最大特征点数
double qLevel = 0.01;//检测特征的等级
double minDist = 10.0;//检测特征的最小距离
vector<uchar> status;//跟踪特征的状态,发现特征的流为1,否则为0
vector<float> err;//误差矢量
Mat pregray;//先前图片
vector<Point2f> point[2];//point[0]是特征点的原来位置,point[1]是特征点的新位置
vector<Point2f> initpoint;//初始化跟踪点的位置
vector<Point> features;//检测到的特征点
int maxCounts=500;//检测的最大特征点数
double qLevel = 0.01;//检测特征的等级
double minDist = 10.0;//检测特征的最小距离
vector<uchar> status;//跟踪特征的状态,发现特征的流为1,否则为0
vector<float> err;//误差矢量
int main()
{
Mat srcimage, dstimage;
VideoCapture capture(0);
{
Mat srcimage, dstimage;
VideoCapture capture(0);
while (capture.isOpened())
{
capture >> srcimage;
if (!srcimage.data)
{
cerr << "Get picture error!" << endl;
return 0;
}
else
{
track(srcimage, dstimage);
}
if(waitKey(1) == 27)
return 0;
}
waitKey(0);
system("pause");
return 0;
}
{
capture >> srcimage;
if (!srcimage.data)
{
cerr << "Get picture error!" << endl;
return 0;
}
else
{
track(srcimage, dstimage);
}
if(waitKey(1) == 27)
return 0;
}
waitKey(0);
system("pause");
return 0;
}
void track(Mat& frame, Mat& result)
{
cvtColor(frame, curgray, COLOR_BGR2GRAY);
frame.copyTo(result);
if (addNewPoint())
{
//确定图像强角点,并把角点存放在vector<Point2f>的features中
goodFeaturesToTrack(curgray, features, maxCounts, qLevel, minDist);
{
cvtColor(frame, curgray, COLOR_BGR2GRAY);
frame.copyTo(result);
if (addNewPoint())
{
//确定图像强角点,并把角点存放在vector<Point2f>的features中
goodFeaturesToTrack(curgray, features, maxCounts, qLevel, minDist);
//把feature里的角点重头到尾存到point[0]的末尾中
point[0].insert(point[0].end(), features.begin(), features.end());
point[0].insert(point[0].end(), features.begin(), features.end());
//把feature里的角点重头到尾存到initpoint的末尾中
initpoint.insert(initpoint.end(), features.begin(), features.end());
}
if (pregray.empty())
{
curgray.copyTo(pregray);
}
//计算稀疏征集的光流
calcOpticalFlowPyrLK(pregray, curgray, point[0], point[1], status, err);
int k = 0;
for (int i = 0; i < point[1].size(); i++)
{
if (acceptTrackPoint(i))
{
initpoint[k] = initpoint[i];
point[1][k++] = point[1][i];
}
}
point[1].resize(k);//把point[1]中所含有的数量重新变成含有k个
initpoint.resize(k);//把initpoint中所含有的数量重新变成含有k个
initpoint.insert(initpoint.end(), features.begin(), features.end());
}
if (pregray.empty())
{
curgray.copyTo(pregray);
}
//计算稀疏征集的光流
calcOpticalFlowPyrLK(pregray, curgray, point[0], point[1], status, err);
int k = 0;
for (int i = 0; i < point[1].size(); i++)
{
if (acceptTrackPoint(i))
{
initpoint[k] = initpoint[i];
point[1][k++] = point[1][i];
}
}
point[1].resize(k);//把point[1]中所含有的数量重新变成含有k个
initpoint.resize(k);//把initpoint中所含有的数量重新变成含有k个
//绘制角点和运动轨迹
for (int i = 0; i < point[1].size(); i++)
{
line(result, initpoint[i], point[1][i], Scalar(0, 0, 255));
circle(result, point[1][i], 3, Scalar(0, 255, 0), -1);
}
for (int i = 0; i < point[1].size(); i++)
{
line(result, initpoint[i], point[1][i], Scalar(0, 0, 255));
circle(result, point[1][i], 3, Scalar(0, 255, 0), -1);
}
swap(point[1], point[0]);//把point[0]和point[1]的元素交换
swap(pregray, curgray);//把两张图片交换
swap(pregray, curgray);//把两张图片交换
imshow("Optical Flow Demo", result);
}
//function:addNewPoint
//brief:检测新点是否被添加
//return:是否被添加的标志
bool addNewPoint()
{
return point[0].size() <= 10;
}
//brief:检测新点是否被添加
//return:是否被添加的标志
bool addNewPoint()
{
return point[0].size() <= 10;
}
//function:acceptTrackPoint
//brief:决定哪些跟踪点被接受
//return:是否被接受的标志
bool acceptTrackPoint(int i)
{
return status[i] && ((abs(point[0][i].x - point[1][i].x) + abs(point[0][i].y - point[1][i].y)) > 2);
}
//brief:决定哪些跟踪点被接受
//return:是否被接受的标志
bool acceptTrackPoint(int i)
{
return status[i] && ((abs(point[0][i].x - point[1][i].x) + abs(point[0][i].y - point[1][i].y)) > 2);
}