zoukankan      html  css  js  c++  java
  • sift&surf检测关键点及描述子

    1sift介绍

    SIFT全称Scale-Invariant Feature Transform(尺度不变特征转换)。它用来侦测与描述影像中的局部性特征,它在空间尺度中寻找极值点,并提取出其位置、尺度、旋转不变量,此算法由 David Lowe在1999年所发表,2004年完善总结。

    SIFT算法分解为如下四步:

    (1)构建尺度空间

    搜索所有尺度上的图像位置,通过高斯微分函数来识别潜在的对于尺度和旋转不变的兴趣点,具体的过程如下。

    A、采用高斯函数对图像进行模糊以及降采样处理得到高斯金字塔

     

    B、采用DOG(Difference of Gaussian)即在高斯金子塔中的每组中相邻两层相减(“下一层减上一层”)生成高斯差分金字塔

     

    (2)关键点定位

    A、找到局部极值点

     

    B、剔除极值点

    通过Taylor展开式(插值函数)精确定位关键点,通过Hessian矩阵消除边缘响应点。

    (3)方向确定

    对关键点进行梯度计算生成梯度直方图统计领域内像素的梯度和方向,从而确定方向。

     

    (4)关键点特征描述子

    取特征点周围44个区域块,统计每小块内8个梯度方向,用这448=128维向量作为Sift特征的描述子。

    2surf介绍

    SURF全称Speeded Up Robust Features,为SIFT的加速版本。它改进了特征的提取和描述方式,用一种更为高效的方式完成特征的提取和描述。

    SURF跟SIFT一样分四步走:

    1构建尺度空间

    A、使用box filter滤波,然后使用Hessian矩阵获取二阶梯度特征(相当于LoG算子或SIFT里的DOG)

     

    从左到右分别表示在y方向LoG算子(),xy方向的LoG算子,y方向近似的LoG算子,xy方向近似的LoG算子

    (2)构建Hessian矩阵塔

    surf在建塔的时候每层图像大小不变,只是对模板的尺度不断增大,相当于一个上采样的过程。

     

    第一塔中size分别为,而以后每塔中size边长差距逐塔翻倍。

    (2)关键点定位

    A、找到局部极值点

    这里和LoG,DoG相同,都是在生成尺度空间后,在三维上找极值点。

     

    B、剔除极值点

    这里和DoG不同的是不用剔除边缘导致的极值点了,因为Hessian矩阵的行列式就已经考虑到边缘的问题了,而DoG计算只是把不同方向变化趋势给出来,后续还需要使用Hessian矩阵的特征值剔除边缘产生的影响。

    通过Taylor展开式(插值函数)精确定位关键点。

    (3)方向确定

    统计特征点圆形邻域内的harr小波特征,按每60度划分一个扇区进行计算,最后得到值最大的那个扇区的方向做为主方向。

     

    (4)关键点特征描述子

    在特征点周围取一个44的矩形区域块,但是所取得矩形区域方向是沿着特征点的主方向。每个子区域统计25个像素的水平方向和垂直方向的haar小波特征,这里的水平和垂直方向都是相对主方向而言的。该haar小波特征为水平方向值之后、垂直方向值之后、水平方向绝对值之后以及垂直方向绝对值之和4个方向。

    把这4个值作为每个子块区域的特征向量,所以一共有4^4=64维向量作为Surf特征的描述子。

     

    3siftsurf对比

    (1)SURF不同点

    A、在尺度空间中,使用box filtes与原图像卷积,而不是使用DoG算子。

    B、确定关键点方向时,Surf是利用不同方向bin中的haar小波响应的最大值最为方向,而Sift是统计周围区域像素点的方向直方图,找出最大方向bin作为主方向,而且还可以有多个方向。

    C、特征描述子,Surf在关键点周围取区域分成44块小区域,在每个小区域计算采样点的haar响应,统计对应的四个特征,共64维特征,而Sift在周围1616的区域划分成4*4的子区域,每一个子区域提取长度为8的方向直方图特征,排列起来形成128维特征向量。

    (2)SURF速度更快

    A、使用box filters相对于高斯滤波,再辅助以积分图速度肯定提升不少。

    B、Hessian矩阵的计算一般而言还是挺麻烦的,但这里可以使用积分图计算,无论尺度是多少都可以使用几个数的加减完成,速度很快。

    C、确定关键点方向时使用haar特征同样可以利用积分图,简单快速。

    D、特征描述子使用64维取代128维特征降低了后续处理的数据规模。

    4sift示例

    #sift特征匹配
    def siftFeature(queryPhoto,trainPhoto):
        img1 = cv.imread(queryPhoto,3) # queryImage
        img2 = cv.imread(trainPhoto,3) # trainImage
        # Initiate SIFT detector初始化SIFT检测器
        # ref:https://docs.opencv.org/3.4.2/d5/d3c/classcv_1_1xfeatures2d_1_1SIFT.html
        sift = cv.xfeatures2d.SIFT_create()
        # find the keypoints and descriptors with SIFT获取关键点与特征描述子
        # ref:https://docs.opencv.org/3.4.2/d0/d13/classcv_1_1Feature2D.html#a8be0d1c20b08eb867184b8d74c15a677
        kp1, des1 = sift.detectAndCompute(img1,None)
        kp2, des2 = sift.detectAndCompute(img2,None)
        # print(len(kp1))#输出关键点的长度
        # Brute-force descriptor matcher蛮力描述子匹配 
        # ref:https://docs.opencv.org/3.4.2/d3/da1/classcv_1_1BFMatcher.html
        bf = cv.BFMatcher() 
        #从查询集中查找每个描述符的k个最佳匹配。
        #ref:https://docs.opencv.org/3.4.2/db/d39/classcv_1_1DescriptorMatcher.html#aa880f9353cdf185ccf3013e08210483a
        matches = bf.knnMatch(des1,des2, k=2)
        # Apply ratio test
        good = []
        for m,n in matches:
            if m.distance < 0.75*n.distance:#剔除两个匹配具体相差太远的项
                good.append([m])
                
        #从两个图像中绘制找到的关键点匹配项,flags指定画出匹配关键点的方式
        #ref:https://docs.opencv.org/3.4.2/d4/d5d/group__features2d__draw.html
        img3 = cv.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=2)
    
        return img3
    

      

    5surf示例

    #surf特征匹配
    def surfFeature(queryPhoto,trainPhoto):
        img1 = cv.imread(queryPhoto,3) # queryImage
        img2 = cv.imread(trainPhoto,3) # trainImage
        # Initiate SURF detector初始化SURF检测器
        #ref:https://docs.opencv.org/3.4.2/d5/df7/classcv_1_1xfeatures2d_1_1SURF.html
        surf=cv.xfeatures2d.SURF_create(400)#初始Hessian矩阵的阈值
        # find the keypoints and descriptors with SURF
        kp1, des1 = surf.detectAndCompute(img1,None)
        kp2, des2 = surf.detectAndCompute(img2,None)
        # print(len(kp1))
        # surf.setHessianThreshold(5000) #指定Hessian矩阵的阈值
        # print(surf.getHessianThreshold())
        
        # BFMatcher with default params
        bf = cv.BFMatcher()
        matches = bf.knnMatch(des1,des2, k=2)
        # Apply ratio test
        good = []
        for m,n in matches:
            if m.distance < 0.75*n.distance:
                good.append([m])
        print(type(good[0][0]))# cv2.DMatch      
        img3 = cv.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=2)
    
        return img3
    

    参考:

    Introduction to SIFT (Scale-Invariant Feature Transform)

    https://docs.opencv.org/3.3.0/da/df5/tutorial_py_sift_intro.html

    图像相似度算法--SIFT算法详解

    https://blog.csdn.net/counte_rking/article/details/78834644

    SIFT特征点提取

    https://blog.csdn.net/lingyunxianhe/article/details/79063547

    DoG (Difference of Gaussian)角点检测

    https://blog.csdn.net/abcjennifer/article/details/7639488

    Surf特征提取分析

    https://www.cnblogs.com/YiXiaoZhou/p/5903690.html

    SURF算法

    https://www.cnblogs.com/jinjidexuetu/p/90ace4e8de574e3d5f4e6ac16a0dc157.html

  • 相关阅读:
    git 回滚merge的两个分支
    java 将一段时间分割为两个连续的时间
    Linux 命令记录
    C# WebBrowser 设置独立的代理
    VS2019 开发Django(八)------视图
    VS2019 开发Django(七)------VS2019不能格式化html代码
    VS2019 开发Django(六)------Admin中图片上传
    VS2019 开发Django(五)------createsuperuser
    VS2019 开发Django(四)------models
    VS2019 开发Django(三)------连接MySQL
  • 原文地址:https://www.cnblogs.com/hepc/p/9636474.html
Copyright © 2011-2022 走看看