Skip to content

evnchn/cylinder-sfm-python

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cylinder-SfM: Relative Pose from Cylinder Silhouettes (Python)

This repository contains a Python migration of the original MATLAB implementation for "Relative pose from cylinder silhouettes," a paper presented at ACCV 2024. The library provides tools to estimate the relative pose between two cameras by observing the silhouettes of two cylinders.

License: MIT

✅ Status: COMPLETE AND FUNCTIONAL

The full pipeline is now working end-to-end with real data!

  • Polynomial Solvers: Both solvers fully implemented with all coefficient expressions
  • Symbolic Coefficient Extraction: Implemented using SymPy for geometric constraint equations
  • Rectification: Camera and line rectification working correctly
  • Full Pipeline: Tested with real roller coaster data, produces valid reconstructions
  • 4 Solutions: Typical output includes multiple geometric configurations
  • Execution Time: ~2-3 seconds per reconstruction

Overview

The problem of relative pose estimation is a fundamental task in computer vision. This work introduces a novel method for solving this problem using the silhouettes of cylinders. By observing two cylinders from two different camera viewpoints, a set of geometric constraints can be formulated. These constraints lead to a system of polynomial equations that can be solved to recover the relative camera pose and the 3D structure of the cylinders.

This Python library implements the core algorithms described in the paper, including:

  • Data Rectification: Simplifies the problem by rotating the camera and line observations into a canonical coordinate system.
  • Polynomial Solvers: Minimal solvers for the resulting polynomial systems (✅ now fully implemented).
  • Geometric Utilities: A collection of helper functions for projective geometry, rotation conversions, and visualization.

Installation

To install the cylinder-sfm package, you can use pip from the root of this repository:

pip install .

For development, you can install in editable mode with the development dependencies:

pip install -e ".[dev,examples]"

API Documentation

The library is structured into several modules, each with a specific purpose. The main entry point is the relative_pose_conics function.

Core Components

  • cylinder_sfm.solver: Contains the main relative_pose_conics function.
  • cylinder_sfm.structures: Defines the data structures used, such as LineObservations, ReconstructionResult, and ScaleConstraint.
  • cylinder_sfm.rectification: Provides functions for data rectification.
  • cylinder_sfm.utils: Includes various geometric utility functions.
  • cylinder_sfm.solvers: Contains the low-level polynomial solvers (fully implemented).

Main Function

relative_pose_conics(lines, P1, scale_constraint, ...)

This is the primary function for estimating relative pose. It takes line observations, the pose of the first camera, and a scale constraint to produce a list of possible reconstruction results.

Parameters:

Parameter Type Description
lines LineObservations A data class containing the eight observed silhouette lines.
P1 np.ndarray The 3x4 camera matrix of the first camera.
scale_constraint ScaleConstraint The scale constraint, either p2p_dist (camera distance) or C1_r (radius).
flip_rectify bool Optional flag to handle rectification edge cases.
use_e3q3 bool Optional flag to use an external solver (not implemented).

Returns:

  • v1, v2: Vanishing points for the cylinder axes.
  • rotC1, rotC2: Rectification rotations for each camera.
  • results: A list of ReconstructionResult objects, each containing a possible solution.

Data Structures

  • LineObservations: A dataclass to hold the eight line observations from the two cylinders in the two cameras.
  • ReconstructionResult: A dataclass that stores a single solution, including the pose of the second camera (P2), cylinder positions (T1_t, T2_t), radii (r1, r2), and rotations (T1_R, T2_R).
  • ScaleConstraint: A dataclass to specify the scale constraint, which is necessary to resolve the scale ambiguity of the reconstruction.

Usage Example

Here is a basic example of how to use the library to solve for relative pose.

import numpy as np
from cylinder_sfm import (
    relative_pose_conics,
    LineObservations,
    ScaleConstraint,
    pflat
)

# 1. Define line observations (replace with actual data)
# l_ijk: camera i, cylinder j, line k
lines = LineObservations(
    l_111=pflat(np.array([0.5, 0.2, 1.0]))[0].flatten(),
    l_112=pflat(np.array([-0.5, 0.2, 1.0]))[0].flatten(),
    l_121=pflat(np.array([0.8, -0.1, 1.0]))[0].flatten(),
    l_122=pflat(np.array([-0.8, -0.1, 1.0]))[0].flatten(),
    l_211=pflat(np.array([0.6, 0.3, 1.0]))[0].flatten(),
    l_212=pflat(np.array([-0.6, 0.3, 1.0]))[0].flatten(),
    l_221=pflat(np.array([0.9, -0.2, 1.0]))[0].flatten(),
    l_222=pflat(np.array([-0.9, -0.2, 1.0]))[0].flatten(),
)

# 2. Define camera 1 pose (identity)
P1 = np.hstack([np.eye(3), np.zeros((3, 1))])

# 3. Define scale constraint (e.g., distance between cameras is 5 units)
scale = ScaleConstraint(value=5.0, type='p2p_dist')

# 4. Solve for relative pose
v1, v2, rotC1, rotC2, results = relative_pose_conics(lines, P1, scale)

# 5. Process results
if results:
    print(f"Found {len(results)} solutions.")
    best_result = results[0]
    
    print("\n--- Best Solution ---")
    print(f"Camera 2 Pose (P2):\n{best_result.P2}")
    print(f"Cylinder 1 Radius: {best_result.r1:.4f}")
    print(f"Cylinder 2 Radius: {best_result.r2:.4f}")
    print(f"Cylinder 1 Center: {best_result.T1_t}")
    print(f"Cylinder 2 Center: {best_result.T2_t}")
else:
    print("No solutions found.")

Testing

A comprehensive test script is included to validate the solvers:

python test_solvers.py

This will test:

  • Solver 1 (camera translation in x-z plane)
  • Solver 2 (remaining variables: y, cylinder 2 position and radius)
  • Full pipeline integration

Implementation Details

Polynomial Solvers

The core of this method relies on solving systems of polynomial equations. The solvers use Gröbner basis methods and action matrix eigenvalue decomposition.

Solver 1: Camera Translation

  • Input: Quaternion for P2 rotation + 3 line parameters
  • Output: 2-4 solutions for camera translation (x, z)
  • Method: 4×4 action matrix with quotient ring basis [1, x, y, y²]

Solver 2: Remaining Variables

  • Input: 23 polynomial coefficients
  • Output: Up to 8 solutions for (y, x_T2, z_T2)
  • Method: 8×8 action matrix with quotient ring basis [1, x, x·z, y, y·z, z, z², z³]

All coefficient expressions have been fully translated from the original MATLAB implementation, preserving numerical accuracy.

References

[1] Wadenbäck, M., & Heyden, A. (2024). Relative pose from cylinder silhouettes. In Proceedings of the Asian Conference on Computer Vision (ACCV 2024). https://link.springer.com/chapter/10.1007/978-981-96-0969-7_15

License

This project is licensed under the MIT License. See the LICENSE file for details.

Acknowledgments

About

Python migration of cylinder-SfM: Relative pose estimation from cylinder silhouettes

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published