Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upside down models #527

Open
JaLnYn opened this issue Jan 4, 2025 · 3 comments
Open

Upside down models #527

JaLnYn opened this issue Jan 4, 2025 · 3 comments

Comments

@JaLnYn
Copy link

JaLnYn commented Jan 4, 2025

The output of my gaussian splats seems to be upside down. Here is my colmap script

I saw documentation saying that the data format is different so I've tried flipping the cameras.txt and points3d.txt over the x axis manually but the gaussians remain upside down. Anyone with a similar issue? Am I not converting correctly?


import os
import logging
import argparse
import shutil
from pathlib import Path

def run_command(cmd, error_msg="Command failed"):
   exit_code = os.system(cmd)
   if exit_code != 0:
       logging.error(f"{error_msg} with code {exit_code}. Exiting.")
       exit(exit_code)
   return exit_code

def process_dataset(dataset_name):
   script_dir = os.path.dirname(os.path.abspath(__file__))
   unprocessed_dir = os.path.join(script_dir, "data", "unprocessed", dataset_name)
   processed_dir = os.path.join(script_dir, "data", dataset_name)

   if not os.path.exists(unprocessed_dir):
       print(f"Error: Dataset directory {unprocessed_dir} does not exist")
       return False

   os.makedirs(os.path.join(processed_dir, "images"), exist_ok=True)
   os.makedirs(os.path.join(processed_dir, "sparse"), exist_ok=True)
   os.makedirs(os.path.join(processed_dir, "distorted/sparse"), exist_ok=True)

   print("Copying and renaming images...")
   files = sorted(os.listdir(unprocessed_dir))
   for idx, filename in enumerate(files, 1):
       if filename.lower().endswith(('.jpg', '.jpeg', '.png')):
           old_path = os.path.join(unprocessed_dir, filename)
           new_path = os.path.join(processed_dir, "images", f"frame_{idx:05d}.jpg")
           shutil.copy2(old_path, new_path)

   print("Running feature extraction...")
   cmd = f"colmap feature_extractor" \
         f" --database_path {processed_dir}/distorted/database.db" \
         f" --image_path {processed_dir}/images" \
         f" --ImageReader.single_camera 1" \
         f" --ImageReader.camera_model OPENCV"
   run_command(cmd)

   print("Running feature matching...")
   cmd = f"colmap exhaustive_matcher" \
         f" --database_path {processed_dir}/distorted/database.db"
   run_command(cmd)

   print("Running bundle adjustment...")
   cmd = f"colmap mapper" \
         f" --database_path {processed_dir}/distorted/database.db" \
         f" --image_path {processed_dir}/images" \
         f" --output_path {processed_dir}/distorted/sparse" \
         f" --Mapper.ba_refine_focal_length 1" \
         f" --Mapper.ba_refine_principal_point 1" \
         f" --Mapper.ba_refine_extra_params 1"
   run_command(cmd)

   print("Converting model to modify orientation...")
   cmd = f"colmap model_converter --input_path {processed_dir}/distorted/sparse/0 --output_path {processed_dir}/distorted/sparse/0 --output_type TXT"
   run_command(cmd)

   images_file = f"{processed_dir}/distorted/sparse/0/images.txt"
   with open(images_file, 'r') as f:
       lines = f.readlines()
       for i, line in enumerate(lines):
           if line[0].isdigit():
               parts = line.split()
               qw, qx, qy, qz = map(float, parts[1:5])
               qy, qz = -qy, -qz  # 180-degree rotation around X-axis
               parts[1:5] = map(str, [qw, qx, qy, qz])
               lines[i] = ' '.join(parts) + '\n'

   with open(images_file, 'w') as f:
       f.writelines(lines)

   cmd = f"colmap model_converter --input_path {processed_dir}/distorted/sparse/0 --output_path {processed_dir}/distorted/sparse/0 --output_type BIN"
   run_command(cmd)

   print("Running image undistortion...")
   cmd = f"colmap image_undistorter" \
         f" --image_path {processed_dir}/images" \
         f" --input_path {processed_dir}/distorted/sparse/0" \
         f" --output_path {processed_dir}" \
         f" --output_type COLMAP"
   run_command(cmd)

   print("Organizing sparse reconstruction...")
   sparse_dir = os.path.join(processed_dir, "sparse")
   sparse_0_dir = os.path.join(sparse_dir, "0")
   os.makedirs(sparse_0_dir, exist_ok=True)

   for file in os.listdir(sparse_dir):
       if file == '0':
           continue
       source_file = os.path.join(sparse_dir, file)
       destination_file = os.path.join(sparse_0_dir, file)
       if os.path.isfile(source_file):
           shutil.move(source_file, destination_file)

   print("Creating resized versions...")
   img_dir = os.path.join(processed_dir, "images")
   for scale in [2, 4, 8]:
       scaled_dir = os.path.join(processed_dir, f"images_{scale}")
       os.makedirs(scaled_dir, exist_ok=True)
       
       resize_percent = {2: "50%", 4: "25%", 8: "12.5%"}[scale]
       
       for img in sorted(os.listdir(img_dir)):
           if img.lower().endswith(('.jpg', '.jpeg', '.png')):
               src = os.path.join(img_dir, img)
               dst = os.path.join(scaled_dir, img)
               shutil.copy2(src, dst)
               cmd = f"magick mogrify -resize {resize_percent} {dst}"
               run_command(cmd)

   print("Processing complete!")
   return True

def main():
   parser = argparse.ArgumentParser(description="Process dataset through COLMAP pipeline")
   parser.add_argument("dataset_name", help="Name of the dataset")
   args = parser.parse_args()
   
   process_dataset(args.dataset_name)

if __name__ == "__main__":
   main()

image
@CaptainArmenia
Copy link

I am experiencing exactly the same issue:

image

This makes the visualization really uncomfortable, as it is impossible to flip it upside-down.

@JaLnYn
Copy link
Author

JaLnYn commented Jan 7, 2025

I think it's a visualizer issue? It works when I use nerfstudio splat with the same data.

@brentyi
Copy link
Collaborator

brentyi commented Jan 8, 2025

If you pip install --upgrade viser there should be a tool for reorienting the viewer. Relevant PR: nerfstudio-project/viser#361

The align_principle_axes function is a possible root cause of this problem: https://github.com/search?q=repo%3Anerfstudio-project%2Fgsplat%20align_principle_axes&type=code

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

No branches or pull requests

3 participants