easy-local-features
Unified, minimal wrappers around many local feature extractors and matchers (classical + learned).
⚠️ CRITICAL LICENSE DISCLAIMER
This repository aggregates wrappers around MANY third‑party local feature extractors and matchers. Each baseline/model keeps its OWN original license (BSD, MIT, Apache 2.0, GPLv3, Non‑Commercial, CC BY‑NC‑SA, custom research licenses, etc.). Your rights for a given baseline are governed only by that baseline’s upstream license. Some components here are non‑commercial only (e.g., SuperGlue, original SuperPoint, R2D2) or copyleft (e.g., DISK under GPLv3). Others are permissive (BSD/MIT/Apache 2.0). Before any research publication, internal deployment, redistribution, or commercial/production use, YOU MUST review and comply with every relevant upstream license, including attribution, notice reproduction, share‑alike, copyleft, and patent clauses.
The maintainers provide NO warranty, NO guarantee of license correctness, and accept NO liability for misuse. This notice and any summaries are not legal advice. If in doubt, consult qualified counsel.
See:
LICENSES.mdfor an overview and links to included full license texts. Built with DINOv3.
Installation
pip install easy-local-features
Installing from source
pip install -e .
Usage
Stable minimal API
getExtractor(name, conf)→ returns an extractor.to(device)→"cpu" | "cuda" | "mps".match(img0, img1)→{"mkpts0": (M,2), "mkpts1": (M,2), ...}- Descriptor-only methods additionally support
.addDetector(detector)
Detector-only methods
- Some methods only implement
detect(image) -> keypoints(no descriptors, no matching). UsegetDetector(name, conf)for those.
Example:
from easy_local_features import getDetector
from easy_local_features.utils import io
img = io.fromPath("tests/assets/megadepth0.jpg")
det = getDetector("rekd", {"num_keypoints": 1500}).to("cpu")
kps = det.detect(img) # [1, N, 2]
Discover available config keys (no model init)
In code:
from easy_local_features import describe
print(describe("superpoint"))
On the CLI:
easy-local-features --describe superpoint
Detect+Describe (one-liner matching)
from easy_local_features import getExtractor
from easy_local_features.utils import io, ops, vis
img0 = io.fromPath("tests/assets/megadepth0.jpg")
img1 = io.fromPath("tests/assets/megadepth1.jpg")
img0 = ops.resize_short_edge(img0, 320)[0]
img1 = ops.resize_short_edge(img1, 320)[0]
extractor = getExtractor("aliked", {"top_k": 2048}).to("cpu")
out = extractor.match(img0, img1)
vis.plot_pair(img0, img1, title="ALIKED")
vis.plot_matches(out["mkpts0"], out["mkpts1"])
vis.save("tests/results/aliked.png")
Descriptor-only (attach a detector)
from easy_local_features import getExtractor
from easy_local_features.feature.baseline_superpoint import SuperPoint_baseline
from easy_local_features.utils import io, ops
img0 = ops.resize_short_edge(io.fromPath("tests/assets/megadepth0.jpg"), 320)[0]
img1 = ops.resize_short_edge(io.fromPath("tests/assets/megadepth1.jpg"), 320)[0]
desc = getExtractor("sosnet").to("cpu")
det = SuperPoint_baseline({"top_k": 2048, "detection_threshold": 0.005}).to("cpu")
desc.addDetector(det)
out = desc.match(img0, img1)
End-to-end matchers
from easy_local_features import getExtractor
from easy_local_features.utils import io, ops
img0 = ops.resize_short_edge(io.fromPath("tests/assets/megadepth0.jpg"), 320)[0]
img1 = ops.resize_short_edge(io.fromPath("tests/assets/megadepth1.jpg"), 320)[0]
roma = getExtractor("romav2", {"top_k": 2000}).to("cpu")
out = roma.match(img0, img1)
CLI
easy-local-features --list
easy-local-features --list-detectors
Metadata
Release files for easy-local-features 0.8.29
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| easy_local_features-0.8.29.tar.gz | 13.8 MB | Without provenance | Details for easy_local_features-0.8.29.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| easy_local_features-0.8.29-py3-none-any.whl | Python 3 | none | any | Details for easy_local_features-0.8.29-py3-none-any.whl |
Total release size: 14.3 MB
Release files / easy_local_features-0.8.29.tar.gz
| Download URL | easy_local_features-0.8.29.tar.gz |
|---|---|
| Size | 13.8 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c1c63ccc36071086b455b45854b7036543c203d31f71f2603c9c80ed8560003f
|
|
BLAKE2b-256 checksum How to use checksums |
1f2f9cdb5473b93460eccc4ff12a7b57c867d9b40fb08781a40030a876358000
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.7
|
Release files / easy_local_features-0.8.29-py3-none-any.whl
| Download URL | easy_local_features-0.8.29-py3-none-any.whl |
|---|---|
| Size | 531.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3109e15cdd7f9fd3707153a1bb49f86e6abd4581fc31cfe782ca753c4af20e7b
|
|
BLAKE2b-256 checksum How to use checksums |
82d468b4377e4082e2c190e6525c75fc0b2bee899b12e9eda917a10e14d02a4a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.7
|
Security for easy-local-features 0.8.29
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.