# Patch-NetVLAD re-ranks place recognition results with local feature matches

> Patch-NetVLAD is the reference implementation of the CVPR 2021 paper that combines a global NetVLAD descriptor with local patch matches to improve visual place recognition. It suits robotics and mapping researchers who want the paper's pipeline rather than a library.

**QVPR/Patch-NetVLAD** — Code for the CVPR2021 paper "Patch-NetVLAD: Multi-Scale Fusion of Locally-Global Descriptors for Place Recognition"

- Repository: https://github.com/QVPR/Patch-NetVLAD
- Stars: 600 · Forks: 77
- Language: Python
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/qvpr-patch-netvlad

## Two descriptors, one ranking

The repository contains the code for the CVPR 2021 paper Patch-NetVLAD: Multi-Scale Fusion of Locally-Global Descriptors for Place Recognition, with the article on arXiv and in the official proceedings. The problem it addresses is a specific weakness in visual place recognition. A global descriptor such as NetVLAD summarises an entire image into one vector, which makes retrieval fast, but the vector discards the spatial detail you need to tell two visually similar places apart, and it says nothing about which parts of the query actually correspond to parts of the candidate. The paper's contribution is a fusion of locally global descriptors at multiple scales, which is why the name combines patch and NetVLAD. The output artefacts in the repository make the two stage structure visible. There is a file of top 100 reference images for each query image obtained using vanilla NetVLAD, and a second file with the same reference images re-ranked by Patch-NetVLAD, both in Kapture format. The audience is researchers in visual place recognition, robot localisation and mapping, and the code is packaged as a script collection rather than as a tidy library with a stable API.

## pixi is the environment, and the scripts are the interface

The project recommends using pixi to install all dependencies from conda-forge, and the install step is a single command:

```bash
pixi install
```

The pixi.toml installs Patch-NetVLAD as an editable Python package and provides tasks for common workflows. Passing less common script options is done by appending them after a double dash, for example pixi run extract with -- --nocuda. That detail matters more than it looks, because the underlying scripts are ordinary Python entry points with argparse style options, and the double dash is what passes them through the task runner. The package metadata confirms the shape. The project name is patchnetvlad at version 0.2.0, it is built with scikit-build-core, and it requires Python 3.9 or newer. The declared dependencies list is empty, because the environment is described by pixi.toml and the lockfile rather than by the package metadata. What the metadata does give you is the command line surface, with console scripts named patchnetvlad-match-two, patchnetvlad-feature-match, patchnetvlad-feature-extract, patchnetvlad-train, patchnetvlad-match-realtime and patchnetvlad-download-models. Each maps to a module at the repository root, and the sdist include list in the build configuration names the same set of scripts, which tells you the package is meant to be installed and run, not only cloned and read.

## Pretrained weights are downloaded on first use, or by hand

Several pretrained models and configuration files are provided, and the models are downloaded automatically into the pretrained_models directory the first time feature extraction is performed. The download script exists as a separate task, and the manual route is documented for anyone who wants the files up front:

```bash
  # Note: the pre-trained models will be downloaded automatically the first time feature extraction is performed
  # the steps below are optional!

  # You can use the download script which automatically downloads the models:
  pixi run download-models
```

The manual commands fetch each weight file by name, and the naming shows the design of the method. There are Mapillary and Pittsburgh variants at three descriptor sizes each, 128, 512 and 4096, plus a landmarks variant at 4096, and the WPCA prefix on each file refers to the aggregation applied to the local features. The size range is the multi-scale part of the paper, and the two datasets reflect that the same architecture is trained for street scenes and for a different domain. If you prefer to fetch them yourself, the individual wget commands are given. The recommendation is to put them in the pretrained_models folder, which is what the configuration files in the configs directory point at, so a manual download that lands the files elsewhere will not be found.

## Extract, then match, then read the two prediction files

The quick start is a three stage flow with a configuration file doing the work. You replace performance.ini with speed.ini or storage.ini depending on which trade-off you want, and you adapt the dataset paths, with the examples given for the Pittsburgh30k dataset and the note that pitts30k can simply be replaced with tokyo247 or nordland. Feature extraction takes a list of image names, the dataset root, and an output prefix:

```bash
pixi run extract \
  pitts30k_imageNames_index.txt \
  /path/to/your/pitts/dataset \
  patchnetvlad/output_features/pitts30k_index
```

You repeat it for the query images by replacing _index with _query, adjusting dataset_root_dir as needed. Feature matching then takes the query and index name lists, the two feature directories, the dataset path, a result folder, and optionally a ground truth file:

```bash
pixi run match \
  pitts30k_imageNames_query.txt \
  pitts30k_imageNames_index.txt \
  patchnetvlad/output_features/pitts30k_query \
  patchnetvlad/output_features/pitts30k_index \
  /path/to/your/pitts/dataset \
  patchnetvlad/results/pitts30k \
  -- --ground_truth_path patchnetvlad/dataset_gt_files/pitts30k_test.npz
```

