Skip to content

Commit

Permalink
add match_test to visual the matches with own image
Browse files Browse the repository at this point in the history
  • Loading branch information
myboyhood committed Sep 13, 2023
1 parent 5a9e87d commit 171f3e3
Show file tree
Hide file tree
Showing 7 changed files with 767 additions and 0 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
# LightGlue_CIUS
Test using `meta_count` image pairs
```sh
conda activate superpoint # activate the conda env
python match_test.py # to save the matches plot
python match_test_loop.py # to make statistics of the matching time
```
- The image matched is shown below, seems good:
<p align="center">
<a><img src="assets/match_test.png" alt="match_show" width=100%></a>
<br>
<em>The match result in meta count. </em>
</p>

- Average time cost of 640*480 image with 540 keypoints is 110ms using device: RTX 2070 SUPER and i7-9700K CPU @ 3.60GHz × 8

## TODO:
Since there is no C++ version of LightGlue, we will wait official update the C++ version with TensorRT

---



<p align="center">
<h1 align="center"><ins>LightGlue ⚡️</ins><br>Local Feature Matching at Light Speed</h1>
<p align="center">
Expand Down
Binary file added assets/10_1683599558_070450.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/10_1683599558_173581.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/match_test.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
92 changes: 92 additions & 0 deletions match_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
from operator import truediv
from lightglue import LightGlue, SuperPoint, DISK
from lightglue.utils import load_image, rbd

# wzy add >>>>
import cv2
from pathlib import Path
import argparse
import random
import numpy as np
import matplotlib.cm as cm
import torch

from utils import (compute_pose_error, compute_epipolar_error,
estimate_pose, make_matching_plot,
error_colormap, AverageTimer, pose_auc, read_image,
rotate_intrinsics, rotate_pose_inplane,
scale_intrinsics)

torch.set_grad_enabled(False)
# wzy add <<<<


# SuperPoint+LightGlue
extractor = SuperPoint(max_num_keypoints=2048).eval().cuda() # load the extractor
matcher = LightGlue(features='superpoint').eval().cuda() # load the matcher

# or DISK+LightGlue
# extractor = DISK(max_num_keypoints=2048).eval().cuda() # load the extractor
# matcher = LightGlue(features='disk').eval().cuda() # load the matcher

# load each image as a torch.Tensor on GPU with shape (3,H,W), normalized in [0,1]
image0 = load_image('/home/zph/projects/LightGlue/assets/10_1683599558_173581.jpg').cuda()
image1 = load_image('/home/zph/projects/LightGlue/assets/10_1683599558_070450.jpg').cuda()

timer = AverageTimer(newline=True)
# extract local features
feats0 = extractor.extract(image0) # auto-resize the image, disable with resize=None
feats1 = extractor.extract(image1)

# match the features
matches01 = matcher({'image0': feats0, 'image1': feats1})
feats0, feats1, matches01 = [rbd(x) for x in [feats0, feats1, matches01]] # remove batch dimension
matches = matches01['matches'] # indices with shape (K,2)
points0 = feats0['keypoints'][matches[..., 0]] # coordinates in image #0, shape (K,2)
points1 = feats1['keypoints'][matches[..., 1]] # coordinates in image #1, shape (K,2)
print('number of points0: ', len(points0))
# print(points0)

# convert CUDA to CPU
image0 = image0.cpu().numpy().transpose((1, 2, 0)) # CxHxW to HxWxC
image1 = image1.cpu().numpy().transpose((1, 2, 0)) # CxHxW to HxWxC
# print(image0)
# print(image0.shape)

# cv2.imshow("image0",image0)
# cv2.waitKey(0)
# image0 = cv2.cvtColor(image0, cv2.COLOR_BGR2GRAY)
# image1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)

matches = matches.cpu().numpy()
points0 = points0.cpu().numpy()
points1 = points1.cpu().numpy()
# print(points0)

