FAST(features from accelerated segment test)是基于⾓点检测的图像特征,是公认的比较快速的特征点检测方法,只利用周围像素比较的信息就可以得到特征点,简单,有效。很多传统的算法都很耗时,而且特征点检测算法只是很多复杂图像处理里中的第一步,得不偿失。FAST算法思想是若某像素与其周围领域内足够多的像素点相差较大,则该像素可能是角点
FAST算法大致流程
- 确定候选角点
- 非极大值抑制
API介绍
static Ptr<FastFeatureDetector> create( int threshold=10,bool nonmaxSuppression=true,
FastFeatureDetector::DetectorType type=FastFeatureDetector::TYPE_9_16 );
/*******************************************************************
* threshold: 比较时边缘轨迹点和中心点的差值
* nonmaxSuppression: 是否使用非极大值抑制
* type: FastFeatureDetector枚举类型
* TYPE_5_8 从轨迹中取8个点,当有5个点满足条件,就是特征点.
* TYPE_7_12 取轨迹12个点,7个满足条件,就是特征点.
* TYPE_9_16 取轨迹16个点,当9个满足条件,就是特征点.
*********************************************************************/
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 FastFeature
{
public:
FastFeature() :img(imread("mm.jpg"))
{
result["img"] = img;
}
void TestFAST()
{
Ptr<FastFeatureDetector> fast = FastFeatureDetector::create();
fast->detect(img, point);
drawKeypoints(img, point, result["SIFT"], 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<FastFeature> p(new FastFeature);
p->TestFAST();
p->Show();
return 0;
}
opencv BRISK特征检测
BRISK(Binary Robust Invariant Scalable Keypoints)是一种二进制的特征描述算子。它具有较好的旋转不变性、尺度不变性,较好的鲁棒性(稳定性)等。在对有较大模糊的图像配准时,BRISK算法在其中表现最为出色。对描述子匹配时,采用汉明距离,进行二值匹配。
汉明距离:它表示两个(相同长度)字对应位不同的数量,我们以d(x,y)表示两个字x,y之间的汉明距离。对两个字符串进行异或运算,并统计结果为1的个数,那么这个数就是汉明距离。例如:1011101 与 1001001 之间的汉明距离是 2。
BRISK算法大致流程
- 建立尺度空间
- 特征点检测
- 非极大值抑制
- 亚像素插值
- 特征点描述
- 高斯滤波
- 局部梯度计算
API介绍
static Ptr<BRISK> create(int thresh=30, int octaves=3, float patternScale=1.0f);
/*******************************************************************
* thresh: 检测阈值
* octaves: 检测角度
* patternScale: 邻域采样比例
*********************************************************************/
static Ptr<BRISK> create(const std::vector<float> &radiusList, const std::vector<int> &numberList,float dMax=5.85f, float dMin=8.2f, const std::vector<int>& indexChange=std::vector<int>());
/*******************************************************************
* radiusList: 关键点周围采样的半径
* numberList: 定义采样圆上的采样点数
* dMax: 长配对阈值
* dMin: 短配对阈值
* indexChange: 位的索引重新映射
*********************************************************************/
static Ptr<BRISK> create(int thresh, int octaves, const std::vector<float> &radiusList,const std::vector<int> &numberList, float dMax=5.85f, float dMin=8.2f,const std::vector<int>& indexChange=std::vector<int>());
/*******************************************************************
* thresh: 检测阈值
* octaves: 检测角度
* radiusList: 关键点周围采样的半径
* numberList: 定义采样圆上的采样点数
* dMax: 长配对阈值
* dMin: 短配对阈值
* indexChange: 位的索引重新映射
*********************************************************************/
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 BRISKFeature
{
public:
BRISKFeature() :img(imread("mm.jpg"))
{
result["img"] = img;
}
void TestFAST()
{
Ptr<BRISK> fast = BRISK::create(10);
fast->detect(img, point);
drawKeypoints(img, point, result["BRISK"], 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<BRISKFeature> p(new BRISKFeature);
p->TestFAST();
p->Show();
return 0;
}
opencv ORB特征检测
ORB在2011年才首次发布,ORB算法将基于FAST关键点的技术和基于BRIEF描述符的技术相结合,但是ORB并没有解决尺度不一致的问题,在OpenCV的ORB实现中采用了图像金字塔来改善这方面的性能,我们通过构建高斯金字塔,然后在每一层金字塔图像上检测角点,来实现尺度不变性。ORB主要解决了BRIEF描述子不具备旋转不变性的问题。 BRIEF是一种特征描述子提取算法,并非特征点的提取算法,一种生成二值化描述子的算法,不提取代价低,匹配只需要使用简单的汉明距离(Hamming Distance)利用比特之间的异或操作就可以完成。因此,时间代价低,空间代价低,效果还挺好是最大的优点。
ORB算法大致流程
- 建立图像金字塔
- FAST算法寻找特征点
- 给关键点分配方向
- 通过BRIEF算法创建特征向量,得到特征描述符
API介绍
static Ptr<ORB> create(int nfeatures=500, float scaleFactor=1.2f, int nlevels=8, int edgeThreshold=31,int firstLevel=0, int WTA_K=2, ORB::ScoreType scoreType=ORB::HARRIS_SCORE, int patchSize=31, int fastThreshold=20);
/*******************************************************************
* nfeatures: 保留的最佳特性的数量
* scaleFactor: 金字塔抽取率,必须大于1
* nlevels: 金字塔等级的数量
* edgeThreshold: 边缘阈值
* firstLevel: 第一层的索引值
* WTA_K: 用于生成定向的BRIEF描述符的每个元素的随机像素的数量
* 2:一次选择两个随机像素比较,匹配的时候距离参数选择NORM_HAMMING,默认方式
* 3:一次选择三个随机像素来比较它们的亮度,返回最亮像素的索引,返回回的索引将为0,1或2
* 4:一次选择四个随机像素来比较它们的亮度,返回最亮像素的索引,回的索引将为0,1,2或3
* scoreType: 对特征点进行排序的算法
* HARRIS_SCORE:Harris角算法用于对要素进行排名。该分数仅用于保留最佳功能
* FAST_SCORE: 速度快,关键点稍差
* patchSize: 用于计算BIREF描述子的特征点邻域大小
* fastThreshold: fast特征阈值
*********************************************************************/
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 ORBFeature
{
public:
ORBFeature() :img(imread("mm.jpg"))
{
result["img"] = img;
}
void TestORB()
{
Ptr<ORB> orb = ORB::create();
orb->detect(img, point);
drawKeypoints(img, point, result["orb"], 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<ORBFeature> p(new ORBFeature);
p->TestORB();
p->Show();
return 0;
}