The ground_truth_path is optional, and when it is supplied you also get recalls.txt in addition to the two prediction files. That distinction is worth internalising, because the recall numbers and the rankings come from different sources, and the ranking file is the actual output of the method while the recall file is the evaluation of it. The repository also carries add_pca.py, download_models.py, feature_extract.py, feature_match.py, match_realtime.py, match_two.py, train.py, a patchnetvlad/ package directory and a CMakeLists.txt.

## Matching two images directly, with a picture of the result

For a quick look without a dataset, there is a two file mode. The match_two script computes the Patch-NetVLAD features for two given images and then determines the local feature matching between them, and while example images are provided, any image pair can be used:

```bash
pixi run match-two \
  patchnetvlad/example_images/tokyo_query.jpg \
  patchnetvlad/example_images/tokyo_db.png
```

The output is a score, where a larger score indicates more similar images and a lower score means dissimilar ones, and a matching figure showing the patch correspondences after RANSAC between the two images, saved as results/patchMatchings.png. This is the most useful entry point for understanding the method, because it shows the thing the paper is actually about. A global descriptor gives you a number; this shows you which patches in the query matched which patches in the database image and which of those matches survived the RANSAC filter, which is the evidence a global vector discards. A script named match_realtime.py sits in the same family for the live case, and the training task is invoked with pixi run train and a path to your data.

## What this repository is and is not

The honest framing is that this is a paper implementation, and that shapes both its value and its limits. The value is that it is the code that produced the published numbers, with the pretrained weights, the three dataset configurations and the evaluation scripts, so anyone trying to reproduce or extend that line of work starts from the same baseline. Two things follow from the paper framing. The first is that the interface is scripts and configuration files rather than a stable library API, so it is awkward to embed in an application that wants descriptors as a service. The second is that the domain is bounded. This is visual place recognition for a camera looking at a street, and the pretrained weights are trained on Mapillary, Pittsburgh and landmarks data, so an application in a different environment, a warehouse, an underwater vehicle or a night time camera, is outside what the shipped models cover. The alternative approaches differ in kind. A general purpose image retrieval system gives you a general purpose interface and no method specific gains. A learned local feature approach, with its own matching pipeline, does the same job as this one without the NetVLAD global stage, and is a reasonable choice if you do not want the two stage design. What this repository offers that a generic retriever does not is the specific claim that fusing local patch matches into a global descriptor ranking improves place recognition, and the code and weights to test that claim for yourself.

## Conclusion

Adopt Patch-NetVLAD if you are reproducing or building on the CVPR 2021 place recognition paper and want the reference pipeline, the pretrained weights and the evaluation scripts rather than a general purpose retrieval library. Do not adopt it as a production image search dependency, since it is a research release with a narrow script oriented interface and no published version since v0.1.8 in 2024. Before you start, read the paper rather than the code, check that pixi resolves the environment on your machine, and download the pretrained models early, because the first feature extraction run fetches them over the network.

## FAQ

### What is Patch-NetVLAD?

It is the code for the CVPR 2021 paper Patch-NetVLAD: Multi-Scale Fusion of Locally-Global Descriptors for Place Recognition. The approach combines a global NetVLAD descriptor with local patch level matches at multiple scales to improve visual place recognition.

### How do I install the Patch-NetVLAD dependencies?

Using pixi, which pulls dependencies from conda-forge: run `pixi install`. The pixi.toml installs the package in editable mode and defines the tasks, and less common script options are passed after a double dash, for example `pixi run extract ... -- --nocuda`.

### Where do the pretrained Patch-NetVLAD models come from?

They are downloaded automatically into the pretrained_models folder the first time feature extraction runs, or you can run `pixi run download-models`, or fetch the individual .pth.tar files by hand with wget. The set includes Mapillary and Pittsburgh variants at WPCA 128, 512 and 4096, plus a landmarks variant at 4096.

### How do I run Patch-NetVLAD on my own images?

Use the match-two task with any pair of images. The script computes features for both and prints a score, larger meaning more similar, and saves a figure of the patch correspondences after RANSAC to results/patchMatchings.png. Example images for Tokyo are included but are not required.

### What licence is Patch-NetVLAD released under and what citation is required?

The code is under the MIT License, with the terms in the LICENSE file. The project asks that you refer to the paper in your publications, with the citation given in the documentation for the Hausler, Garg, Xu, Milford and Fischer CVPR 2021 paper.

## Sources

- [Issues](https://github.com/QVPR/Patch-NetVLAD/issues)
- [License: MIT](https://github.com/QVPR/Patch-NetVLAD/blob/main/LICENSE)
- [QVPR/Patch-NetVLAD on GitHub](https://github.com/QVPR/Patch-NetVLAD)
- [README](https://github.com/QVPR/Patch-NetVLAD/blob/main/README.md)
- [Releases](https://github.com/QVPR/Patch-NetVLAD/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/qvpr-patch-netvlad
