Skip to content

Conversation

@zalo
Copy link

@zalo zalo commented Jan 15, 2026

Summary

Add support for equirectangular (360° panoramic) camera model to enable global SfM reconstruction with 360° cameras like Insta360, Ricoh Theta, etc.

Changes

  1. Camera model support (glomap/scene/types_sfm.h)

    • Add EQUIRECTANGULAR to CameraModelId enum (ID 10, matching COLMAP)
    • Register in camera model switch macros
  2. Intrinsic handling (glomap/scene/types_sfm.cc)

    • Add case for EQUIRECTANGULAR in Camera::GetK() (returns identity - no focal length)
    • Add case in InitializeCamera() for EQUIRECTANGULAR model
  3. CMake configuration (cmake/FindDependencies.cmake)

    • Configure to use local COLMAP and PoseLib builds with equirectangular support
    • Uses FetchContent to pull from feature branches

Dependencies

This PR depends on equirectangular support being merged in:

Test plan

  • Build passes with local COLMAP/PoseLib
  • Successfully reconstructed 330-image 360° panoramic dataset
  • Output: 26,384 3D points, 1.09px mean reprojection error

🤖 Generated with Claude Code

zalo and others added 2 commits January 14, 2026 11:39
- Configure FetchContent to use local COLMAP/PoseLib with equirectangular
- Add EQUIRECTANGULAR handling in view_graph_calibration.cc
- Support spherical camera intrinsics in camera.h
- Enables global SfM pipeline for 360° panoramic images

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Resolved conflict in cmake/FindDependencies.cmake to keep local
COLMAP/PoseLib paths for EQUIRECTANGULAR support.
Copilot AI review requested due to automatic review settings January 15, 2026 13:40
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for the EQUIRECTANGULAR camera model to enable global SfM reconstruction with 360° panoramic cameras. The implementation detects spherical camera models and provides compatibility shims for methods that assume perspective projection, while excluding them from focal length calibration.

Changes:

  • Added IsSpherical() method to detect equirectangular/spherical camera models and adapted Focal(), PrincipalPoint(), and GetK() to return compatibility values for spherical cameras
  • Modified view graph calibration to skip spherical cameras during focal length estimation
  • Updated CMake configuration to use local COLMAP and PoseLib builds with equirectangular support

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
glomap/scene/camera.h Adds spherical camera detection and compatibility methods for cameras without traditional intrinsics
glomap/estimators/view_graph_calibration.cc Excludes spherical cameras from focal length calibration optimization
cmake/FindDependencies.cmake Configures build to use local dependency versions with equirectangular support
Comments suppressed due to low confidence (1)

glomap/estimators/view_graph_calibration.cc:185

  • Potential index mismatch bug. The FilterImagePairs method iterates through all valid image pairs and accesses residuals by counter, but AddImagePair skips spherical camera pairs without adding residuals to the problem. This means counter will advance for spherical pairs in FilterImagePairs, but no corresponding residuals exist, causing an out-of-bounds access or misaligned residual reading. Need to skip spherical camera pairs in FilterImagePairs similar to AddImagePair.
  for (auto& [image_pair_id, image_pair] : view_graph.image_pairs) {
    if (image_pair.config != colmap::TwoViewGeometry::CALIBRATED &&
        image_pair.config != colmap::TwoViewGeometry::UNCALIBRATED)
      continue;
    if (image_pair.is_valid == false) continue;

    const Eigen::Vector2d error(residuals[counter], residuals[counter + 1]);

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


# Use local PoseLib with EQUIRECTANGULAR support
FetchContent_Declare(PoseLib
SOURCE_DIR /home/selstad/Desktop/colmap_workspace/PoseLib
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded absolute path to a user's home directory will break builds on other systems. Use FetchContent with GIT_REPOSITORY and GIT_TAG to pull from the actual feature branches mentioned in the PR description, or provide a CMake option to allow users to override the path.

Copilot uses AI. Check for mistakes.

# Use local COLMAP with EQUIRECTANGULAR support
FetchContent_Declare(COLMAP
SOURCE_DIR /home/selstad/Desktop/colmap_workspace/colmap
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded absolute path to a user's home directory will break builds on other systems. Use FetchContent with GIT_REPOSITORY and GIT_TAG to pull from the actual feature branches mentioned in the PR description, or provide a CMake option to allow users to override the path.

Copilot uses AI. Check for mistakes.
// Spherical cameras don't have a meaningful focal length
// Return a dummy value based on image dimensions for compatibility
if (IsSpherical()) {
return static_cast<double>(std::max(width, height)) / M_PI;
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

M_PI is not a standard C++ constant and may not be defined on all platforms. The codebase defines HALF_PI and TWO_PI in glomap/types.h but not M_PI. Consider using std::numbers::pi (C++20) if available, or define M_PI in types.h, or use the literal value 3.141592653589793238462643383279502884L consistent with other constants in the codebase.

Suggested change
return static_cast<double>(std::max(width, height)) / M_PI;
return static_cast<double>(std::max(width, height)) /
3.141592653589793238462643383279502884L;

Copilot uses AI. Check for mistakes.
Comment on lines +60 to +62
Eigen::Matrix3d K = Eigen::Matrix3d::Identity();
K(0, 2) = width / 2.0;
K(1, 2) = height / 2.0;
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Division by 2.0 could potentially be problematic if width or height are 0, though this is unlikely for valid images. The comment on line 58 states this matrix 'should not be used', but returning a matrix that appears valid could lead to subtle bugs if code incorrectly uses it. Consider adding a LOG(WARNING) when this function is called for spherical cameras to make misuse more visible during development.

Copilot uses AI. Check for mistakes.
bool Camera::IsSpherical() const {
// Check by model name since model_id may not be defined for EQUIRECTANGULAR
// in older COLMAP versions
return ModelName() == "EQUIRECTANGULAR" || ModelName() == "SPHERICAL";
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String comparisons for camera model detection are fragile and case-sensitive. If COLMAP uses different casing or model names change, this will silently fail. Consider also checking model_id if available (with appropriate fallback handling) for more robust detection, or document the exact model names expected from COLMAP.

Copilot uses AI. Check for mistakes.
- Use GIT_REPOSITORY in FetchContent instead of hardcoded local paths
- Fix M_PI usage with explicit constant value
- Add LOG(WARNING) for GetK() on spherical cameras
- Use model_id check with fallback to ModelName() for IsSpherical()
- Update DatabaseCache::Create to use new Options struct API
- Handle std::optional types for TwoViewGeometry fields (F, H, cam2_from_cam1)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@ichsan2895
Copy link

ichsan2895 commented Jan 17, 2026

This is a great feature.

Recently, 360 videos into 3DGS is more popular. Instead of creates cubemap/planar of equirectangular images, it can directly train the equirectangular images with Lichtfeld-Studio/others that has GUT feature.

Only agisoft metashape that can handle equirectangular poses. Hopefully glomap can handle it too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants