Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Keypoints

Created by Codex.

Hold an image’s two-dimensional feature coordinates for track generation.

Open In Colab

Mathematical idea

Image ii stores feature coordinates uik=(xik,yik)u_{ik}=(x_{ik},y_{ik}). A pairwise match (k,)(k,\ell) between images ii and jj asserts

uikuj,u_{ik}\sim u_{j\ell},

and track generation takes the transitive closure of these equivalence relations across images. A valid structure-from-motion track contains at most one feature index from each image.

import gtsam
import numpy as np

from gtsam import symbol_shorthand

C = symbol_shorthand.C
K = symbol_shorthand.K
P = symbol_shorthand.P
S = symbol_shorthand.S
X = symbol_shorthand.X

Coordinate convention

gtsam.gtsfm.Keypoints stores an N x 2 coordinate matrix. x increases rightward, y increases downward, and the image origin is the upper-left corner. The C++ struct can also carry optional scales and responses; the current Python binding exposes coordinates.

KeypointsVector and MatchIndicesMap are wrapper support types. In Python, use a normal list of Keypoints and a dictionary from image-index pairs to N x 2 integer correspondence arrays.

keypoints = [
    gtsam.gtsfm.Keypoints(np.array([[10.0, 20.0], [30.0, 40.0]])),
    gtsam.gtsfm.Keypoints(np.array([[11.0, 20.5], [31.0, 40.5]])),
]
matches = {gtsam.IndexPair(0, 1): np.array([[0, 0], [1, 1]], dtype=np.int32)}

tracks = gtsam.gtsfm.tracksFromPairwiseMatches(matches, keypoints)
print("track count:", len(tracks))
print("first track cameras:", tracks[0].indexVector())
track count: 2
first track cameras: [0 1]

Data-quality rule

A valid track should contain at most one feature from each camera. Conflicting pairwise matches can merge two detections from one image into a component; inspect SfmTrack2d.hasUniqueCameras() before using generated tracks downstream.