SphereSfM icon indicating copy to clipboard operation
SphereSfM copied to clipboard

Results differ significantly from provided examples – mapping fails to initialize with custom and provided datasets

Open JohannesKrueger opened this issue 9 months ago • 1 comments

First of all, thank you for this great research work and for sharing the SphereSfM code publicly.

I installed the latest release of the software (SphereSfM-2024-12-14) and tested it using both the provided datasets and several custom datasets captured using spherical cameras. However, I was not able to achieve reconstruction results anywhere close to the quality shown in the example outputs.

In all cases — including the official datasets — the reconstruction fails to proceed beyond the mapping stage with the following log output:

      Residuals : 39972
     Parameters : 14681
     Iterations : 12
           Time : 0.268353 [s]
   Initial cost : 0.763392 [px]
     Final cost : 0.762463 [px]
    Termination : Convergence
  
    => Completed observations: 4
    => Merged observations: 0
    => Filtered observations: 1
    => Changed observations: 0.000250
    => Filtered images: 0
  
  Finding good initial image pair
    
    => No good initial image pair found.
  
  Elapsed time: 0.785 [minutes]

I also developed a simple processing pipeline according to your instructions (including ERP inputs, camera models, and all reconstruction stages), and verified everything multiple times. Still, mapping consistently fails at the initial pair selection phase.

Could you please help clarify:

Whether there might be a parameter tweak or preprocessing step required that's not explicitly mentioned in the README?

Could there be an issue with the recent release that prevents correct initialization of the reconstruction?

Would you be willing to review a minimal reproducible example from my side or review my pipeline for any mistakes?

import os
import logging
import subprocess
from argparse import ArgumentParser

parser = ArgumentParser("SphereSfM COLMAP pipeline")
parser.add_argument("--no_gpu", action="store_true")
parser.add_argument("--skip_matching", action="store_true")
parser.add_argument("--source_path", "-s", required=True, type=str)
parser.add_argument("--colmap_executable", default="colmap", type=str)
parser.add_argument("--camera_model", default="SPHERE", type=str)
parser.add_argument("--camera_params", default="1,6144,3072", type=str)  # Default from repo
parser.add_argument("--camera_mask", default="C:/Users/Admin/insta360_test/output/input/mask/camera_mask.png", type=str)
parser.add_argument("--pose_file", default="C:/Users/Admin/insta360_test/output/input/POS.txt", type=str)

args = parser.parse_args()

use_gpu = 0 if args.no_gpu else 1
colmap = f'"{args.colmap_executable}"'

input_path = os.path.join(args.source_path, "images")
db_path = os.path.join(args.source_path, "colmap", "database.db")
sparse_path = os.path.join(args.source_path, "colmap", "sparse")
cubic_path = os.path.join(args.source_path, "colmap", "sparse-cubic")

os.makedirs(os.path.dirname(db_path), exist_ok=True)
os.makedirs(sparse_path, exist_ok=True)

def run(cmd, step):
    print(f"\n🚀 {step}:\n{cmd}\n")
    result = subprocess.run(cmd, shell=True)
    if result.returncode != 0:
        logging.error(f"{step} failed with exit code {result.returncode}")
        exit(result.returncode)

if not args.skip_matching:
    # Step 1 - Feature Extraction
    cmd = f"""{colmap} feature_extractor \
--database_path {db_path} \
--image_path {input_path} \
--ImageReader.camera_model {args.camera_model} \
--ImageReader.camera_params "{args.camera_params}" \
--ImageReader.single_camera 1 \
--ImageReader.camera_mask_path "{args.camera_mask}"""

    run(cmd, "Step 1 - Feature Extraction")

    # STEP 2 - feature matching
    cmd = f"""{colmap} spatial_matcher \
--database_path "{db_path}" \
--SiftMatching.use_gpu {use_gpu} \
--SiftMatching.max_error 4 \
--SiftMatching.min_num_inliers 50 \
--SpatialMatching.is_gps 0 \
--SpatialMatching.max_distance 50"""

    run(cmd, "Step 2 - Feature Matching")

# Step 3 - Sparse Reconstruction
cmd = f"""{colmap} mapper \
--database_path {db_path} \
--image_path {input_path} \
--output_path {sparse_path} \
--Mapper.ba_refine_focal_length 0 \
--Mapper.ba_refine_principal_point 0 \
--Mapper.ba_refine_extra_params 0 \
--Mapper.sphere_camera 1"""

run(cmd, "Step 3 - Sparse Mapping")

# ✅ Step 4 - Cubic Conversion
cmd = f"""{colmap} sphere_cubic_reprojecer \
--image_path "{input_path}" \
--input_path "{sparse_path}/0" \
--output_path "{cubic_path}" """
run(cmd, "Step 4 - Cubic Reprojection")

print("\n✅ SphereSfM COLMAP pipeline complete.")

Thank you again for the contribution. Looking forward to your insights.

JohannesKrueger avatar Apr 23 '25 15:04 JohannesKrueger

parser.add_argument("--camera_params", default="1,6144,3072", type=str) # Default from repo

you should modify the camera params according to your datasets.

json87 avatar May 09 '25 00:05 json87

@json87 Hi, I also got an awful result.

Image

Here are the commands that I used, which follow the provided example completely. The only difference thing is the mask area, which I used, which is the area without the vehicle.

Image
./colmap database_creator --database_path ./database.db

./colmap feature_extractor \  
--database_path ./database.db \
--image_path ./images \
--ImageReader.camera_model SPHERE \
--ImageReader.camera_params "1,7040,3520" \
--ImageReader.single_camera 1 \
--ImageReader.camera_mask_path ./Urban_street_mask.png \
--ImageReader.pose_path ./POS.txt

./colmap spatial_matcher \ 
--database_path ./database.db \
--SiftMatching.max_error 4 \
--SiftMatching.min_num_inliers 50 \
--SpatialMatching.is_gps 0 --SpatialMatching.max_distance 50

./colmap mapper \
--database_path ./database.db \
--image_path ./images \
--output_path ./sparse \
--Mapper.ba_refine_focal_length 0 \
--Mapper.ba_refine_principal_point 0 \
--Mapper.ba_refine_extra_params 0 \
--Mapper.sphere_camera 1

Matt-V50 avatar Jul 04 '25 13:07 Matt-V50

if the camera parameters are OK, you should pay attention to the overlap degree of images.

json87 avatar Jul 04 '25 23:07 json87

If the camera parameters are OK, you should pay attention to the overlap degree of images.

Sorry, all images are from your urban street dataset. I noticed that there are only a part of the images in the POS.txt. Will it be the problem?

Matt-V50 avatar Jul 06 '25 02:07 Matt-V50

If the camera parameters are OK, you should pay attention to the overlap degree of images.

Sorry, all images are from your urban street dataset. I noticed that there are only a part of the images in the POS.txt. Will it be the problem?

You can finetune the feature matching results, such as combing spatial matching with sequential maching.

json87 avatar Sep 18 '25 00:09 json87