KAZE算法是由法国学者在在2012年的ECCV会议中提出的,是一种比SIFT更稳定的特征检测算法。KAZE算法是基于非线性尺度空间的算法,KAZE 特征对旋转、尺度、有限仿射具有不变性,并且在不同尺度上具有更多的独特性,但代价是计算时间适度增加。
KAZE算法与SIFT算法不一样,它采用的是非线性扩散滤波法。 具体地,非线性扩散滤波法是将图像亮度(L)在不同尺度上的变化视为某种形式的流动函数(flow function)的散度(divergence),可以通过非线性偏微分方程来描述:
通过设置合适的传导函数 c(x,y,t) ,可以使得扩散自适应于图像的局部结构。传导函数可以是标量、也可以是张量。时间t作为尺度参数,其值越大、则图像的表示形式越简单。 Perona和Malik提出了传导函数的构造方式:
其中函数g1优先保留高对比度的边缘,g2优先保留宽度较大的区域,g3能够有效平滑区域内部而保留边界信息(KAZE代码中默认采用函数g2) 。
API介绍
static Ptr<KAZE> create(bool extended=false, bool upright=false,float threshold = 0.001f,int nOctaves = 4, int nOctaveLayers = 4,KAZE::DiffusivityType diffusivity = KAZE::DIFF_PM_G2);
/*******************************************************************
* extended: 设置以启用扩展(128 字节)描述符的提取
* upright: 设置为启用垂直描述符(非旋转不变)
* threshold: 响应阈值
* nOctaves: 图像的最大倍频程演化
* nOctaveLayers: 每个比例级别的默认子级别数
* diffusivity: 扩散型
* DIFF_PM_G1
* DIFF_PM_G2
* DIFF_WEICKERT
* DIFF_CHARBONNIER
*********************************************************************/
virtual void detect( InputArray image,std::vector<KeyPoint>& keypoints,InputArray mask=noArray());
/*******************************************************************
* image: 输入图
* keypoints: 角点信息
* mask: 计算亚像素角点区域大小
*********************************************************************/
void drawKeypoints( InputArray image, const std::vector<KeyPoint>& keypoints, InputOutputArray outImage,const Scalar& color=Scalar::all(-1), DrawMatchesFlags flags=DrawMatchesFlags::DEFAULT );
/*******************************************************************
* image: 输入图
* keypoints: 角点信息
* outImage: 输出图
* color: 颜色
* flags: 绘制匹配标记
*********************************************************************/
综合代码
#include <iostream>
#include <map>
#include <new>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
class KAZEFeature
{
public:
KAZEFeature() :img(imread("mm.jpg"))
{
result["img"] = img;
}
void TestKAZE()
{
Ptr<KAZE> kaze = KAZE::create();
kaze->detect(img, point);
drawKeypoints(img, point, result["kaze"], Scalar(255, 0, 255));
}
void Show()
{
for (auto& v : result)
{
imshow(v.first, v.second);
}
waitKey(0);
}
protected:
Mat img;
vector<KeyPoint> point;
map<string, Mat> result;
};
int main()
{
unique_ptr<KAZEFeature> p(new KAZEFeature);
p->TestKAZE();
p->Show();
return 0;
}