对象跟踪三要素:图像表示,外观模型,移动模型
KLT(Lucas Kanade Tracker)条件:亮度恒定,近距离移动,空间一致性
稀疏光流:Sparse Optical Flow
找到特征点: 角点检测法
代码:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
Mat frame,gray;
Mat prev_frame,prev_gray;
vector<Point2f> features;
vector<Point2f> iniPoints;
vector<Point2f> fpts[2];
vector<uchar> status;
vector<float> errors;
//void drawFeature(Mat &inFrame)
//{
// for(size_t t = 0;t < features.size();t++)
// {
// circle(inFrame,features[t],2, Scalar(0,0,255),2,8,0);
// }
//}
void drawFeature(Mat &inFrame)
{
for(size_t t = 0;t < fpts[0].size();t++)
{
//画圆点
circle(inFrame,fpts[0][t],2, Scalar(0,0,255),2,8,0);
}
}
void detectFeatures(Mat &inFrame,Mat &ingray)
{
double MaxCorners = 5000;
double qualitylevel = 0.01;
double minDistance = 10;
double blockSize = 3;
double k= 0.04;
//特征跟踪
goodFeaturesToTrack(ingray,features,MaxCorners,qualitylevel,minDistance,Mat(),blockSize,false,k);
printf("[%s][%d]detect features:%d\n",__FUNCTION__,__LINE__,features.size());
}
void drawTrackLines()
{
for(size_t t = 0;t < fpts[1].size();t++)
{
line(frame,iniPoints[t],fpts[1][t],Scalar(0,255,0),2,8,0);
circle(frame,fpts[1][t],2, Scalar(0,0,255),2,8,0);
}
}
void klTrackFeature()
{
calcOpticalFlowPyrLK(prev_gray,gray,fpts[0],fpts[1],status,errors);
int k = 0;
for(int i=0; i<fpts[1].size();i++)
{
double dist =abs(fpts[0][i].x - fpts[1][i].x) + abs(fpts[0][i].y -fpts[1][i].y);
if(dist > 2 && status[i])
{
iniPoints[k] = iniPoints[i];
fpts[1][k++] = fpts[1][i];
}
}
iniPoints.resize(k);
fpts[1].resize(k);
drawTrackLines();
std::swap(fpts[1],fpts[0]);
}
int main(int argc, char** argv)
{
VideoCapture capture(0);
//capture.open("./video/bike.avi");
//capture.open("./video/video_006.mp4");
//VideoCapture capture(0);
if(!capture.isOpened())
{
printf("[%s][%d]could not load video data...\n",__FUNCTION__,__LINE__);
return -1;
}
while(capture.read(frame))
{
//转化为灰度图像
cvtColor(frame,gray,COLOR_BGR2GRAY);
if(fpts[0].size()<40)
{
detectFeatures(frame,gray);
fpts[0].insert(fpts[0].end(),features.begin(),features.end());
iniPoints.insert(iniPoints.end(),features.begin(),features.end());
}
else
{
printf("TTTTTTTTTTTTT\n");
}
if(prev_gray.empty())
{
gray.copyTo(prev_gray);
}
klTrackFeature();
drawFeature(frame);
//保存上一针的图像
gray.copyTo(prev_gray);
frame.copyTo(prev_frame);
imshow("input",frame);
if(waitKey(33) == 27)
{
break;
}
}
capture.release();
waitKey(0);
return 0;
}
稠密光流:Dense Optical Flow
相关函数:
calcOpticalFlowFarneback() 稠密光流
代码:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void drawOpticalFlowHF(Mat &flowdata, Mat &image,int step)
{
for(int row = 0;row <image.rows;row++)
{
for(int col = 0;col<image.cols;col++)
{
const Point2f fxy = flowdata.at<Point2f>(row, col);
if(fxy.x >2||fxy.y >2)
{
line(image,Point(col,row),Point(cvRound(col+fxy.x),cvRound(row+fxy.y)),Scalar(0,255,0),2,8,0);
circle(image,Point(col,row),2,Scalar(0,0,255),-1);
}
}
}
}
int main(int argc, char** argv)
{
#if 1
VideoCapture capture;
//capture.open("./video/bike.avi");
capture.open("./video/video_003.avi");
//capture.open("./video/video_006.mp4");
#else
VideoCapture capture(0);
#endif
if(!capture.isOpened())
{
printf("[%s][%d]could not load video data...\n",__FUNCTION__,__LINE__);
return -1;
}
Mat frame,gray;
Mat prev_frame,prev_gray;
Mat flowResult,flowdata;//光流的结果,以及数据
capture.read(frame);
imshow("input1",frame);
cvtColor(frame,prev_gray,COLOR_BGR2GRAY);
while(capture.read(frame))
{
cvtColor(frame,gray,COLOR_BGR2GRAY);
if(!prev_gray.empty())
{
calcOpticalFlowFarneback(prev_gray,gray,flowdata,0.5,3,15,3,5,1.2,0);
cvtColor(prev_gray,flowResult,COLOR_GRAY2BGR);
drawOpticalFlowHF(flowdata,flowResult,1);
imshow("flow",flowResult);
imshow("input",frame);
}
if(waitKey(33) == 27)
{
break;
}
}
capture.release();
waitKey(0);
return 0;
}