35from typing
import List, Optional, Tuple
40from pathlib
import Path
42import torch.nn.functional
as F
44from visp.core
import ImageRGBa
48 assert len(kps) == 0
or isinstance(kps, np.ndarray)
and len(kps.shape) == 2
and kps.shape[1] == 2
49 assert len(kps) == len(descriptors)
53 def split(self, i1, i2) -> Tuple['XFeatRepresentation', 'XFeatRepresentation']:
66 def copy(self) -> 'XFeatRepresentation':
69 def merged_with(self, r:
'XFeatRepresentation') ->
'XFeatRepresentation':
70 keypoints = np.concatenate((self.
keypoints, r.keypoints), axis=0)
71 descriptors = torch.concatenate((self.
descriptors, r.descriptors), dim=0)
79 'descriptors': descriptors,
85 repr1 = {k: v[i1]
for k, v
in self.
repr.items()}
86 repr2 = {k: v[i2]
for k, v
in self.
repr.items()}
87 return (
XFeatStarRepresentation(*(r[k]
for k
in [
'keypoints',
'descriptors',
'scale']))
for r
in (repr1, repr2))
89 def add(self, r:
'XFeatStarRepresentation'):
90 raise RuntimeError(
'Not implemented')
94 def __init__(self, num_points: int, min_cos: float, use_dense=
False, scale_factor = 1.0):
96 self.
xfeat = torch.hub.load(
'verlab/accelerated_features',
'XFeat', pretrained =
True, top_k = 4096).eval()
98 print(
'Could not load XFeat from torchhub', file=sys.stderr)
99 xfeat_env_var_name =
'XFEAT_PATH'
100 print(f
'Looking at {xfeat_env_var_name} environment variable to load XFeat!', file=sys.stderr)
102 if not xfeat_env_var_name
in os.environ:
103 raise EnvironmentError(
'you should set the value of the environment variable XFEAT_PATH to the folder containing the xfeat sources')
105 xfeat_path = Path(os.environ[xfeat_env_var_name]).absolute()
106 if not xfeat_path.exists():
107 raise EnvironmentError(f
'XFeat folder {str(xfeat_path)} does not exist')
109 sys.path.append(str(xfeat_path))
110 from modules.xfeat
import XFeat
111 self.
xfeat = XFeat().eval()
119 self.
k = d[
'numPoints']
125 idx0, idx1 = matches[0]
128 offsets = self.
xfeat.net.fine_matcher(torch.cat([feats1[idx0], feats2[idx1]],dim=-1))
129 conf = F.softmax(offsets*3, dim=-1).max(dim=-1)[0]
131 mask_good = conf > fine_conf
133 return idx0[mask_good], idx1[mask_good]
135 def match_dense(self, r1: torch.Tensor, descriptors: torch.Tensor, min_cossim=
None):
136 if min_cossim
is None:
138 with torch.no_grad():
139 idxs_list = self.
xfeat.batch_match(r1[
None], descriptors[
None], min_cossim)
140 indices_1, indices_2 = self.
refine_dense(r1, descriptors, matches=idxs_list)
141 return indices_1, indices_2
143 def match(self, r1: torch.Tensor, descriptors: torch.Tensor, min_cos=
None):
149 if len(r1.size()) == 3:
150 assert r1.size(0) == 1
152 if len(descriptors.size()) == 3:
153 assert descriptors.size(0) == 1
154 descriptors = descriptors[0]
157 return self.
xfeat.
match(r1, descriptors, min_cossim=min_cos)
162 with torch.no_grad():
165 rgb = self.
xfeat.parse_input(image.numpy())
168 rgb = torch.nn.functional.interpolate(rgb, scale_factor=self.
scale_factor, mode=
'nearest', antialias=
True, align_corners=
True)
169 print(
'Interp took: ', (time.time() - t1) * 1000)
172 representation = self.
xfeat.detectAndComputeDense(rgb, top_k = top_k, multiscale=
True)
174 kps = representation[
'keypoints'][0]
177 return kps.cpu().numpy(), representation[
'descriptors'][0], representation[
'scales'][0].cpu().numpy()
179 def detect(self, IRGB) -> XFeatRepresentation:
183 rgb = torch.from_numpy(IRGB.numpy()[
None, ..., :3]).to(self.
xfeat.dev).permute((0, 3, 1, 2)) / 255.0
186 rgb = torch.nn.functional.interpolate(rgb, scale_factor=self.
scale_factor, mode=
'nearest')
189 rep = self.
xfeat.detectAndCompute(rgb, top_k = self.
k)[0]
192 'keypoints': torch.empty((0,)),
193 'descriptors': torch.empty((0,))
195 kps = rep[
'keypoints'].cpu().numpy()
refine_dense(self, feats1, feats2, matches, fine_conf=0.0)
match_dense(self, torch.Tensor r1, torch.Tensor descriptors, min_cossim=None)
computeDense(self, ImageRGBa image, top_k=None)
load_settings(self, dict d)
match(self, torch.Tensor r1, torch.Tensor descriptors, min_cos=None)
__init__(self, int num_points, float min_cos, use_dense=False, scale_factor=1.0)
XFeatRepresentation detect(self, IRGB)
__init__(self, kps, descriptors)
'XFeatRepresentation' copy(self)
'XFeatRepresentation' merged_with(self, 'XFeatRepresentation' r)
Tuple[ 'XFeatRepresentation', 'XFeatRepresentation'] split(self, i1, i2)
__init__(self, kps, descriptors, scales)
add(self, 'XFeatStarRepresentation' r)