gberton commited on
Commit
37bb43d
·
1 Parent(s): 7cb9f79

Change pipeline tag, improve README, add LICENSE, make model faster and lighter

Browse files
Files changed (3) hide show
  1. LICENSE +21 -0
  2. README.md +17 -6
  3. megaloc_model.py +3 -9
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Gabriele Berton, Carlo Masone
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- pipeline_tag: visual-document-retrieval
3
  library_name: pytorch
4
  license: mit
5
  tags:
@@ -20,13 +20,24 @@ MegaLoc is an image retrieval model for visual place recognition (VPR) that achi
20
 
21
  ```python
22
  import torch
 
 
 
23
  model = torch.hub.load("gmberton/MegaLoc", "get_trained_model")
24
- model.eval()
25
 
26
- # Extract descriptor from an image
27
- image = torch.randn(1, 3, 322, 322) # [B, 3, H, W] - any size works
28
- with torch.no_grad():
29
- descriptor = model(image) # [B, 8448] L2-normalized descriptor
 
 
 
 
 
 
 
 
 
30
  ```
31
 
32
  For benchmarking on VPR datasets, see [VPR-methods-evaluation](https://github.com/gmberton/VPR-methods-evaluation).
 
1
  ---
2
+ pipeline_tag: image-feature-extraction
3
  library_name: pytorch
4
  license: mit
5
  tags:
 
20
 
21
  ```python
22
  import torch
23
+ import torchvision.transforms as tfm
24
+ from PIL import Image
25
+
26
  model = torch.hub.load("gmberton/MegaLoc", "get_trained_model")
 
27
 
28
+ # Same preprocessing we use for evaluation: ImageNet normalization, resize to 322x322
29
+ # (any resolution works, paper results are computed at 322x322)
30
+ transform = tfm.Compose([
31
+ tfm.ToTensor(),
32
+ tfm.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
33
+ tfm.Resize(size=[322, 322], antialias=True),
34
+ ])
35
+
36
+ images = torch.stack([transform(Image.open(path).convert("RGB")) for path in ["im1.jpg", "im2.jpg"]])
37
+ with torch.inference_mode():
38
+ descriptors = model(images) # shape [2, 8448], L2-normalized
39
+
40
+ similarities = descriptors @ descriptors.T # cosine similarities
41
  ```
42
 
43
  For benchmarking on VPR datasets, see [VPR-methods-evaluation](https://github.com/gmberton/VPR-methods-evaluation).
megaloc_model.py CHANGED
@@ -142,13 +142,10 @@ class FeatureAggregator(nn.Module):
142
  p = torch.exp(p)
143
  p = p[:, :-1, :]
144
 
145
- p = p.unsqueeze(1).repeat(1, self.cluster_dim, 1, 1)
146
- f = f.unsqueeze(2).repeat(1, 1, self.num_clusters, 1)
147
-
148
  f = torch.cat(
149
  [
150
  F.normalize(t, p=2, dim=-1),
151
- F.normalize((f * p).sum(dim=-1), p=2, dim=1).flatten(1),
152
  ],
153
  dim=-1,
154
  )
@@ -212,11 +209,8 @@ class MultiHeadAttention(nn.Module):
212
  qkv = qkv.permute(2, 0, 3, 1, 4)
213
  q, k, v = qkv[0], qkv[1], qkv[2]
214
 
215
- attn = (q @ k.transpose(-2, -1)) * self.scale
216
- attn = attn.softmax(dim=-1)
217
- attn = self.attn_drop(attn)
218
-
219
- x = (attn @ v).transpose(1, 2).reshape(B, N, C)
220
  x = self.proj(x)
221
  x = self.proj_drop(x)
222
 
 
142
  p = torch.exp(p)
143
  p = p[:, :-1, :]
144
 
 
 
 
145
  f = torch.cat(
146
  [
147
  F.normalize(t, p=2, dim=-1),
148
+ F.normalize(torch.einsum("bdn,bkn->bdk", f, p), p=2, dim=1).flatten(1),
149
  ],
150
  dim=-1,
151
  )
 
209
  qkv = qkv.permute(2, 0, 3, 1, 4)
210
  q, k, v = qkv[0], qkv[1], qkv[2]
211
 
212
+ x = F.scaled_dot_product_attention(q, k, v, dropout_p=self.attn_drop.p if self.training else 0.0)
213
+ x = x.transpose(1, 2).reshape(B, N, C)
 
 
 
214
  x = self.proj(x)
215
  x = self.proj_drop(x)
216