97.SURF特征点检测

目录

        1 SIFT与SURF的比较

        2 SURF工作原理

        3 SURF算法流程

        4 API详解

        4.1 SURF::create()函数

        4.2 Ptr create()函数

        4.3 drawMatches()函数

  5 用C++编写代码进行实现

        1 SIFT与SURF的比较

        SIFT算法的优点是特征稳定,对旋转、尺度变换、亮度保持不变性,对视角变换、噪声也有一定程度的稳定性。它的缺点是实时性不高,并且对于光滑目标的特征点提取能力较弱。

        SURF(Speeded Up Robust Features)和SIFT算法相似,它改进了特征的提取和描述方式,用一种更为高效的方式完成了特征的提取与描述。

        2 SURF工作原理

        1.构建Hessian Matrix,初步提取特征点(稳定边缘点)。

        2.构造尺度空间,在不同尺度下,根据Hessian得分寻找特征点。

        3.根据特征点邻域haar小波特征计算特征点主方向。

        4.生成特征描述符。

        3 SURF算法流程

1)Hessian矩阵构建:

        在SIFT中第一步首先建立图像金字塔,在每一层进行多尺度高斯滤波再求图像差得到DoG金字塔再进行特征点提取。 而SURF则用的是Hessian矩阵进行特征点的提取,因此Hessian矩阵是SURF算法的核心。 假设函数f(x,y),Hessian矩阵由函数偏导数组成,定义为如下公式:

        而每一个像素点都可以求得一个Hessian矩阵,Hessian矩阵判别式为:

        在构建Hessian矩阵前需要对图像进行高斯滤波,经滤波后的Hessian矩阵表达式为:

其中(x,y)是像素位置,L(x,y,σ)=G(σ)∗I(x,y),代表着图像的高斯尺度空间。

        得到滤波之后的Hessian矩阵后,我们再通过上面讲的Hessian矩阵判别式可以得到图像中每个像素的H矩阵决定值,并用这个值来判别特征点。 然而在实际计算时,为了提高运算速度(积分图),而是使用方框滤波器Boxfilter来替代高斯滤波器,为了平衡准确值和近似值之间的误差,引入了权值0.9。H矩阵的判别式可以表示为:

其中高斯滤波器和盒式滤波器在图像垂直方向二阶导数L_yy、L_xy的示意图如下:

 2)尺度空间构建:

        和SIFT算法一样,SURF算法的尺度空间由O组S层组成。 不同的是,SIFT算法下一组图像的长宽均是上一组的一半,同一组不同层图像之间尺寸一样,但是所使用的尺度空间因子(高斯模糊系数σ)逐渐增大;

        在SURF算法中,不同组间图像的尺寸都是一致的,不同的是不同组间使用的盒式滤波器的模板尺寸逐渐增大,同一组不同层图像使用相同尺寸的滤波器,但是滤波器的尺度空间因子逐渐增大。如下图所示:

 3)特征点过滤:

        和SIFT算法一致,将经过Hessian矩阵处理的每个像素点(每个像素点Hessian矩阵判别式值)与其图像域(相同大小图像)和尺度域(相邻尺度空间)的所有相邻点进行比较,当其大于(或者小于)所有相邻点时,该点就是极值点。

 4)计算特征主方向:

        SIFT算法特征点的主方向是采用在特征点邻域内统计其梯度直方图,横轴是梯度方向的角度,纵轴是梯度方向对应梯度幅值的累加,取直方图bin最大的以及超过最大80%的那些方向作为特征点的主方向。

        而在SURF算法中,采用的是统计特征点圆形邻域内的Harr小波特征,即在特征点的圆形邻域内,统计60度扇形内所有点的水平、垂直Harr小波特征总和,然后扇形以0.2弧度大小的间隔进行旋转并再次统计该区域内Harr小波特征值之后,最后将值最大的那个扇形的方向作为该特征点的主方向。该过程示意图如下:

 5)生成特征描述子:

        在SURF中,也是在特征点周围选取一个正方形框,框的边长为20s(s为所检测到该特征点所在的尺度)。该框的方向是第4步检测出的主方向。(不同于SIFT的关键点方向旋转)

        然后把该框分为16个子区域,每个子区域统计25个像素的水平方向和垂直方向(相对于主方向)的haar小波特征。该haar小波特征为水平方向值之和、水平方向绝对值之和,垂直方向之和,垂直方向绝对值之和。

        4 API详解

        4.1 SURF::create()函数

        cv::xfeatures2d::SURF::create 是 OpenCV 库中的一个函数,用于创建 SURF(Speeded Up Robust Features)算法的特征提取器。

        SURF 是一种用于图像特征提取和匹配的算法,它可以在图像中检测出稳定的关键点,并计算这些关键点的描述子。SURF 算法具有较高的速度和鲁棒性,适用于各种图像处理任务,如目标识别、图像拼接等。

        使用 cv::xfeatures2d::SURF::create 函数可以创建一个 SURF 特征提取器对象,使得我们能够在代码中使用 SURF 算法进行特征提取和匹配操作。

