• 004 OpenCV akaze特征点检测匹配


    目录

    一、环境

    二、akaze特征点算法

    2.1、基本原理

    2.2、实现过程

    2.3、实际应用

    2.4、优点与不足

    三、代码

    3.1、数据准备

    3.2、完整代码


    一、环境

    本文使用环境为:

    • Windows10
    • Python 3.9.17
    • opencv-python 4.8.0.74

    二、akaze特征点算法

    特征点检测算法AKAZE是一种广泛应用于图像处理领域的算法,它可以在不同尺度下提取图像的特征点,并具有尺度不变性和旋转不变性等优点。本文将概括介绍AKAZE算法的基本原理、实现过程以及其在实际应用中的表现。

    2.1、基本原理

    AKAZE算法是基于尺度空间理论和图像金字塔的,它通过非线性扩散滤波来构建尺度空间,并在尺度空间中检测关键点。在AKAZE中,关键点的检测是通过一个称为“加速非线性扩散”的过程来实现的,该过程可以快速地生成尺度空间。此外,AKAZE还采用了M-LDB描述子来描述特征点的周围区域。

    2.2、实现过程

    1. 图像预处理:首先,对输入图像进行预处理,包括灰度化和降噪等操作,以提高算法的准确性。
    2. 构建尺度空间:然后,通过非线性扩散滤波来构建尺度空间,并在尺度空间中检测关键点。在这个过程中,采用了一种称为“加速非线性扩散”的方法,该方法可以快速地生成尺度空间。
    3. 关键点检测:在尺度空间中,采用基于区域的方法来检测关键点。这些关键点对应于图像中的局部极值点,即在周围区域内具有最大或最小的灰度值。
    4. 描述子生成:在检测到关键点后,AKAZE采用M-LDB描述子来描述特征点的周围区域。M-LDB描述子是一种改进的LDB描述子,它可以更好地描述图像的特征。
    5. 特征匹配:最后,通过比较不同图像之间的M-LDB描述子来进行特征匹配,从而识别出图像中的相似区域。

    2.3、实际应用

    AKAZE算法在实际应用中表现出了良好的性能,可以应用于许多领域,如目标识别、图像配准、拼接等。例如,在目标识别中,AKAZE可以用于检测图像中的目标特征点,并通过特征匹配来识别出目标物体。此外,AKAZE还可以用于图像拼接中,通过对齐不同图像中的特征点来实现无缝拼接。

    2.4、优点与不足

    AKAZE算法具有以下优点:

    1. 尺度不变性:AKAZE算法能够在不同尺度下提取图像的特征点,从而适应了不同尺度的图像。
    2. 旋转不变性:AKAZE算法具有旋转不变性,可以在不同角度下提取图像的特征点。
    3. 加速性能:与SIFT算法相比,AKAZE算法采用了加速非线性扩散方法来构建尺度空间,具有更快的运行速度。
    4. 稳健性:AKAZE算法对噪声和干扰具有较强的鲁棒性,能够提取出较为稳健的特征点。

    然而,AKAZE算法也存在一些不足之处:

    1. 对光照变化敏感:AKAZE算法对光照变化较为敏感,可能会受到光照变化的影响。
    2. 对局部变化敏感:AKAZE算法对局部变化较为敏感,可能会导致误检或漏检。
    3. 需要手动设置参数:AKAZE算法需要手动设置一些参数,如尺度空间级数、加速非线性扩散的迭代次数等。这些参数的设置会影响到算法的性能和准确性。

    总之,特征点检测算法AKAZE是一种有效的图像特征提取方法,具有尺度不变性和旋转不变性等优点。在实际应用中表现出了良好的性能,可以应用于许多领域。然而,它也存在一些不足之处,如对光照变化敏感、对局部变化敏感以及需要手动设置参数等。未来可以进一步改进和完善AKAZE算法的性能和准确性。

    三、代码

    3.1、数据准备

    代码需要的两张图,一个xml格式的文件,即:H1to3p.xml,如下:

    1. "1.0"?>
    2. <opencv_storage>
    3. <H13 type_id="opencv-matrix">
    4. <rows>3rows>
    5. <cols>3cols>
    6. <dt>ddt>
    7. <data>
    8. 7.6285898e-01 -2.9922929e-01 2.2567123e+02
    9. 3.3443473e-01 1.0143901e+00 -7.6999973e+01
    10. 3.4663091e-04 -1.4364524e-05 1.0000000e+00 data>H13>
    11. opencv_storage>

    3.2、完整代码

    代码:

    1. from __future__ import print_function
    2. import cv2 as cv
    3. import numpy as np
    4. import argparse
    5. from math import sqrt
    6. # 读取两张图片
    7. parser = argparse.ArgumentParser(description='Code for AKAZE local features matching tutorial.')
    8. parser.add_argument('--input1', help='Path to input image 1.', default='graf1.png') # 在这里设置图像1
    9. parser.add_argument('--input2', help='Path to input image 2.', default='graf3.png') # 在这里设置图像2
    10. parser.add_argument('--homography', help='Path to the homography matrix.', default='H1to3p.xml') # 在这里设置H矩阵
    11. args = parser.parse_args()
    12. img1 = cv.imread(cv.samples.findFile(args.input1), cv.IMREAD_GRAYSCALE)
    13. img2 = cv.imread(cv.samples.findFile(args.input2), cv.IMREAD_GRAYSCALE)
    14. if img1 is None or img2 is None:
    15. print('Could not open or find the images!')
    16. exit(0)
    17. fs = cv.FileStorage(cv.samples.findFile(args.homography), cv.FILE_STORAGE_READ)
    18. homography = fs.getFirstTopLevelNode().mat()
    19. ## 初始化算法[AKAZE]
    20. akaze = cv.AKAZE_create()
    21. # 检测图像1和图像2的特征点和特征向量
    22. kpts1, desc1 = akaze.detectAndCompute(img1, None)
    23. kpts2, desc2 = akaze.detectAndCompute(img2, None)
    24. ## 基于汉明距离,使用暴力匹配来匹配特征点
    25. matcher = cv.DescriptorMatcher_create(cv.DescriptorMatcher_BRUTEFORCE_HAMMING)
    26. nn_matches = matcher.knnMatch(desc1, desc2, 2)
    27. ## 下面0.8默认参数,可以手动修改、调试
    28. matched1 = []
    29. matched2 = []
    30. nn_match_ratio = 0.8 # 最近邻匹配参数
    31. for m, n in nn_matches:
    32. if m.distance < nn_match_ratio * n.distance:
    33. matched1.append(kpts1[m.queryIdx])
    34. matched2.append(kpts2[m.trainIdx])
    35. ## 使用单应矩阵进行精匹配,进一步剔除误匹配点
    36. inliers1 = []
    37. inliers2 = []
    38. good_matches = []
    39. inlier_threshold = 2.5 # 如果两个点距离小于这个值,表明足够近,也就是一对匹配对
    40. for i, m in enumerate(matched1):
    41. col = np.ones((3,1), dtype=np.float64)
    42. col[0:2,0] = m.pt
    43. col = np.dot(homography, col)
    44. col /= col[2,0]
    45. dist = sqrt(pow(col[0,0] - matched2[i].pt[0], 2) +\
    46. pow(col[1,0] - matched2[i].pt[1], 2))
    47. if dist < inlier_threshold:
    48. good_matches.append(cv.DMatch(len(inliers1), len(inliers2), 0))
    49. inliers1.append(matched1[i])
    50. inliers2.append(matched2[i])
    51. ## 可视化
    52. res = np.empty((max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1], 3), dtype=np.uint8)
    53. cv.drawMatches(img1, inliers1, img2, inliers2, good_matches, res)
    54. cv.imwrite("akaze_result.png", res)
    55. inlier_ratio = len(inliers1) / float(len(matched1))
    56. print('A-KAZE Matching Results')
    57. print('*******************************')
    58. print('# Keypoints 1: \t', len(kpts1))
    59. print('# Keypoints 2: \t', len(kpts2))
    60. print('# Matches: \t', len(matched1))
    61. print('# Inliers: \t', len(inliers1))
    62. print('# Inliers Ratio: \t', inlier_ratio)
    63. cv.imshow('result', res)
    64. cv.waitKey()

  • 相关阅读:
    悄悄上线:CSS @starting-style 新规则
    二叉搜索树的实现
    C++核心编程
    万字详解以太坊合并后可能面临的 PoS 攻击及防御措施
    使用spark-sql处理Doris大表关联
    java计算机毕业设计健康医疗预约系统源码+mysql数据库+系统+lw文档+部署
    事关Django的静态资源目录设置与静态资源文件引用(Django的setting.py中的三句静态资源(static)目录设置语句分别是什么作用?)
    Vuex基本流程及 mapState mapMutations mapActions 简写形式
    两台Linux文件夹单向同步【inotify、rsync、ssh】
    Java将JPG/PNG图片转换为WEBP格式,以及WEBP转换成JPG/PNG格式
  • 原文地址:https://blog.csdn.net/m0_72734364/article/details/134468628