基于LK光流的点特征跟踪
程序员文章站
2022-06-15 09:46:47
...
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
Mat frame, gray;//定义原图像 灰度图像
Mat prev_frame, prev_gray;//表示前一帧的图像帧,前一帧的图像帧的灰度图
vector<Point2f> features;//shi-tomasi角点特征检测数据 存入到features
vector<Point2f> inPoints;//初始化特征数据 用于光流跟踪
vector<Point2f> fpts[2];//保存当前帧和前一帧的特征点数据的位置,表示前一帧fpts[0] 表示当前fpts[1]
vector<uchar> status;//特征点是否成功的标志位
vector<float> errors;//跟踪时区域误差和
void detectFratures(Mat &inFrame, Mat &inGray);
void drawFeature(Mat &inframe);
void lkTrackFeatures();
void drawTrackLines();
int main(){
//frame = imread("G:/learning/OPENCV/LK/LK/LK.mp4");
VideoCapture capture;
capture.open("G:/learning/OPENCV/LK/LK/LK.mp4");
if (!capture.isOpened()){
cout << "could not load video file!" << endl;
return -1;
}
namedWindow("Camera output",1);
while (capture.read(frame)){
cvtColor(frame, gray, COLOR_BGR2GRAY);
if (fpts[0].size() < 40){
detectFratures(frame, gray);
fpts[0].insert(fpts[0].end(),features.begin(),features.end());
inPoints.insert(inPoints.end(), features.begin(), features.end());
}
else{
cout << "ttttt--------" << endl;
}
detectFratures(frame, gray);
drawFeature(frame);
//如果前一帧为空 ,则表示第一帧,将第一帧的gray 拷贝到前一帧
if (prev_gray.empty()){
gray.copyTo(prev_gray);
}
lkTrackFeatures();//跟踪
drawFeature(frame);//显示跟踪效果
//数据更新
gray.copyTo(prev_gray);
frame.copyTo(prev_frame);
imshow("camera input", frame);
char c = waitKey(50);
if (c == 27){
break;
}
}
return 0;
}
void detectFratures(Mat &inFrame, Mat &inGray) {
double maxCorners = 5000;
double qualityLevel = 0.01;
double minDistance = 10;
double blockSize = 1;
double k = 0.04;
goodFeaturesToTrack(inGray, features, maxCorners, qualityLevel, minDistance, Mat(), blockSize, false, k);
cout << "detectFratures---------" << endl;
}
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 lkTrackFeatures(){
//光流法跟踪
calcOpticalFlowPyrLK(prev_gray, gray, fpts[0], fpts[1], status, errors,Size(21,21),1);
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]){
inPoints[k] = inPoints[i];
fpts[1][k++] = fpts[1][i];
}
}
//保存特征点并绘制跟踪轨迹
inPoints.resize(k);
fpts[1].resize(k);
drawTrackLines();
std::swap(fpts[1], fpts[0]);
}
//跟踪轨迹绘制
void drawTrackLines(){
for (size_t t = 0; t < fpts[1].size(); t++){
line(frame, inPoints[t], fpts[1][t], Scalar(0, 255, 0), 2, 8, 0);
circle(frame, fpts[1][t], 2, Scalar(0, 0, 255), 2, 8, 0);
}
}