0
点赞
收藏
分享

微信扫一扫

OpenCV + CPP 系列(卌二)图像特征匹配( KAZE/AKAZE)


文章目录

  • ​​一、KAZE简介​​
  • ​​二、代码演示​​
  • ​​特征检测效果对比​​
  • ​​演示匹配​​

一、KAZE简介

ECCV2012中出现了一种比SIFT更稳定的特征检测算法KAZE ([1])。KAZE的取名是为了纪念尺度空间分析的开创者—日本学者Iijima。KAZE是日语‘风’的谐音,寓意是就像风的形成是空气在空间中非线性的流动过程一样,KAZE特征检测是在图像域中进行非线性扩散处理的过程

传统的SIFT、SURF等特征检测算法都是基于线性的高斯金字塔进行多尺度分解来消除噪声和提取显著特征点。但高斯分解是牺牲了局部精度为代价的,容易造成边界模糊和细节丢失。

非线性的尺度分解有望解决这种问题,但传统方法基于正向欧拉法(forward Euler scheme)求解非线性扩散(Non-linear diffusion)方程时迭代收敛的步长太短,耗时长、计算复杂度高。由此,KAZE算法的作者提出采用 ​​加性算子分裂算法(Additive Operator Splitting, AOS)​​来进行非线性扩散滤波,可以采用任意步长来构造稳定的非线性尺度空间。


下面为AKAZE局部匹配介绍(KAZE的加速版)
整个算法流程:

  1. 非线性扩散滤波与尺度空间构建:(Perona-Malik扩散方程)–>(AOS算法)
  2. Hessian矩阵特征点检测
  3. 特征检测与描述子生成:(特征点主方向:一阶微分图像)–>(构造特征描述向量)

二、代码演示

头文件 ​​image_feature_all.h​​:声明类与公共函数

#pragma once
#include <opencv2/opencv.hpp>
#include <iostream>
#include <opencv2/xfeatures2d.hpp>  //新增引入库

using namespace cv;
using namespace std;


class ImageFeature {
public:
void kaze_akaze_demo(Mat& image, Mat& image2);
void akazeMatch_demo(Mat& image, Mat& image2);

};

主函数​​main.cpp​​调用该类的公共成员函数

#include "image_feature_all.h"



int main(int argc, char** argv) {
const char* img_path = "D:\\Desktop\\match_dst.jpg";
const char* img_path2 = "D:\\Desktop\\match_raw.jpg";
Mat image = imread(img_path, IMREAD_GRAYSCALE);
Mat image2 = imread(img_path2, IMREAD_GRAYSCALE);
if (image.empty() || image2.empty()) {
cout << "图像数据为空,读取文件失败!" << endl;
}
ImageFeature imgfeature;
imgfeature.kaze_akaze_demo(image, image2);
imgfeature.akazeMatch_demo(image, image2);

waitKey(0);
destroyAllWindows();
return 0;
}

特征检测效果对比

void ImageFeature::kaze_akaze_demo(Mat& image, Mat& image2) {
// KAZE 检测
Ptr<KAZE> kaze_detector = KAZE::create();
vector<KeyPoint> kaze_keypoints;

double t0 = getTickCount();
kaze_detector->detect(image2, kaze_keypoints, Mat());
double t1 = getTickCount();
cout << " kaze_keypoints:" << kaze_keypoints.size() << endl;
cout << " KAZE cost time:" << ((t1 - t0) / getTickFrequency()) << endl;

Mat kaze_Img;
drawKeypoints(image2, kaze_keypoints, kaze_Img, Scalar::all(-1), DrawMatchesFlags::DEFAULT);
imshow("kaze_Img", kaze_Img);


// AKAZE 检测
Ptr<AKAZE> akaze_detector = AKAZE::create();
vector<KeyPoint> akaze_keypoints;

double t00 = getTickCount();
akaze_detector->detect(image2, akaze_keypoints, Mat());
double t11 = getTickCount();
cout << "akaze_keypoints:" << akaze_keypoints.size() << endl;
cout << "AKAZE cost time:" << ((t11 - t00) / getTickFrequency()) << endl;

Mat akaze_Img;
Mat image2_copy = image2.clone();
drawKeypoints(image2_copy, akaze_keypoints, akaze_Img, Scalar::all(-1), DrawMatchesFlags::DEFAULT);
imshow("akaze_Img", akaze_Img);
}

快了大约6倍,但是检测的特征好像少了不少。
kaze_keypoints:1238
KAZE cost time:0.209193

akaze_keypoints:977

AKAZE cost time:0.0335966

OpenCV + CPP 系列(卌二)图像特征匹配( KAZE/AKAZE)_opencv

演示匹配

void ImageFeature::akazeMatch_demo(Mat& image, Mat& image2) {
// AKAZE feature detect
Ptr<AKAZE> akaze_detector = AKAZE::create();
vector<KeyPoint> keypoints_obj,keypoints_scens;
Mat descriptor_obj, descriptor_scens;

double t00 = getTickCount();
akaze_detector->detectAndCompute(image, Mat(), keypoints_obj, descriptor_obj);
akaze_detector->detectAndCompute(image2, Mat(), keypoints_scens, descriptor_scens);
double t11 = getTickCount();
cout << "AKAZE cost time:" << ((t11 - t00) / getTickFrequency()) << endl;

// BFmatch
vector<DMatch> matches;
BFMatcher matcher;
Mat AKAZE_Img;
matcher.match(descriptor_obj, descriptor_scens, matches, Mat());

vector<DMatch> good_matches;
double maxDist=0, minDist=1000;
for (size_t i = 0; i < descriptor_obj.rows; i++){
double dist = matches[i].distance;
if (dist < minDist) { minDist = dist; }
if (dist > minDist) { maxDist = dist; }
}

for (size_t i = 0; i < descriptor_obj.rows; i++){
if (matches[i].distance < max(2.0 * minDist, 0.02)) {
good_matches.push_back(matches[i]);
}
}

drawMatches(
image, keypoints_obj,
image2, keypoints_scens,
good_matches, AKAZE_Img,
Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS
);
imshow("AKAZE_Img", AKAZE_Img);

// flann_match
FlannBasedMatcher flann_matcher(new flann::LshIndexParams(20, 10, 2));
vector<DMatch> flann_matches;
Mat flann_AKAZE_Img;
flann_matcher.match(descriptor_obj, descriptor_scens, flann_matches, Mat());
drawMatches(
image, keypoints_obj,
image2, keypoints_scens,
flann_matches, flann_AKAZE_Img,
Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS
);
imshow("flann_AKAZE_Img", flann_AKAZE_Img);
}

OpenCV + CPP 系列(卌二)图像特征匹配( KAZE/AKAZE)_opencv_02


OpenCV + CPP 系列(卌二)图像特征匹配( KAZE/AKAZE)_#include_03


举报

相关推荐

0 条评论