改进orb提取算法,根据图像灰度信息计算出一 种自适应提取阈值,若此阈值提取的特征点数目不满足要求,则降低阈值至 T/2,直到提取的特征点数目达到要求,然后采用四叉树算法均匀化,最后采用GMS匹配算法,给出源码和头文件
时间: 2023-12-07 16:04:31 浏览: 100
以下是一个基于ORB算法的特征点提取器和GMS匹配算法的完整实现,其中使用了自适应的阈值计算方法和四叉树算法均匀化,确保提取到足够的特征点并提高匹配效率。
头文件:
```
#include "opencv2/opencv.hpp"
#include <iostream>
#include <vector>
#include <algorithm>
using namespace cv;
using namespace std;
```
自适应ORB特征点提取函数:
```
void ORB_ADAPTIVE(Mat& img, vector<KeyPoint>& keypoints, int min_points, int max_points, int max_iterations)
{
//自适应提取阈值的初始值
int threshold = 100;
//循环迭代,直到满足特征点数目的要求或者迭代次数达到上限
for (int i = 0; i < max_iterations; i++) {
//使用当前阈值提取ORB特征点
Ptr<ORB> orb = ORB::create(threshold);
orb->detect(img, keypoints);
//如果提取的特征点数目在要求范围内,则退出循环
if (keypoints.size() >= min_points && keypoints.size() <= max_points) {
break;
}
//如果提取的特征点数目不足,则将阈值减半
if (keypoints.size() < min_points) {
threshold /= 2;
}
//如果提取的特征点数目过多,则将阈值加倍
else if (keypoints.size() > max_points) {
threshold *= 2;
}
}
}
```
四叉树算法均匀化函数:
```
void QuadTree(Mat& img, vector<KeyPoint>& keypoints, int max_points)
{
int w = img.cols;
int h = img.rows;
int step = sqrt(w * h / max_points);
//递归构建四叉树
function<void(int, int, int, int)> quad = [&](int x1, int y1, int x2, int y2) {
Rect rect(x1, y1, x2 - x1, y2 - y1);
vector<KeyPoint> kp_in_rect;
for (auto kp : keypoints) {
if (rect.contains(kp.pt)) {
kp_in_rect.push_back(kp);
}
}
//如果该矩形内的特征点数目超过阈值,则将矩形四等分
if (kp_in_rect.size() > max_points) {
int mx = (x1 + x2) / 2;
int my = (y1 + y2) / 2;
quad(x1, y1, mx, my);
quad(mx, y1, x2, my);
quad(x1, my, mx, y2);
quad(mx, my, x2, y2);
}
//否则将矩形内的特征点均匀分布
else if (!kp_in_rect.empty()) {
sort(kp_in_rect.begin(), kp_in_rect.end(), [](KeyPoint a, KeyPoint b) { return a.response > b.response; });
int n = kp_in_rect.size();
for (int i = 0; i < n; i += step) {
keypoints.push_back(kp_in_rect[i]);
}
}
};
quad(0, 0, w, h);
}
```
GMS匹配算法函数:
```
void GMS_MATCHING(Mat& img1, Mat& img2, vector<DMatch>& matches, vector<KeyPoint>& keypoints1, vector<KeyPoint>& keypoints2)
{
//将特征点转换为GMS可用的格式
vector<vector<int>> kp1, kp2;
for (auto kp : keypoints1) {
kp1.push_back({ (int)kp.pt.x, (int)kp.pt.y });
}
for (auto kp : keypoints2) {
kp2.push_back({ (int)kp.pt.x, (int)kp.pt.y });
}
//计算匹配矩阵
vector<vector<int>> match_matrix(keypoints1.size(), vector<int>(keypoints2.size(), 0));
for (auto match : matches) {
int i = match.queryIdx;
int j = match.trainIdx;
match_matrix[i][j] = 1;
}
//调用GMS匹配算法
Ptr<GMS> gms = GMS::create();
gms->setBothSize(5);
gms->setThreshold(0.6);
vector<pair<int, int>> inliers;
gms->getInlier(kp1, kp2, match_matrix, inliers);
//根据GMS的结果过滤匹配
vector<DMatch> filtered_matches;
for (auto inlier : inliers) {
int i = inlier.first;
int j = inlier.second;
filtered_matches.push_back(matches[i]);
}
matches = filtered_matches;
}
```
完整的匹配函数:
```
void MATCHING(Mat& img1, Mat& img2, vector<DMatch>& matches)
{
//提取ORB特征点并进行四叉树均匀化
vector<KeyPoint> keypoints1, keypoints2;
ORB_ADAPTIVE(img1, keypoints1, 100, 500, 10);
ORB_ADAPTIVE(img2, keypoints2, 100, 500, 10);
QuadTree(img1, keypoints1, 500);
QuadTree(img2, keypoints2, 500);
//计算ORB特征描述子
Mat descriptors1, descriptors2;
Ptr<ORB> orb = ORB::create();
orb->compute(img1, keypoints1, descriptors1);
orb->compute(img2, keypoints2, descriptors2);
//进行特征匹配
Ptr<BFMatcher> matcher = BFMatcher::create(NORM_HAMMING);
matcher->match(descriptors1, descriptors2, matches);
//进行GMS匹配
GMS_MATCHING(img1, img2, matches, keypoints1, keypoints2);
}
```
使用示例:
```
int main()
{
//读取图像
Mat img1 = imread("img1.jpg");
Mat img2 = imread("img2.jpg");
//进行特征匹配和GMS匹配
vector<DMatch> matches;
MATCHING(img1, img2, matches);
//在图像上绘制匹配点
Mat img_matches;
drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches);
//显示图像
imshow("Matches", img_matches);
waitKey(0);
return 0;
}
```
注意,以上代码中使用的是OpenCV的ORB特征点提取器、BFMatcher匹配器和GMS匹配算法,需要包含头文件`#include "opencv2/features2d.hpp"`和`#include "opencv2/xfeatures2d.hpp"`。
阅读全文