do_viz = True
fast_viz = False
opencv_display = True
show_keypoints = True
viz_path = '/home/zph/projects/LightGlue/assets/match_test.png'
mconf = np.ones(len(points0))


if do_viz:
# Visualize the matches.
color = cm.jet(mconf)
text = [
'LightGlue',
'Matches: {}'.format(len(points0)),
]

# Display extra parameter info.
small_text = [
'Image Pair: {}:{}'.format('kun0', 'kun1'),
]

make_matching_plot(
image0, image1, points0, points1, points0, points1, color,
text, viz_path, show_keypoints,
fast_viz, opencv_display, 'Matches', small_text)

timer.update('viz_match')
87 changes: 87 additions & 0 deletions match_test_loop.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
from operator import truediv
from time import time
from lightglue import LightGlue, SuperPoint, DISK
from lightglue.utils import load_image, rbd

# wzy add >>>>
import cv2
from pathlib import Path
import argparse
import random
import numpy as np
import matplotlib.cm as cm
import torch

from utils import (compute_pose_error, compute_epipolar_error,
estimate_pose, make_matching_plot,
error_colormap, AverageTimer, pose_auc, read_image,
rotate_intrinsics, rotate_pose_inplane,
scale_intrinsics)

torch.set_grad_enabled(False)
# wzy add <<<<


# SuperPoint+LightGlue
extractor = SuperPoint(max_num_keypoints=2048).eval().cuda() # load the extractor
matcher = LightGlue(features='superpoint').eval().cuda() # load the matcher

# or DISK+LightGlue
# extractor = DISK(max_num_keypoints=2048).eval().cuda() # load the extractor
# matcher = LightGlue(features='disk').eval().cuda() # load the matcher

# load each image as a torch.Tensor on GPU with shape (3,H,W), normalized in [0,1]
image0 = load_image('/home/zph/projects/LightGlue/assets/10_1683599558_173581.jpg').cuda()
image1 = load_image('/home/zph/projects/LightGlue/assets/10_1683599558_070450.jpg').cuda()

timer = AverageTimer(newline=True)
for i in range(1,20):
# extract local features
feats0 = extractor.extract(image0) # auto-resize the image, disable with resize=None
feats1 = extractor.extract(image1)

# match the features
matches01 = matcher({'image0': feats0, 'image1': feats1})
feats0, feats1, matches01 = [rbd(x) for x in [feats0, feats1, matches01]] # remove batch dimension
matches = matches01['matches'] # indices with shape (K,2)
points0 = feats0['keypoints'][matches[..., 0]] # coordinates in image #0, shape (K,2)
points1 = feats1['keypoints'][matches[..., 1]] # coordinates in image #1, shape (K,2)
print('number of points0: ', len(points0))

# convert CUDA to CPU
image0_cpu = image0.cpu().numpy().transpose((1, 2, 0)) # CxHxW to HxWxC
image1_cpu = image1.cpu().numpy().transpose((1, 2, 0)) # CxHxW to HxWxC
matches = matches.cpu().numpy()
points0 = points0.cpu().numpy()
points1 = points1.cpu().numpy()
timer.update('match loop sum')
timer.print()

do_viz = False
fast_viz = False
opencv_display = True
show_keypoints = True
viz_path = '/home/zph/projects/LightGlue/assets/match_test.png'
mconf = np.ones(len(points0))


if do_viz:
# Visualize the matches.
color = cm.jet(mconf)
text = [
'LightGlue',
'Keypoints: {}:{}'.format(len(points0), len(points1)),
'Matches: {}'.format(len(points0)),
]

# Display extra parameter info.
small_text = [
'Image Pair: {}:{}'.format('kun0', 'kun1'),
]

make_matching_plot(
image0, image1, points0, points1, points0, points1, color,
text, viz_path, show_keypoints,
fast_viz, opencv_display, 'Matches', small_text)

timer.update('viz_match')
Loading

0 comments on commit 171f3e3

Please sign in to comment.