OpenCV 基于Lucas-Kanade光流算法的对象跟踪
视频来源:https://www.youtube.com/watch?v=EvIwL0aSCZY
以下代码用OpenCV实现了视频中基于Lucas-Kanade光流算法【OpenCV中的实现为calcOpticalFlowPyrLK函数】的对象跟踪。为了规避孔径问题,以下代码实现仅对角点【通过goodFeaturesToTrack函数做角点检测】做光流计算。
//
// main.cpp
// opencv-learning
//
// Created by _R on 2019/1/9.
// Copyright © 2019 _R. All rights reserved.
//
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main(int argc, char* argv[])
{
VideoCapture video = VideoCapture("/Users/_R/Desktop/Flying_disc_freestyle_640x360.mp4");
if (!video.isOpened()) {
cout << "could not load video file ..." << endl;
return -1;
}
Mat frame, frame_in_gray, prev_frame, prev_frame_in_gray;
vector<Point2f> initPoints;
vector<Point2f> feature_points[2];
vector<uchar> status_of_feature_points;
vector<float> errors;
double count_of_success = 0;
double distance_between_feature_points = 0.0;
namedWindow("flying_disc", WINDOW_AUTOSIZE);
while (video.read(frame)) {
cvtColor(frame, frame_in_gray, COLOR_BGR2GRAY);
if (feature_points[0].empty() || initPoints.size() < 10) {
goodFeaturesToTrack(frame_in_gray, feature_points[0], 1000, 0.01, 10.0);
initPoints.assign(feature_points[0].begin(), feature_points[0].end());
} else {
goodFeaturesToTrack(frame_in_gray, feature_points[1], 1000, 0.01, 10.0);
calcOpticalFlowPyrLK(prev_frame_in_gray, frame_in_gray, feature_points[0], feature_points[1], status_of_feature_points, errors);
count_of_success = 0;
for (size_t t=0; t<status_of_feature_points.size(); t++) {
distance_between_feature_points = abs(feature_points[0][t].x - feature_points[1][t].x) + abs(feature_points[0][t].y - feature_points[1][t].y);
if (distance_between_feature_points > 2 && status_of_feature_points[t]) {
initPoints[count_of_success] = initPoints[t];
feature_points[1][count_of_success] = feature_points[1][t];
count_of_success++;
}
}
initPoints.resize(count_of_success);
feature_points[1].resize(count_of_success);
std::swap(feature_points[0], feature_points[1]);
cout << initPoints.size() << " " << feature_points[0].size() << endl;
for (size_t t=0; t<feature_points[0].size(); t++) {
cout << "(" << initPoints[t].x << "," << initPoints[t].y << ")" << " " << "(" << feature_points[0][t].x << "," << feature_points[0][t].y << ")" << endl;
line(frame, initPoints[t], feature_points[0][t], Scalar(0,255,0));
circle(frame, feature_points[0][t], 2, Scalar(0,0,255));
}
cout << endl;
}
frame.copyTo(prev_frame);
frame_in_gray.copyTo(prev_frame_in_gray);
imshow("flying_disc", frame);
char c = waitKey(50);
if (c == 27) {
break;
}
}
waitKey(0);
video.release();
return 0;
}