当前位置:   article > 正文

SuperGluePretrainedNetwork调用接口版本(两个版本!)_superglue matches

superglue matches

        本脚本是一个基于Python的应用,旨在演示如何使用SuperGlue算法进行图像之间的特征匹配。SuperGlue是一个强大的特征匹配工具,能够在不同的图像之间找到对应的关键点。这个工具尤其适用于计算机视觉任务,如立体视觉、图像拼接、对象识别和追踪等场景。脚本使用PyTorch框架,并且可以选择在CPU或GPU上运行。

脚本的工作流程如下:

  1. 解析命令行参数,用于设置输入输出目录、图像尺寸、SuperGlue配置等。
  2. 根据用户选择,决定算法是在CPU还是GPU上执行。
  3. 加载预设的配置,初始化SuperPoint和SuperGlue模型。
  4. 定义图像预处理函数来调整图像大小。
  5. 加载两幅图像,调整它们的大小,并将它们转换为PyTorch张量。
  6. 使用SuperPoint提取关键点和描述符。
  7. 使用SuperGlue算法匹配两幅图像的关键点。
  8. 可视化并打印匹配的关键点坐标。
  9. 如果设置了输出目录,将结果图像写到磁盘上。

        这个脚本展示了如何在实践中使用深度学习模型来处理实际问题,并提供了图像匹配演示。

  1. #! /usr/bin/env python3
  2. import argparse
  3. import matplotlib.cm as cm
  4. import cv2
  5. from pathlib import Path
  6. import torch
  7. from models.matching import Matching
  8. from models.utils import (make_matching_plot_fast, frame2tensor)
  9. torch.set_grad_enabled(False) # 关闭PyTorch的梯度计算,提高效率,因为我们不需要进行模型训练
  10. # 创建命令行参数解析器,以便从命令行接收参数
  11. parser = argparse.ArgumentParser(description='SuperGlue',
  12. formatter_class=argparse.ArgumentDefaultsHelpFormatter)
  13. # 添加命令行参数
  14. parser.add_argument('--input', type=str, default='assets/freiburg_sequence/',
  15. help='Input directory or video file')
  16. parser.add_argument('--output_dir', type=str, default=None,
  17. help='Directory to write output frames (default: None)')
  18. parser.add_argument('--resize', type=int, nargs='+', default=[1241, 376],
  19. help='Resize input frames (default: [640, 480])')
  20. parser.add_argument('--superglue', choices={'indoor', 'outdoor'}, default='outdoor',
  21. help='SuperGlue weights (default: indoor)')
  22. parser.add_argument('--show_keypoints', action='store_true',
  23. help='Show detected keypoints (default: False)')
  24. parser.add_argument('--no_display', action='store_true',
  25. help='Do not display images (useful when running remotely)')
  26. parser.add_argument('--force_cpu', action='store_true',
  27. help='Force PyTorch to run on CPU')
  28. # 解析命令行参数
  29. opt = parser.parse_args()
  30. # 确定程序是运行在GPU还是CPU
  31. device = 'cuda' if torch.cuda.is_available() and not opt.force_cpu else 'cpu'
  32. # 设置SuperPoint和SuperGlue的配置参数
  33. config = {
  34. 'superpoint': {
  35. 'nms_radius': 4,
  36. 'keypoint_threshold': 0.005,
  37. 'max_keypoints': -1
  38. },
  39. 'superglue': {
  40. 'weights': opt.superglue,
  41. 'sinkhorn_iterations': 20,
  42. 'match_threshold': 0.2,
  43. }
  44. }
  45. # 创建Matching类的实例,用于图像匹配
  46. matching = Matching(config).eval().to(device)
  47. keys = ['keypoints', 'scores', 'descriptors']
  48. # 函数:处理图像尺寸调整
  49. def process_resize(w, h, resize):
  50. # 确保resize参数是合法的
  51. assert(len(resize) > 0 and len(resize) <= 2)
  52. # 如果只提供了一个值,基于最大维度调整比例
  53. if len(resize) == 1 and resize[0] > -1:
  54. scale = resize[0] / max(h, w)
  55. w_new, h_new = int(round(w*scale)), int(round(h*scale))
  56. # 如果提供的值是-1,保持原有尺寸
  57. elif len(resize) == 1 and resize[0] == -1:
  58. w_new, h_new = w, h
  59. else: # len(resize) == 2: # 如果提供了两个值,直接使用这两个值作为新的宽和高
  60. w_new, h_new = resize[0], resize[1]
  61. # 如果新的分辨率太小或太大,给出警告
  62. if max(w_new, h_new) < 160:
  63. print('警告:输入分辨率非常小,结果可能会有很大差异')
  64. elif max(w_new, h_new) > 2000:
  65. print('警告:输入分辨率非常大,可能会导致内存不足')
  66. return w_new, h_new
  67. # 定义load_image函数,用于加载和预处理图像
  68. def load_image(impath, resize):
  69. grayim = cv2.imread(impath, 0)
  70. # 以灰度模式读取图像
  71. if grayim is None:
  72. raise Exception('Error reading image %s' % impath)
  73. w, h = grayim.shape[1], grayim.shape[0]
  74. w_new, h_new = process_resize(w, h, resize)
  75. # 调用process_resize函数计算调整后的尺寸
  76. grayim = cv2.resize(grayim, (w_new, h_new), interpolation=cv2.INTER_AREA)
  77. # 使用cv2.resize函数调整图像尺寸
  78. return grayim
  79. # 返回调整后的灰度图像
  80. image_path_0 = "/home/fairlee/786D6A341753F4B4/KITTI/sequences_kitti_00_21/01/image_0/000000.png"
  81. frame0 = load_image(image_path_0, opt.resize)
  82. image_path_1 = "/home/fairlee/786D6A341753F4B4/KITTI/sequences_kitti_00_21/01/image_0/000001.png"
  83. frame1 = load_image(image_path_1, opt.resize)
  84. if __name__ == '__main__':
  85. # 将第一帧图像转换为张量,并移动到指定设备上
  86. frame_tensor0 = frame2tensor(frame0, device)
  87. # 使用SuperPoint提取第一帧图像的关键点和描述符
  88. last_data = matching.superpoint({'image': frame_tensor0})
  89. # 为第一帧图像的关键点、得分和描述符添加'0'后缀,以区分不同帧
  90. last_data = {k + '0': last_data[k] for k in keys}
  91. # 将第一帧图像的张量存储在last_data字典中
  92. last_data['image0'] = frame_tensor0
  93. # 存储第一帧图像
  94. last_frame = frame0
  95. # 存储第一帧图像的ID
  96. last_image_id = 0
  97. # 将第二帧图像转换为张量,并移动到指定设备上
  98. frame_tensor1 = frame2tensor(frame1, device)
  99. # 使用SuperGlue进行特征匹配,将第一帧图像的数据与第二帧图像的张量传递给matching函数
  100. pred = matching({**last_data, 'image1': frame_tensor1})
  101. # 获取第一帧图像的关键点坐标,并将其转换为NumPy数组
  102. kpts0 = last_data['keypoints0'][0].cpu().numpy()
  103. # 获取第二帧图像的关键点坐标,并将其转换为NumPy数组
  104. kpts1 = pred['keypoints1'][0].cpu().numpy()
  105. # 获取匹配结果,将其转换为NumPy数组
  106. matches = pred['matches0'][0].cpu().numpy()
  107. # 获取匹配置信度,将其转换为NumPy数组
  108. confidence = pred['matching_scores0'][0].cpu().numpy()
  109. # 找到有效的匹配,即匹配索引大于-1的位置
  110. valid = matches > -1
  111. # 获取第一帧图像中有效匹配的关键点坐标
  112. mkpts0 = kpts0[valid]
  113. # 获取第二帧图像中与第一帧图像有效匹配的关键点坐标
  114. mkpts1 = kpts1[matches[valid]]
  115. stem0, stem1 = last_image_id, 1
  116. # 打印匹配的关键点信息
  117. print(f"Matched keypoints in frame {stem0} and {stem1}:")
  118. for i, (kp0, kp1) in enumerate(zip(mkpts0, mkpts1)):
  119. print(f"Match {i}: ({kp0[0]:.2f}, {kp0[1]:.2f}) -> ({kp1[0]:.2f}, {kp1[1]:.2f})")
  120. color = cm.jet(confidence[valid])
  121. text = [
  122. 'SuperGlue',
  123. 'Keypoints: {}:{}'.format(len(kpts0), len(kpts1)),
  124. 'Matches: {}'.format(len(mkpts0))
  125. ]
  126. k_thresh = matching.superpoint.config['keypoint_threshold']
  127. m_thresh = matching.superglue.config['match_threshold']
  128. small_text = [
  129. 'Keypoint Threshold: {:.4f}'.format(k_thresh),
  130. 'Match Threshold: {:.2f}'.format(m_thresh),
  131. 'Image Pair: {:06}:{:06}'.format(stem0, stem1),
  132. ]
  133. out = make_matching_plot_fast(
  134. last_frame, frame1, kpts0, kpts1, mkpts0, mkpts1, color, text,
  135. path=None, show_keypoints=opt.show_keypoints, small_text=small_text)
  136. if not opt.no_display:
  137. cv2.imshow('SuperGlue matches', out)
  138. cv2.waitKey(0)
  139. cv2.destroyAllWindows()
  140. if opt.output_dir is not None:
  141. stem = 'matches_{:06}_{:06}'.format(stem0, stem1)
  142. out_file = str(Path(opt.output_dir, stem + '.png'))
  143. print('\nWriting image to {}'.format(out_file))
  144. cv2.imwrite(out_file, out)

