LocalOptimizationDoneRight provides the local optimizers of the ACCV 2026 paper
Robust Local Optimization Done Right
(James Pritts and Kevin Köser): half-quadratic lifts, graduated non-convexity,
Student-t + uniform reweighting and PoseLib's truncated refiners, for the
refinement step of a RANSAC. Each one implements VisualGeometryToolkitCore's
local-optimization contract, so it composes with any scorer in
VisualGeometryToolkitEstimation's find_* estimators.
The package requires Julia 1.12 or later. The example below also loads the packages it composes with:
pkg> add LocalOptimizationDoneRight VisualGeometryToolkitEstimation VisualGeometryToolkitCore RANSACScoringDoneRight StaticArraysThe paper's recipe, Student-t + uniform selection and Welsch half-quadratic refinement at its cross-validated scale multiple, on a synthetic two-view scene:
using Random: MersenneTwister
using StaticArrays: SA
using VisualGeometryToolkitCore: CameraModel, Point2, WelschShape, estimate, motion, px
using VisualGeometryToolkitCore.Synthetic: pose_error, sample_twoview_scene
using VisualGeometryToolkitEstimation: EssentialProblem, find_essential
using RANSACScoringDoneRight: StudentTUniformScoring
using LocalOptimizationDoneRight: HQ, WELSCH_HQ_SCALE_MULTIPLE_ESSENTIAL
# Two 500 × 500 px views of one pinhole camera (focal length 600 px, principal
# point at the image centre): 200 matches with 1 px noise, then 100 mismatches
# drawn anywhere in the image.
rng = MersenneTwister(1)
R, t, _, _, matches = sample_twoview_scene(rng, 200; f = 600.0, c = 250.0)
noisy(u) = u + Point2(randn(rng), randn(rng))
anywhere() = Point2(500 * rand(rng), 500 * rand(rng))
cs = [[u₁ => noisy(u₂) for (u₁, u₂) in matches]; [anywhere() => anywhere() for _ in 1:100]]
camera = CameraModel(600.0px, SA[250.0px, 250.0px])
# Student-t + uniform selection, its outlier half-width 250 px (half the image),
# then Welsch half-quadratic refinement at its cross-validated multiple of the
# consensus set's scale.
result = find_essential(camera, camera, cs;
scoring = StudentTUniformScoring(EssentialProblem, 250.0),
local_optimization = HQ{WelschShape}(; scale_multiple = WELSCH_HQ_SCALE_MULTIPLE_ESSENTIAL),
rng = MersenneTwister(2))
n_inliers = count(result.inlier_mask) # the 200 matches, and the few mismatches that land on their epipolar lines
# Rotation and translation-direction errors in degrees, against the closest of
# the four motions (R, t) the estimated essential matrix factors into.
rotation_error, translation_error =
rad2deg.(minimum(pose_error(Rᵢ, tᵢ, R, t) for (Rᵢ, tᵢ) in motion(estimate(result))))The Overview introduces every strategy, its width modes and how it composes with a scorer.
- Home: the paper's results, installation and this example.
- Overview: the strategies, their width modes, scorers and TOML configuration.
- Reproducing the paper: every figure and table from its config and driver.
- Baselines: the classical LO arms (PoseLib, RansacLib).
- API Reference.
The package builds on VisualGeometryToolkitCore (the contracts and losses) and VisualGeometryToolkitEstimation (the problems and the RANSAC loop); its scorer companion is RANSACScoringDoneRight. The Visual Geometry Toolkit portal links them all.
@inproceedings{Pritts2026LocalOptimization,
title = {Robust Local Optimization Done Right},
author = {Pritts, James and K{\"o}ser, Kevin},
booktitle = {Asian Conference on Computer Vision (ACCV)},
year = {2026},
eprint = {2610.05743},
archivePrefix = {arXiv}
}If you use the paper project's RansacLib arms, also cite RansacLib and Lebeda, Matas and Chum (BMVC 2012); see Baselines.
MIT (see LICENSE). The vendored RansacLib keeps its BSD-3-Clause licence.