Downloads · 30 days
180
98% of all-time downloads
rkreft/upal
upal is a keypoint detection model from rkreft. Use it for the keypoint detection task on the model card, and read the license before you ship it in a product. It is set up for upal. The card lists the license as apache-2.0.
Joint keypoint + line local feature extractor. One forward pass predicts sub-pixel keypoints with confidence scores, 128-D L2-normalised descriptors, a dense keypoint/junction heatmap and a dense line distance field.…
Downloads · 30 days
180
98% of all-time downloads
All-time downloads
184
Public
Parameters
790K
4.5 MB on disk
Likes
0
Public
Click a slice to open those files.
.safetensors3.2 MB · 70%
From the Hugging Face model README
Joint keypoint + line local feature extractor. One forward pass predicts sub-pixel keypoints with confidence scores, 128-D L2-normalised descriptors, a dense keypoint/junction heatmap and a dense line distance field. Line segments are obtained by seeding a modified LSD detector with the learned keypoints and filtering its proposals with the distance field.

Red: learned keypoints · green: line segments supported by the learned distance field · coloured links: mutual-nearest descriptor matches.
pip install upal # network + point-seeded line detector
import cv2
import torch
from upal import UPAL, mutual_nearest_neighbors, match_lines_from_endpoints
model = UPAL.from_pretrained("rkreft/upal").to("cuda" if torch.cuda.is_available() else "cpu")
def read(path):
image = cv2.cvtColor(cv2.imread(path), cv2.COLOR_BGR2RGB)
return torch.from_numpy(image).permute(2, 0, 1).float() / 255.0
feats0, feats1 = model.extract(read("img0.png")), model.extract(read("img1.png"))
feats0["keypoints"] # N x 2 pixel (x, y)
feats0["descriptors"] # N x 128, L2-normalised
feats0["keypoint_scores"] # N
feats0["keypoint_dispersity"] # N, spread of the score peak (lower = sharper)
feats0["keypoint_heatmap"] # H x W
feats0["line_distance_field"] # H x W, distance to the nearest line in pixels
feats0["lines"] # L x 2 x 2 endpoints
# Point matching: mutual nearest neighbours on descriptors.
point_matches = mutual_nearest_neighbors(feats0["descriptors"], feats1["descriptors"]) # M x 2 indices
# Line matching: describe both endpoints of each segment, then solve a one-to-one assignment.
desc0 = model.describe_lines(read("img0.png"), feats0["lines"]) # L0 x 2 x 128
desc1 = model.describe_lines(read("img1.png"), feats1["lines"]) # L1 x 2 x 128
line_matches, scores = match_lines_from_endpoints(desc0, desc1) # K x 2 indices, K scores (NumPy)
To skip line post-processing, call model.extract(image, lines=False); lines is then empty
(0 x 2 x 2) and everything else is unchanged.
extract(image, lines=True, max_lines=200, min_line_length=25.0, max_line_distance=2.0)
takes a C x H x W tensor in [0, 1] (RGB or grayscale); the number of keypoints is set by
UPAL.from_pretrained("rkreft/upal", max_num_keypoints=2048). Images are padded to a
multiple of 32 internally and outputs are returned in input-image coordinates.
[0, 5] px).points-lsd) filtered by the mean distance-field value along the
segment; mutual-nearest-neighbour point matching; endpoint-descriptor line matching with a
maximum-weight assignment.model.safetensors, 0.79M parameters, 3.2 MB) and its configuration (config.json).| File | Content |
|---|---|
model.safetensors | inference weights |
config.json | max_num_keypoints, nms_radius, line_neighborhood |
assets/boat_demo.png | demo visualisation |
Apache-2.0 (weights and code). Line detection uses points-lsd,
whose LSD core is AGPL-3.0-or-later.
@misc{costa2026unifiedefficientpointlinelocal,
title={Unified and Efficient Point-Line Local Features},
author={François Costa and Raphael Kreft and Eckhard Goedeke and Felix Möller and Hardik Shah and Ramanathan Rajaraman and Shaohui Liu and Rémi Pautrat and Marc Pollefeys},
year={2026},
eprint={2608.19894},
archivePrefix={arXiv},
primaryClass={cs.CV},
url={https://arxiv.org/abs/2608.19894},
}
Parts of the code reuse ALIKED and glue-factory. We thank the authors of SuperPoint, ALIKED, DaD and DeepLSD for releasing the pre-trained models used as teachers.