static Ptr<xfeatures2d::SURF> cv::xfeatures2d::SURF::create(double   
 hessianThreshold=100, int nOctaves = 4, int nOctaveLayers = 3,
 bool  extended = false, bool upright = false);
参数含义:
hessianThreshold  --  hessian关键点检测器的阈值。
Octaves  --  关键点检测器使用的金字塔组数
nOctaveLayers  --  多尺度金字塔每个组内图像的层数
extended  --  扩展描述符标志, (true使用扩展的128个元素的描述符,false使用	
  64个元素的描述符)
upright  --  旋转的特征标志(true不计算方向,false计算方向)

        4.2 Ptr<DescriptorMatcher> create()函数

        Ptr<DescriptorMatcher> create 是 OpenCV 库中的一个函数,用于创建特征描述子匹配器(Descriptor Matcher)对象。

        特征描述子匹配器是用于在两个或多个图像之间进行特征匹配的算法。它可以根据提取到的特征描述子,比较这些描述子之间的相似度,并找出最佳匹配的特征点对应关系。特征描述子匹配器在计算机视觉领域具有广泛的应用,如图像拼接、目标识别等任务。

        使用 Ptr<DescriptorMatcher> create 函数可以创建一个特征描述子匹配器对象,使得我们能够在代码中使用各种不同的匹配算法进行特征匹配操作。

static Ptr<DescriptorMatcher> create( const DescriptorMatcher::MatcherType&matcherType
参数含义:
matcherType  --  枚举类型特征匹配方式,包括:
FLANNBASED = 1,  --  快速最近邻匹配法
BRUTEFORCE = 2,  --  暴力匹配法     
BRUTEFORCE_L1 = 3,        
BRUTEFORCE_HAMMING = 4,       
BRUTEFORCE_HAMMINGLUT = 5,        
BRUTEFORCE_SL2 = 6

        4.3 drawMatches()函数

        cv::drawMatches 是 OpenCV 库中的一个函数,用于在图像上绘制特征匹配结果。特征匹配是通过比较两个图像中的特征描述子来找到相似的特征点对应关系。cv::drawMatches 函数可以将这些匹配结果可视化,并在图像上绘制出匹配的线段或圆圈,以便我们更直观地观察和分析特征匹配的效果。

void drawMatches(
    InputArray img1,                        // 第一幅输入图像
    const std::vector<KeyPoint>& keypoints1, // 第一幅图像的关键点
    InputArray img2,                        // 第二幅输入图像
    const std::vector<KeyPoint>& keypoints2, // 第二幅图像的关键点
    const std::vector<DMatch>& matches,      // 特征匹配结果
    OutputArray outImg,                      // 输出图像,用于存储绘制结果
    const Scalar& matchColor = Scalar::all(-1),          // 匹配线段或圆圈的颜色,默认为随机颜色
    const Scalar& singlePointColor = Scalar::all(-1),    // 单个关键点的颜色,默认为随机颜色
    const std::vector<char>& matchesMask = std::vector<char>(),   // 匹配结果的掩码,默认为空
    int flags = DrawMatchesFlags::DEFAULT       // 绘制标志,默认为 DEFAULT
);
img1:第一幅输入图像,类型为 cv::Mat 或 cv::InputArray。
keypoints1:第一幅图像的关键点,类型为 std::vector<cv::KeyPoint>。
img2:第二幅输入图像,类型为 cv::Mat 或 cv::InputArray。
keypoints2:第二幅图像的关键点,类型为 std::vector<cv::KeyPoint>。
matches:特征匹配结果,类型为 std::vector<cv::DMatch>。
outImg:输出图像,用于存储绘制结果,类型为 cv::Mat 或 cv::OutputArray。
matchColor:匹配线段或圆圈的颜色,类型为 cv::Scalar,默认为随机颜色。
singlePointColor:单个关键点的颜色,类型为 cv::Scalar,默认为随机颜色。
matchesMask:匹配结果的掩码,类型为 std::vector<char> 或 std::vector<uchar>,默认为空。
flags:绘制标志,可以是以下值的组合:
    DrawMatchesFlags::DEFAULT:默认标志,显示所有匹配结果。
    DrawMatchesFlags::DRAW_OVER_OUTIMG:将匹配结果绘制在输出图像上,而不是创建一个新的窗口显示。
    DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS:不绘制单个关键点,仅绘制匹配线段。

  5 用C++编写代码进行实现

        下面是使用OpenCV库进行SURF特征点检测的示例代码:

#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>

int main() {
    // 加载图像
    cv::Mat image = cv::imread("image.jpg");

    // 创建 SURF 特征提取器对象
    cv::Ptr<cv::xfeatures2d::SURF> surf = cv::xfeatures2d::SURF::create();

    // 检测关键点和计算描述子
    std::vector<cv::KeyPoint> keypoints;
    cv::Mat descriptors;
    surf->detectAndCompute(image, cv::noArray(), keypoints, descriptors);

    // 在图像上绘制关键点
    cv::Mat image_with_keypoints;
    cv::drawKeypoints(image, keypoints, image_with_keypoints);

    // 显示图像和关键点
    cv::imshow("Image with Keypoints", image_with_keypoints);
    cv::waitKey(0);

    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

别叭叭儿—好好学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值