**
前言
**
只要接口到手,不管烫不烫拿着就用。
**
FLANN特征点匹配
**
FLANN与SURF匹配使用上区别不大,只是在匹配和绘制之间多了
- 快速计算关键点间的最大最小距离
- 保存符合条件的匹配结果
这两步。对匹配后的输出图进行了处理,然后才绘制。
#include<opencv2/opencv.hpp>
#include<iostream>
#include<opencv2/xfeatures2d.hpp>
using namespace std;
using namespace cv;
int main() {
Mat img_1 = imread("E:/File/1.jpg");
Mat img_2 = imread("E:/File/2.jpg");
resize(img_1, img_1, Size(400, 400));
resize(img_2, img_2, Size(400, 400));
if (!img_1.data || !img_2.data) {
cout << "ERROR";
system("pause");
}
//SURF检测关键点
int minHessian = 300;
Ptr<xfeatures2d::SURF> detector = xfeatures2d::SURF::create(minHessian);
vector<KeyPoint> keypoints_1, keypoints_2;
detector->detect(img_1, keypoints_1);
detector->detect(img_2, keypoints_2);
//计算描述符(特征向量)
Ptr<xfeatures2d::SURF> extrator = xfeatures2d::SURF::create();
Mat desriptors_1, desriptors_2;
extrator->compute(img_1, keypoints_1, desriptors_1);
extrator->compute(img_2, keypoints_2, desriptors_2);
//采用FLANN算法匹配描述符向量
Ptr<FlannBasedMatcher> matcher = FlannBasedMatcher::create();
vector<DMatch> matches;
matcher->match(desriptors_1, desriptors_2, matches);
//快速计算关键点间的最大最小距离
double max_dist = 0, min_dist = 100;
for (int i = 0; i < desriptors_1.rows; ++i) {
double dist = matches[i].distance;
if (dist < min_dist)min_dist = dist;
if (dist > max_dist)max_dist = dist;
}
//输出距离信息
printf(">最大距离(Max dist)> %f\n", max_dist);
printf(">最小距离(Min dist) > %f\n", min_dist);
//保存匹配结果小于2*min_dist的点
vector<DMatch> good_matches;
for (int i = 0; i < desriptors_1.rows; ++i) {
if (matches[i].distance < 2 * min_dist)
good_matches.push_back(matches[i]);
}
//绘制出符合条件的匹配点
Mat img_matches;
drawMatches(img_1, keypoints_1,
img_2, keypoints_2,
good_matches,//1到2的匹配点
img_matches,//输出图像
Scalar::all(-1),
Scalar::all(-1),
vector<char>(),
DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
//输出相关匹配点信息
for (int i = 0; i < good_matches.size(); ++i) {
printf(">符合条件的匹配点 [%d] 特征点1> %d ----- 特征点2> %d\n",
i, good_matches[i].queryIdx, good_matches[i].trainIdx);
}
//显示效果图
imshow("匹配效果图", img_matches);
while (char(waitKey(10)) < 0)
;
destroyAllWindows();
}
**
FLANN结合SURF进行关键点的描述和匹配
**
#include<opencv2/opencv.hpp>
#include<iostream>
#include<opencv2/xfeatures2d.hpp>
using namespace std;
using namespace cv;
int main() {
Mat trainImage = imread("E:/File/noknown.jpg");
resize(trainImage, trainImage, Size(400, 400));
if (trainImage.empty()) {
cout << "ERROR";
system("pause");
}
Mat trainImage_gray;
imshow("原始图", trainImage);
cvtColor(trainImage, trainImage_gray, COLOR_BGR2GRAY);
//检测SURF关键点,提取训练图像描述符
vector<KeyPoint> train_keypoint;
Mat trainDescriptor;
int minHessian = 80;
Ptr<xfeatures2d::SURF> feature_detector = xfeatures2d::SURF::create(minHessian);
feature_detector->detect(trainImage_gray, train_keypoint);
Ptr<xfeatures2d::SURF> feature_extractor = xfeatures2d::SURF::create();
feature_extractor->compute(trainImage_gray, train_keypoint, trainDescriptor);
//创建基于FLANN的描述符对象
Ptr<FlannBasedMatcher> matcher=FlannBasedMatcher::create();
vector<Mat> train_desc_collection(1, trainDescriptor);
matcher->add(train_desc_collection);
matcher->train();
//创建视频对象,定义帧率
VideoCapture cap(0);//0打开摄像头
unsigned int frameCount = 0;//帧数
//打算统计平均帧率
double averageFrameRate = 0, formerFrameRate = 0;
//
while (char(waitKey(1)) != 'q') {
//参数设置
int64 time0 = getTickCount();
Mat testImage, testImage_gray;
cap >> testImage;//采集视频帧到testImage中
if (testImage.empty())
continue;
//转换成灰度
cvtColor(testImage, testImage_gray, COLOR_BGR2GRAY);
//检测关键点,提取测试图像描述符
vector<KeyPoint> test_keypoint;
Mat testDescriptor;
feature_detector->detect(testImage_gray, test_keypoint);
feature_extractor->compute(testImage_gray, test_keypoint, testDescriptor);
//匹配训练和测试描述符
vector<vector<DMatch>> matches;
matcher->knnMatch(testDescriptor, matches, 2);
//根据劳式算法(Lowe's algorithm),得到优秀的匹配点
vector<DMatch> goodMatches;
for (unsigned int i = 0; i < matches.size(); ++i) {
if (matches[i][0].distance < 0.6 * matches[i][1].distance)
goodMatches.push_back(matches[i][0]);
}
//绘制匹配点
Mat drawing;
drawMatches(testImage, test_keypoint,
trainImage, train_keypoint,
goodMatches,
drawing);
imshow("匹配窗口", drawing);
double frameRate = getTickFrequency() / (getTickCount() - time0);
averageFrameRate = (frameRate + formerFrameRate) / 2;
if (frameRate != 0 && averageFrameRate != 0)
cout << "当前帧率为>>>" << frameRate << "\t>>>平均帧率 > " << averageFrameRate << endl;
formerFrameRate = averageFrameRate;
}
destroyAllWindows();
}
**
SIFT配合暴力匹配进行关键点描述和提取
**
理论上,SURF是SIFT速度的3倍。
下面是一个SIFT算法配合暴力匹配的示例程序,看看SURF算法波SIFT更快(由于匹配方式不同,这里只进行大概比较)
#include<opencv2/opencv.hpp>
#include<iostream>
#include<opencv2/xfeatures2d.hpp>
using namespace std;
using namespace cv;
int main() {
Mat trainImage = imread("E:/File/noknown.jpg");
resize(trainImage, trainImage, Size(400, 400));
if (trainImage.empty()) {
cout << "ERROR";
system("pause");
}
Mat trainImage_gray;
imshow("原始图", trainImage);
cvtColor(trainImage, trainImage_gray, COLOR_BGR2GRAY);
//检测SIFT关键点,提取训练图像描述符
vector<KeyPoint> train_keypoint;
Mat trainDescriptor;
int minHessian = 80;
Ptr<xfeatures2d::SIFT> feature_detector = xfeatures2d::SIFT::create(minHessian);
feature_detector->detect(trainImage_gray, train_keypoint);
Ptr<xfeatures2d::SIFT> feature_extractor = xfeatures2d::SIFT::create();
feature_extractor->compute(trainImage_gray, train_keypoint, trainDescriptor);
//进行基于描述符的暴力匹配
Ptr<BFMatcher> matcher = BFMatcher::create();
vector<Mat> train_desc_collection(1, trainDescriptor);
matcher->add(train_desc_collection);
matcher->train();
//创建视频对象,定义帧率
VideoCapture cap(0);//0打开摄像头
unsigned int frameCount = 0;//帧数
//打算统计平均帧率
double averageFrameRate = 0,formerFrameRate=0;
//
while (char(waitKey(1)) != 'q') {
//参数设置
int64 time0 = getTickCount();
Mat testImage, testImage_gray;
cap >> testImage;//采集视频帧到testImage中
if (testImage.empty())
continue;
//转换成灰度
cvtColor(testImage, testImage_gray, COLOR_BGR2GRAY);
//检测关键点,提取测试图像描述符
vector<KeyPoint> test_keypoint;
Mat testDescriptor;
feature_detector->detect(testImage_gray, test_keypoint);
feature_extractor->compute(testImage_gray, test_keypoint, testDescriptor);
//匹配训练和测试描述符
vector<vector<DMatch>> matches;
matcher->knnMatch(testDescriptor, matches, 2);
//根据劳式算法(Lowe's algorithm),得到优秀的匹配点
vector<DMatch> goodMatches;
for (unsigned int i = 0; i < matches.size(); ++i) {
if (matches[i][0].distance < 0.6 * matches[i][1].distance)
goodMatches.push_back(matches[i][0]);
}
//绘制匹配点
Mat drawing;
drawMatches(testImage, test_keypoint,
trainImage, train_keypoint,
goodMatches,
drawing);
imshow("匹配窗口", drawing);
double frameRate = getTickFrequency() / (getTickCount() - time0);
averageFrameRate = (frameRate + formerFrameRate) / 2;
if(frameRate!=0 && averageFrameRate!=0)
cout << "当前帧率为>>>" <<frameRate<<"\t>>>平均帧率 > "<<averageFrameRate<< endl;
formerFrameRate = averageFrameRate;
}
destroyAllWindows();
}
SIFT配合暴力匹配的帧率与SURF的相差无几。倒是点的数量前者更少。
参考:《Opencv3编程入门》