#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
Mat frame, gray;
Mat prev_frame, prev_gray;
vector<Point2f> features; // shi-tomasi角點檢測 - 特征資料
vector<Point2f> iniPoints; // 初始化特征資料
vector<Point2f> fpts[2]; // 保持當前幀和前一幀的特征點位置
vector<uchar> status; // 特征點跟蹤成功標志位
vector<float> errors; // 跟蹤時候區域誤差和
void drawFeature(Mat &inFrame);
void detectFeatures(Mat &inFrame, Mat &ingray);
void klTrackFeature();
void drawTrackLines();
int main(int argc, char** argv) {
//VideoCapture capture(0);
VideoCapture capture;
capture.open("bike.avi");
if (!capture.isOpened()) {
printf("could not load video file...\n");
return -1;
}
namedWindow("camera input", 0);
while (capture.read(frame)) {
// flip(frame, frame, 1);
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("沒有檢測,持續追蹤...\n");
}
if (prev_gray.empty()) {
gray.copyTo(prev_gray);
}
klTrackFeature();
// 更新前一幀資料
gray.copyTo(prev_gray);
frame.copyTo(prev_frame);
imshow("camera input", frame);
char c = waitKey(50);
if (c == 27) {
break;
}
}
waitKey(0);
return 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);
cout << "detect features : " << features.size() << endl;
}
void klTrackFeature() {
// KLT
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);
/*
1.calcOpticalFlowPyrLK函式作用是對輸入的特征點fpts[0],根據下一幀的影像對這些特征點判定是不是光流,
檢測結束后,status的每個下標會保存答案,再進行判斷即可。
2.initPoints集合用于存放初始化特征資料,每次的calcOpticalFlowPyrLK后都會重新更新一次,用status判斷判斷有沒有新的特征是可以追蹤的,或者用status判斷哪些舊的特征可以不要了,
3.fpts[1]集合用于存放當前幀的資料,
*/
if (dist > 2 && status[i]) {
iniPoints[k] = iniPoints[i];
fpts[1][k++] = fpts[1][i];
//1.將用KLT演算法找到的特征點集fpts[1]進行篩選,將沒用的點去除,
//沒用的點包括距離太小沒有變化和status的狀態
//2.將有用的點放進fpts[1]中
}
}
// 保存特征點并繪制跟蹤軌跡
iniPoints.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, iniPoints[t], fpts[1][t], Scalar(0, 255, 0), 1, 8, 0);
circle(frame, fpts[1][t], 2, Scalar(0, 0, 255), 2, 8, 0);
}
}
這個程式中呼叫了calcOpticalFlowPyrLK函式,其中傳入的特征點集是fpts[0],我不明白這個程式在視頻中出現移動物體時是怎么進入迭代的。按理說,當前幀gray得到的特征點集feature都用insert插入到了fpts[0]中,然后送入追蹤函式klTrackFeature()讓calcOpticalFlowPyrLK去檢測。
但是這個函式要求輸入的是前一幀的特征點集,然后回傳它們在當前幀對應的光流點集。那現在往里輸入的卻是當前幀特征點集,那會回傳出什么呢?這里我看起來意義不明,有沒有哪位大神解答一下
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/143498.html
標籤:工具平臺和程序庫
上一篇:Python基礎-05串列
