欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于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);
	}
}
相关标签: OpenCV