特征,也称 兴趣点 或 关键点,如下所示:蓝框内区域平坦,无特征;黑框内有“边缘”,红框内有“角点”,后二者都可视为“特征”
角点作为一种特征,它具有 旋转不变性,当图像旋转时,代表角点响应函数 R 的特征椭圆,其形状保持不变
但是,角点不具有 尺度不变性,左图中被检测为角点的特征,当放大到右图的尺度空间时,会被检测为 边缘 或 曲线
下面介绍几种具有尺度不变性的特征检测算法:SIFT、SURF、ORB、BRISK、KAZE 和 AKAZE 等
1 特征检测
1.1 SIFT
SIFT 全称 Scale Invariant Feature Transform,是特征检测中里程碑式的算法,也是目前最有效的特征检测,该算法申请了专利,直到 2020年3月才过专利保护期
OpenCV 从 4.4.0 起,已经将 SIFT 移到了主模块 feature2d 中,SIFT 继承自 Feature2D 类,而 Feature2D 继承自 Algorithm 类,SIFT 的 create() 函数定义如下:
class SIFT : public Feature2D
{
public:
static Ptr<SIFT> create(
int nfeatures = 0, // The number of best features to retain
int nOctaveLayers = 3, // The number of layers in each octave. 3 is the value used in D.Lowe paper
double contrastThreshold = 0.04, // The contrast threshold used to filter out weak features in low-contrast regions
double edgeThreshold = 10, // The threshold used to filter out edge-like features
double sigma = 1.6 ); // The sigma of the Gaussian applied to the input image at the octave 0
Algorithm 类中有两个虚函数:detect() 检测特征,compute() 计算描述符
class Feature2D : public virtual Algorithm
{
public:
/* Detects keypoints in an image (first variant) or image set(second variant). */
virtual void detect(InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask=noArray() );
/* Computes the descriptors for a set of keypoints detected in an image (first variant) or image set (second variant). */
virtual void compute(InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors );
1.2 SURF
SIFT 算法虽好,但计算速度不够快,于是 SIFT 的近似版 SURF (Speeded Up Robust Features) 应运而生, SURF 的运行时间约为 SIFT 的 1/3
SURF 属于 xfeature2d 模块,也继承自 Feature2D 类,其 create() 函数定义如下:
namespace xfeatures2d
{
class SURF : public Feature2D
{
public:
static Ptr<SURF> create(
double hessianThreshold = 100, // Threshold for hessian keypoint detector used in SURF
int nOctaves = 4, // Number of pyramid octaves the keypoint detector will use
int nOctaveLayers = 3, // Number of octave layers within each octave
bool extended = false, // Extended descriptor flag (true, 128-element descriptors;