第二个版本的代码:

  1. #! /usr/bin/env python3
  2. import cv2
  3. import torch
  4. from models.matching import Matching
  5. from models.utils import (frame2tensor)
  6. torch.set_grad_enabled(False)
  7. # 设置SuperPoint和SuperGlue的配置参数
  8. config = {
  9. 'superpoint': {
  10. 'nms_radius': 4,
  11. 'keypoint_threshold': 0.005,
  12. 'max_keypoints': -1
  13. },
  14. 'superglue': {
  15. 'weights': 'outdoor',
  16. 'sinkhorn_iterations': 20,
  17. 'match_threshold': 0.2,
  18. }
  19. }
  20. device = 'cuda' if torch.cuda.is_available() else 'cpu'
  21. # 创建Matching类的实例,用于图像匹配
  22. matching = Matching(config).eval().to(device)
  23. keys = ['keypoints', 'scores', 'descriptors']
  24. # 对于灰度图像,返回的NumPy数组将是一个二维数组,其中数组的形状对应于图像的高度和宽度(H x W)。
  25. # 每个元素的值代表了对应像素的亮度,通常是一个0到255的整数(对于8位灰度图像)。
  26. frame0 = cv2.imread("/home/fairlee/000001.jpg", 0)
  27. frame1 = cv2.imread("/home/fairlee/000000.jpg", 0)
  28. def match_frames(frame0, frame1, device, matching, keys):
  29. """
  30. Match keypoints between two frames and return the matched coordinates and confidence scores.
  31. Parameters:
  32. - frame0: Numpy array, first image frame.
  33. - frame1: Numpy array, second image frame.
  34. - device: The device to perform computation on.
  35. - matching: Matching object with a method to match points between frames.
  36. - keys: List of keys to extract from the matching data.
  37. Returns:
  38. A tuple of (mkpts0, mkpts1, confidence_scores), where:
  39. - mkpts0: Matched keypoints in the first frame.
  40. - mkpts1: Matched keypoints in the second frame.
  41. - confidence_scores: Confidence scores of the matches.
  42. """
  43. # Convert frames to tensors and move to the device
  44. frame_tensor0 = frame2tensor(frame0, device)
  45. frame_tensor1 = frame2tensor(frame1, device)
  46. # Get data from the first frame
  47. last_data = matching.superpoint({'image': frame_tensor0})
  48. last_data = {k + '0': last_data[k] for k in keys}
  49. last_data['image0'] = frame_tensor0
  50. # Perform matching
  51. pred = matching({**last_data, 'image1': frame_tensor1})
  52. # Extract keypoints and convert to Numpy arrays
  53. kpts0 = last_data['keypoints0'][0].cpu().numpy()
  54. kpts1 = pred['keypoints1'][0].cpu().numpy()
  55. # Extract matches and confidence scores, convert to Numpy arrays
  56. matches = pred['matches0'][0].cpu().numpy()
  57. confidence = pred['matching_scores0'][0].cpu().numpy()
  58. # Filter valid matches
  59. valid = matches > -1
  60. mkpts0 = kpts0[valid]
  61. mkpts1 = kpts1[matches[valid]]
  62. return mkpts0, mkpts1, confidence[valid]

结果:

         通过运行这段代码,我们可以看到SuperGlue算法在图像特征匹配方面的强大能力。代码首先处理输入图像,然后使用SuperPoint模型提取特征点和描述子,接着SuperGlue模型根据描述子进行关键点匹配。匹配过程的结果会被可视化显示出来,如果指定了输出目录,还会将结果图像保存下来。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/747822
推荐阅读
相关标签
  

闽ICP备14008679号