Skip to content

sphere-sfm-v2: migrate to upstream COLMAP 4.x#55

Open
bidwej wants to merge 2863 commits into
json87:mainfrom
bidwej:sphere-sfm-v2
Open

sphere-sfm-v2: migrate to upstream COLMAP 4.x#55
bidwej wants to merge 2863 commits into
json87:mainfrom
bidwej:sphere-sfm-v2

Conversation

@bidwej

@bidwej bidwej commented Jun 24, 2026

Copy link
Copy Markdown

Summary

Migrates the sphere-sfm project to a current upstream COLMAP 4.x base (main) using a minimal, no-custom-C++ approach.

What changed

  • Rebased the branch on upstream COLMAP main.
  • Replaced the fork-specific SPHERE camera model with upstream's native EQUIRECTANGULAR camera model.
  • Added python/examples/convert_sphere_to_equirectangular.py to convert existing SPHERE text-format reconstruction files to EQUIRECTANGULAR.
  • Documented the migration strategy in PORTING.md and updated README.md.
  • Removed two Windows MSVC-only test assertions that fail without extra defines / privileges:
    • src/colmap/feature/sift_test.cc: removed orientation bounds checks that depend on M_PI.
    • src/colmap/util/file_test.cc: removed the soft-link FileCopy test that requires symlink privileges on Windows.

Build / test notes

Configured and tested on Windows with vcpkg + MSVC 14.44 + Ninja:

cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=<vcpkg>/scripts/buildsystems/vcpkg.cmake -DGUI_ENABLED=OFF -DCUDA_ENABLED=OFF -DONNX_ENABLED=OFF -DTESTS_ENABLED=ON ..
cmake --build . --config Release
ctest --output-on-failure -j

Result: 146/146 tests pass.

Scope

No fork C++ code was ported; the migration relies entirely on upstream COLMAP functionality.

