#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
// 使用ORB特征检测器和描述符提取器
Ptr<ORB> detector = ORB::create();
// 特征匹配器
BFMatcher matcher(NORM_HAMMING);
int main()
{
// 打开视频文件
VideoCapture cap("video0.mp4");
if (!cap.isOpened())
{
cerr << "无法打开视频文件" << endl;
return -1;
}
// 存储前一帧的特征点和描述符
Mat prevFrame, prevDescriptors;
vector<KeyPoint> prevKeypoints;
// 读取第一帧
if (!cap.read(prevFrame))
{
cerr << "无法读取视频帧" << endl;
return -1;
}
// 调整帧大小
resize(prevFrame, prevFrame, Size(1280, 960));
// 提取第一帧的特征
detector->detectAndCompute(prevFrame, noArray(), prevKeypoints, prevDescriptors);
namedWindow("Video", WINDOW_NORMAL);
resizeWindow("Video", 1280, 960);
int i = 0;
while (true)
{
Mat frame, descriptors;
vector<KeyPoint> keypoints;
// 读取下一帧
if (!cap.read(frame))
break;
// 提取当前帧的特征
detector->detectAndCompute(frame, noArray(), keypoints, descriptors);
// 进行特征匹配
vector<DMatch> matches;
matcher.match(prevDescriptors, descriptors, matches);
// 筛选好的匹配点
double max_dist = 0;
double min_dist = 100;
for (int i = 0; i < prevDescriptors.rows; i++)
{
double dist = matches[i].distance;
if (dist < min_dist)
min_dist = dist;
if (dist > max_dist)
max_dist = dist;
}
vector<DMatch> good_matches;
for (int i = 0; i < prevDescriptors.rows; i++)
{
if (matches[i].distance <= max(2 * min_dist, 30.0))
{
good_matches.push_back(matches[i]);
}
}
// 统计提取的特征数量和正确追踪的特征数量
int extractedFeatures = keypoints.size();
int trackedFeatures = good_matches.size();
cout << "第" << ++i << "次提取的特征数量: " << extractedFeatures << endl;
cout << "正确追踪的特征数量: " << trackedFeatures << endl;
cout << "--------------------------------------------------" << endl;
// 可视化匹配结果
Mat img_matches;
drawMatches(prevFrame, prevKeypoints, frame, keypoints, good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
// 在图像上显示特征数量信息
stringstream ss;
ss << "提取的特征数量: " << extractedFeatures << " 正确追踪的特征数量: " << trackedFeatures;
putText(img_matches, ss.str(), Point(10, img_matches.rows - 10), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 1, LINE_AA);
imshow("Video", img_matches);
// 更新上一帧的数据
prevFrame = frame.clone();
prevKeypoints = keypoints;
prevDescriptors = descriptors;
// 等待30ms,按下任意键退出
char c = (char)waitKey(30);
if (c == 27)
break; // 按下ESC键退出
}
return 0;
}
读取视频前后帧特征追踪