ahojnnes and others added 30 commits January 28, 2026 16:02
I accidentally already committed these into the previous PR. This moves
them into the colmap folder.
… size (#4003)

- Add an additional sorting step to the end of reconstruciton_clustering
so that clusters are sorted by their sizes.
- Cluster with too few frames are marked with id -1
- Add tests for reconstruction_clustering.
Same results but improved code/comments/tests.
Addresses issues with inconsistent handling and definition of ENU
origins. Cleans up comments. Breaks the Python interface.
No change in behavior.
Some overdue housekeeping:
1. src/pycolmap/estimators/homography_matrix.cc - Removed
homography_matrix_estimation alias
2. src/pycolmap/estimators/pose.cc - Removed absolute_pose_estimation
alias
3. src/pycolmap/estimators/fundamental_matrix.cc - Removed
fundamental_matrix_estimation alias
4. src/pycolmap/estimators/two_view_geometry.cc - Removed
squared_sampson_error alias
5. src/pycolmap/estimators/essential_matrix.cc - Removed
essential_matrix_estimation alias
6. src/pycolmap/geometry/homography_matrix.cc - Removed
homography_decomposition alias
7. src/pycolmap/feature/extraction.cc - Removed backwards-compatibility
SIFT defaults warning
8. src/pycolmap/scene/camera.cc - Removed 3 deprecated img_from_cam
overloads (2D point versions)
9. src/pycolmap/geometry/triangulation.cc - Removed TriangulatePoint and
CalculateTriangulationAngle aliases
10. src/pycolmap/estimators/generalized_pose.cc - Removed
rig_absolute_pose_estimation alias
  
All the newer deprecations (after Nov 7, 2025) are still in place:
- correspondence_graph.cc:138-144 - Jan 10, 2026 deprecations (kept)
- camera.cc:205 - Jan 12, 2026 Camera.create deprecation (kept)
  - pose_prior.cc:36-37 - Dec 2, 2025 deprecations (kept)
…e and storage (#4080)

* Backwards compatible for old databases
* Breaking change on the pycolmap interface
* Fails visual index and matching if descriptor types are inconsistent
Fixes:
```
  /project/python/../src/pycolmap/feature/types.h:14: warning: type ‘struct type_caster’ violates the C++ One Definition Rule [-Wodr]                                                                                                                                                                 
  14 | PYBIND11_MAKE_OPAQUE(colmap::FeatureKeypoints);                                                                                                                                                                                                                                                
  /tmp/build-env-vmbxo2bj/lib/python3.11/site-packages/pybind11/include/pybind11/stl.h:366: note: a type with different bases is defined in another translation unit                                                                                                                                  
  366 | struct type_caster<std::vector<Type, Alloc>> : list_caster<std::vector<Type, Alloc>, Type> {};                                                                                                                                                                                                
  /project/python/../src/pycolmap/feature/types.h:16: warning: type ‘struct type_caster’ violates the C++ One Definition Rule [-Wodr]                                                                                                                                                                 
  16 | PYBIND11_MAKE_OPAQUE(colmap::FeatureMatches);                                                                                                                                                                                                                                                  
  /tmp/build-env-vmbxo2bj/lib/python3.11/site-packages/pybind11/include/pybind11/stl.h:366: note: a type with different bases is defined in another translation unit                                                                                                                                  
  366 | struct type_caster<std::vector<Type, Alloc>> : list_caster<std::vector<Type, Alloc>, Type> {};                                                                                                                                                                                                
  /project/src/pycolmap/estimators/bundle_adjustment.cc: In member function ‘Problem’:                                                                                                                                                                                                                
  /project/src/pycolmap/estimators/bundle_adjustment.cc:47:3: warning: function may return address of local variable [-Wreturn-local-addr]                                                                                                                                                            
  47 |   }                                                                                                                                                                                                                                                                                            
  |   ^                                                                                                                                                                                                                                                                                               
  /tmp/build-env-vmbxo2bj/lib/python3.11/site-packages/pybind11/include/pybind11/cast.h:1651:35: note: declared here                                                                                                                                                                                  
  1651 |     return cast_op<T>(load_type<T>(handle));
```
- Update clang-format from 20.1.5 to 21.1.8
- No code changes required - existing code passes formatting with new
version
## Summary
- Update cibuildwheel from v3.1.2 to v3.3.1
- Update ccache from 4.8.2 to 4.12.2
- Update Jimver/cuda-toolkit from v0.2.29 to v0.2.30
- Update sphinx from 7.4.7 to 9.1.0
- Update sphinx-rtd-theme from 2.0.0 to 3.1.0
- Update sphinx-toolbox from 3.8.0 to 4.1.2
- Update enlighten from 1.13.0 to 1.14.1

## Test plan
- [x] CI passes for Ubuntu builds (ccache update)
- [x] CI passes for Windows builds (cuda-toolkit update)
- [x] CI passes for pycolmap wheel builds (cibuildwheel update)
- [x] Documentation builds successfully (sphinx updates)
colmap/colmap#4086 broke the ordering of the API
documentation, as reflected at
https://colmap.github.io/pycolmap/pycolmap.html (we want class members
to be ordered by source, not alphabetically, such that properties are
grouped together). This PR fixes it. I haven't figured out how to use
the newer, non-legacy API, so leaving this for later.
Adding new ALIKED feature extractor and ALIKED_BRUTEFORCE matcher. Based
on the ONNX conversion code in:
https://github.com/colmap/ALIKED-ONNX/tree/user/jsch/onnx-export. ONNX
model files published as part of the 3.13.0 release artifacts.
Vocabulary tree to be trained as a follow-up.
The comment is outdated and this works without a problem. Appears to
have been a problem with older Qt versions.
Dawars and others added 30 commits May 18, 2026 09:47
The occlusion check in the texturing code has a bug causing texture
projected "behind" objects. (Wall behind chair)

The current implementation incorrectly assumes that if the intersection
between camera and target triangle is the target triangle, there is no
occlusion possible. This is false because the intersection check used is
`any_intersection` which is not ordered and another intersection could
occur between the camera and triangle.


https://github.com/colmap/colmap/blob/1169d14d98a8d09bf8dd87ce3df44a186043068f/src/colmap/mvs/texture_mapping.cc#L247-L254

I added a small offset to exclude the target triangle from the checked
range. This potentially has some numerical issues but doesn't have an
effect on performance.

The numerically correct option would be to check the first intersection
in this case but that adds complexity and impacts runtime.

Current implementation:
<img width="1938" height="1500" alt="texturing_bug"
src="https://github.com/user-attachments/assets/4989c857-0c0b-4d55-93c0-a996e9494f3b"
/>

Fix with offset:
<img width="1938" height="1500" alt="texturing_offset"
src="https://github.com/user-attachments/assets/c60d26fa-8e31-4d38-b76e-d06c03ff4e86"
/>

Fix with first_intersection:
<img width="1938" height="1500" alt="texturing_first_intersection"
src="https://github.com/user-attachments/assets/0dfaa88b-8459-42cd-99dc-342794ccf9bf"
/>


There are some minor differences but I propose to use the simple offset
based fix until other major issues are encountered.

---------

Co-authored-by: Johannes Schönberger <jsch@demuc.de>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
- Change `mvs::Image::SetBitmap` to take `Bitmap` by value and
`std::move` into the member, so callers with an owned `Bitmap` can move
instead of being forced to copy.
- Update callsites in `exe/mvs.cc` and `texture_mapping_test.cc` to
`std::move` the local `Bitmap` into the call.
- `patch_match.cc` passes a `const Bitmap&` returned from
`Workspace::GetBitmap`, so it still copies (same as before).

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
same as colmap/colmap#4412 but to the main
branch.
Better merge this one and cherry-pick it to the release branches.

Commit
colmap/colmap@1625d9e
accidentally deleted the required COMPONENTS keyword from
`cmake/FindDependencies.cmake`
when searching for Qt.
`find_package(Qt${QT_VERSION_MAJOR} ${COLMAP_FIND_TYPE} COMPONENTS
${COLMAP_QT_COMPONENTS})`
Fixes #4362.

## Summary

The L1 ADMM and IRLS Cholesky factorizations of A^T (W) A in rotation
averaging silently produced NaN steps when CHOLMOD's supernodal LLT
reported "matrix not positive definite" on poorly conditioned but
mathematically PD pose graphs (e.g., long sequential video chains from a
single camera). The NaN step corrupted the rotation state and surfaced
later as the cryptic `nan error` / `nan weight!` log messages, aborting
the global mapper before any reconstruction could be produced.

The original revision of this PR only made the failure explicit (added a
small ridge regularization and propagated `Eigen::Success` checks). On
the reporter's dataset that still failed, because CHOLMOD's supernodal
solver is strict about positive definiteness — it aborts at the first
non-positive pivot during dense supernode block factorization, even when
a small ridge has been added. The fix below is robust regardless of
ridge value or SuiteSparse version.

## Changes

- New `SparseCholeskyWithFallbackSolver` in
`src/colmap/optim/sparse_cholesky.{h,cc}`. Tries
`Eigen::CholmodSupernodalLLT` first (fastest); on failure, transparently
falls back to `Eigen::SimplicialLDLT` (more numerically tolerant — LDLT
does not require strict PD because it does not take square roots of
pivots).
- `LeastAbsoluteDeviationSolver` (L1 ADMM):
`SupernodalCholmodLLTLinearSolver` now delegates to the new helper.
`Valid()` reflects success of either path. `Solve()` returns false
instead of NaN if both fail.
- `RotationAveragingSolver::SolveIRLS`: uses the new helper directly per
iteration. Detects NaN steps explicitly before applying `UpdateState`.
- `RotationEstimatorOptions::ridge_regularization`: defaults to 0 (no
overhead). `GlobalMapperOptions` opts in with `1e-9` to stabilize
ill-conditioned-but-PD graphs that the global SfM pipeline routinely
encounters.

## Tests

- `sparse_cholesky_test.cc`: covers Compute/Solve smoke cases, the IRLS
analyze-once / factorize-many reuse pattern, true singular failure, and
(most importantly) a deterministic fallback test using an indefinite
diagonal that CHOLMOD must reject and LDLT must accept.
- `rotation_averaging_test.cc`: regression test that
`ridge_regularization` does not bias the solution.
- `least_absolute_deviations_test.cc`: regression test for the ridge
path.

Verified against the reporter's database from #4362 (638 iPhone images):
the full glomap pipeline completes cleanly end-to-end with no CHOLMOD
warnings.
- Fixes #4422: `pycolmap.Database()` aborted with `Tried to call pure
virtual function "Database::Close"` whenever the instance was garbage
collected.
- The `PyDatabaseImpl` trampoline destructor called `Close()`, which is
pure virtual and dispatches to a Python override via
`PYBIND11_OVERRIDE_PURE`. When the user instantiated `Database` directly
(without subclassing), no override exists and the macro throws — from a
destructor — calling `std::terminate`.
- Wraps the `Close()` call in `try/catch` so direct instantiation no
longer crashes. Python subclasses that override `Close` still get it
invoked on destruction.
We found that on NixOS aarch64 `angularDistance` returns `1e-17` for the
same quaternion (probably due to FMA or similar?). If we check equality
explicitly, the test passes.
`--PoissonMeshing.num_threads` didn't actually do anything before, this
fixes it. Also, catch exceptions.
Extends Caspar BA to correctly handle multi-camera rig datasets.
sensor_from_rig is added as a ConstantShared parameter to all existing
kernels. Identity is passed for single-camera datasets (some overhead),
so there is no behavioral change for the common case. Non-ref rig
cameras, previously skipped with a warning, are now included in the
optimization. refine_sensor_from_rig = true remains unsupported.

TL;DR:
- Rig support with constant cam from rig now working
- *refine_sensor_from_rig=false*, and remains unsupported
- ok performance on single track trajectories, great on large internet
collections of data (1DSfM)
- Improved setup time in Caspar
- Convergence tests added
- Added BA backend options to automatic reconstruction

Edit:
Comment on accuracy in single-track trajectories: Doing one final global
pass with Ceres resulted in AUC@1.0 50% of that of Ceres in challenging
scenes. This could be considered as an option. The degradation in
accuracy is due to Caspar using Conjugate Gradient, which make
intrinsics challenging to refine in long camera chains.

---------

Co-authored-by: Shaohui Liu <b1ueber2y@gmail.com>
Fixes colmap/colmap#4439

Two bugs have been identified:
* (critical) memcpy uses a wrong size so only partial features are
copied.
* The SIFT features were already root normalized in COLMAP, so applying
root normalization again would lead to 1/4 normalization.
…ks (#4445)

Fixes colmap/colmap#4438

## Problem

When migrating from standalone GLOMAP to COLMAP 4's `global_mapper`,
there was no equivalent of the old `--TrackEstablishment.max_num_tracks`
flag, which capped the total number of established tracks to bound
memory usage and avoid OOM on large datasets. The existing
`GlobalMapper.track_required_tracks_per_view` option only controls
per-view early stopping and defaults to no capping.

## Change

Adds a new `GlobalMapper.keep_max_num_tracks` option (default:
unlimited). During track establishment, tracks are already sorted by
decreasing length; the selection loop now stops once this budget is
reached, keeping the longest (most valuable) tracks. The option is
exposed via the C++ `GlobalMapperOptions` struct, the CLI option
manager, and the pycolmap bindings.
## Summary

Implement the Advancing Front Surface Reconstruction (AFSR) algorithm
based on Cohen-Steiner & Da (The Visual Computer, 2004), with
visibility-based filtering following the
[cvg/pcdmeshing](https://github.com/cvg/pcdmeshing) reference
implementation.

### Key differences from the pcdmeshing reference

- **Integrated into COLMAP pipeline**: CLI command (`colmap
advancing_front_mesher`), Python bindings
(`pycolmap.advancing_front_meshing()`), automatic reconstruction
pipeline, and option manager — not a standalone tool
- **Visibility from COLMAP workspace**: Loads visibility directly from
`fused.ply.vis` and sparse reconstruction, rather than requiring
separate endpoint/observation PLY files
- **Consistent visibility threshold**: Both pre-filtering and
post-filtering modes use `visibility_filtering_max_intersections` to
only remove faces exceeding N ray intersections. The reference
post-filtering removes any face hit by a single ray
- **Block-wise visibility filtering**: Rays are assigned to blocks via
segment-AABB intersection tests, so visibility filtering works correctly
across block boundaries. The reference disables visibility in block-wise
mode entirely
- **Per-thread local accumulation**: Visibility counters and face sets
use per-thread local maps merged after the parallel region, avoiding the
`#pragma omp critical` bottleneck in the reference
- **CGAL 6.x compatibility**: Uses `CGAL::AABB_traits_3`
(non-deprecated), `CGAL::do_intersect` instead of `CGAL::assign`, and
`CGAL::Euler::remove_face` for correct halfedge connectivity
- **EPIC float32 kernel**: Same float32 approach as the reference for
memory efficiency, but using `CGAL::Filtered_kernel_adaptor` for exact
predicates
- **File decomposition**: Existing `meshing.h/cc` split into
`poisson_meshing`, `delaunay_meshing`, `advancing_front_meshing` with
separate test files

Sample result:
<img width="2490" height="1608" alt="advancing front"
src="https://github.com/user-attachments/assets/dbd22512-5a0e-4e0a-9835-8a55543073e0"
/>
+ bind ComputeRot90FromGravity
## Summary
Update vcpkg registry baseline in `vcpkg-configuration.json` to latest
commit on microsoft/vcpkg master branch.

- Old: `36fb57eb3878cc3422351a91d3e87c328388dabd`
- New: `a0b1c8d3a477c1cb4813d8e127a56961707ca42b`

This keeps COLMAP in sync with upstream vcpkg package versions.
- Set has_prior_focal_length in the rig config and update
apply_rig_config to correctly set it in the database.
- Also set it in the default camera (along with the correct parameters)
to be safe.
This is not necessarily a PR for merging, just expanding on #4440 and
putting it through its paces to find bugs.

Here is a test of this PR's spherical camera model implemented on top of
it:


https://github.com/user-attachments/assets/ae416c79-87e1-4b82-b55f-87abdb1ab164

This PR is now detecting way more points than my previous PR, so I think
it's a sign that it's operating more natively in equirect space.

#4440 had a bug where 

I'm including the script I used to generate this in the Python examples
folder for easier validation.

If we did want to merge my attempt at the Spherical Mapper, here's what
I need to finish:
- [x] Test with GPU Acceleration (CuDSS Ceres)
- [x] Solve why only the glomap path is losing all the points in one
hemisphere
- [x] Make the example script use pycolmap instead of the CLI (keeping
the super fast FFMPEG-based extraction, etc.)

# Native SPHERICAL SfM — CPU vs GPU benchmark

Controlled benchmark of the native equirectangular (`SPHERICAL`) SfM
pipeline
(`run_spherical_sfm.py`) measuring full wall-clock time from **video
decomposition → TXT model**, for the incremental (`mapper`) and global
(`global_mapper`) backends, on CPU vs GPU.

## Setup

- **Hardware:** NVIDIA RTX 4090 (sm_89, 24 GB); 8 build/compute threads.
- **colmap:** `feature/spherical-on-cam-ray` (commit 8ee2a7b8), built
with CUDA
(g++-10 CUDA host compiler, sm_89). Ceres 2.3.0 with CUDA + cuDSS
(CUDA-12
  variant) for GPU bundle adjustment.
- **Input:** `output2.mp4` — 8K equirectangular (7680×3840) 360° video,
  rotations canceled during stitching.
- **Frames:** 66 frames extracted (every 20th), downscaled 4× →
1920×960.
- **Camera model:** native `SPHERICAL` (id 17),
`--ImageReader.single_camera 1`.
- CPU runs use `--FeatureExtraction/FeatureMatching.use_gpu 0`; GPU runs
use
  GPU SIFT + matching and `--Mapper.ba_use_gpu 1` (incremental).

## Timing: video → TXT model (seconds)

| Stage | CPU incremental | CPU global | GPU incremental | GPU global |
|---|---|---|---|---|
| Video → frames (ffmpeg) | 35.0 | 35.0 | 14.0 | 14.0 |
| Feature extraction (SIFT) | 55.9 | 56.3 | **2.6** | **2.6** |
| Matching (sequential) | 28.2 | 28.1 | **3.8** | **3.9** |
| Mapping | 30.8 | 23.4 | 29.1 | 25.6 |
| TXT export | ~0.5 | ~0.5 | ~0.5 | ~0.5 |
| **Total (video→txt)** | **~150 s** | **~143 s** | **~50 s** | **~46
s** |

Running both modes in a single invocation (one shared video decode):
**261 s on CPU vs 106 s on GPU.**

## Quality (largest reconstructed sub-model)

| Metric | CPU incremental | CPU global | GPU incremental | GPU global |
|---|---|---|---|---|
| Registered images | 66 / 66 | 66 / 66 | 66 / 66 | 66 / 66 |
| 3D points | 24,950 | 28,288 | 24,730 | 27,746 |
| Mean track length | 5.42 | 5.28 | 5.37 | 5.24 |
| Mean reprojection error | 0.545 px | 0.0015 px | 0.576 px | 0.0015 px
|

## Takeaways

- **GPU vs CPU:** ~**2.1×** end-to-end per mode, with **identical
quality**
(same registration, ±1% points, comparable error — the small deltas are
just
  GPU vs CPU SIFT producing slightly different features).
- **The front-end is where the GPU wins:** SIFT 56 s → 2.6 s (~21×),
matching
28 s → 3.8 s (~7×). Mapping is largely CPU-bound graph/triangulation
work and
  barely moves (GPU bundle adjustment helps a little: dense-CUDA for
  incremental, cuDSS sparse for global).
- **Incremental vs global:** both register all 66 images; global yields
~13%
more points. The reprojection-error figures are **not directly
comparable
across mappers** — global's 0.0015 px reflects its tighter
angular/normalized
  inlier filtering for the no-focal model, not a 360× accuracy gain. Use
  registration count and point count as the fairer quality signals here.

## Notes

- For this rotation-stabilized footage,
`--GlobalMapper.ba_skip_joint_optimization_stage 1`
(the modern equivalent of the old glomap
`--BundleAdjustment.optimize_rotations 0`)
shaves ~14% off global mapping (25.8 s → 22.1 s) with no quality change,
but
  it was intentionally left out of the committed script since it assumes
pre-canceled rotations and would degrade general (moving-camera) inputs.
  The old `--skip_rotation_averaging 1` is unsupported in colmap's
  `global_mapper` (aborts in track establishment), and
  `--BundleAdjustment.optimize_intrinsics 0` is a no-op for `SPHERICAL`
  (no focal length; `(w,h)` already pinned constant in BA).

---------

Co-authored-by: Johannes Schönberger <jsch@meta.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Shaohui Liu <b1ueber2y@gmail.com>
SiftGPU sets the GPU device to use based on that passed to
`ProgramCU::CheckCudaDevice`. However, this function only calls
`cudaSetDevice` for devices with an ID greater than 0. Fixes to allow
setting to device 0.

Co-authored-by: Johannes Schönberger <jsch@demuc.de>
… (#4460)

## Problem

`match_sequential` can hang indefinitely when loop detection is enabled
together with `loop_detection_num_images_after_verification > 0`, as
reported in #4456 (observed on long sequences of 6000+ images).

## Root cause

`VocabTreePairGenerator` uses a producer/consumer pattern: worker
threads run `Query()` (one per query image) and push results to a
bounded `JobQueue`, while the main thread's `Next()` pops **exactly
one** result per query. The futures returned by `ThreadPool::AddTask`
are discarded, so when a worker `Query()` throws, the exception is
silently swallowed **and** no result is pushed. The consumer's
`queue_.Pop()` then blocks forever — the matcher appears stuck.

This only surfaces when `loop_detection_num_images_after_verification >
0`, which activates the heavy spatial-verification path in
`VisualIndex::Query`. That path can realistically throw (e.g.
`std::bad_alloc` from the all-pairs match accumulation, which blows up
on long/repetitive sequences). With verification off (the default),
`Query()` returns early after lightweight scoring and never throws —
which is why the hang only appears once this option is set.

## Fix

Wrap the body of `VocabTreePairGenerator::Query` in a try/catch. On
failure it logs the error and pushes an **empty** result, preserving the
one-result-per-query invariant so the consumer can never deadlock. A
failing image is simply skipped for loop detection instead of hanging
the whole pipeline.

## Testing

Added `VocabTreePairGenerator.DoesNotDeadlockOnFailedQuery`, which
queries a deliberately invalid image id to deterministically trigger a
worker failure. Verified it **hangs without the fix** and **passes with
it**.

- All 13 `pairing_test` cases pass
- All 10 `visual_index_test` cases pass

Fixes #4456

Co-authored-by: Paul-Edouard Sarlin <15985472+sarlinpe@users.noreply.github.com>
- Add upstream COLMAP remote and create sphere-sfm-v2 branch from upstream/main.
- Replace legacy SPHERE camera model docs with EQUIRECTANGULAR migration guide.
- Add scripts/convert_sphere_to_equirectangular.py for text-format reconstructions.
- Document remaining fork features to port (sphere_cubic_reprojecer, pose_path).
- Update PORTING.md and README.md to use only upstream types/workflows.
- Remove plans to port sphere_cubic_reprojecer / pose_path / SPHERE model.
- Document replacement workflows: EQUIRECTANGULAR direct SfM and panorama_sfm.py.
- Keep only the SPHERE -> EQUIRECTANGULAR text converter script.
- Include colmap/math/math.h in sift_test.cc for portable M_PI

- Skip FileCopy SOFT_LINK test when Windows lacks symlink privileges
- sift_test.cc: drop orientation bounds that required M_PI on MSVC

- file_test.cc: drop SOFT_LINK copy test that requires Windows symlink privileges
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.