### Install Dependencies and Build STDLoc Source: https://context7.com/zju3dv/stdloc/llms.txt Clone the repository, set up a conda environment, install PyTorch with CUDA support, and install Python dependencies and submodules. Specific instructions are provided for Cambridge Landmarks dataset which requires Mask2Former. ```bash git clone --recursive https://github.com/zju3dv/STDLoc.git cd STDLoc conda create -n stdloc python=3.8 -y conda activate stdloc pip install torch==2.4.1 torchvision==0.19.1 torchaudio==2.4.1 \ --index-url https://download.pytorch.org/whl/cu124 pip install -r requirements.txt pip install submodules/simple-knn pip install submodules/gsplat cd submodules/Mask2Former pip install -r requirements.txt python -m pip install 'git+https://github.com/facebookresearch/detectron2.git' cd mask2former/modeling/pixel_decoder/ops sh make.sh cd ../../../.. wget https://dl.fbaipublicfiles.com/maskformer/maskformer/coco/panoptic/maskformer2_swin_large_IN21k_384_bs16_100ep/model_final_f07440.pkl cd ../.. ``` -------------------------------- ### Install Python Packages for STDLoc Source: https://github.com/zju3dv/stdloc/blob/main/README.md Set up the Python environment by creating a conda environment and installing the required packages, including PyTorch with CUDA support and project-specific submodules. ```bash conda create -n stdloc python=3.8 -y pip install torch==2.4.1 torchvision==0.19.1 torchaudio==2.4.1 --index-url https://download.pytorch.org/whl/cu124 pip install -r requirements.txt # install submodules pip install submodules/simple-knn pip install submodules/gsplat ``` -------------------------------- ### Clone STDLoc Repository Source: https://github.com/zju3dv/stdloc/blob/main/README.md Clone the repository to get started. Ensure to use the --recursive flag to include submodules. ```bash git clone --recursive https://github.com/zju3dv/STDLoc.git ``` -------------------------------- ### Download 7-Scenes Full Reconstructions Source: https://github.com/zju3dv/stdloc/blob/main/README.md Installs gdown and downloads the reference models for the 7-Scenes dataset. It then moves the sparse reconstruction data to the appropriate scene directories. ```bash pip install gdown gdown 1ATijcGCgK84NKB4Mho4_T-P7x8LSL80m -O $dataset/7scenes_reference_models.zip unzip $dataset/7scenes_reference_models.zip -d $dataset # move sfm_gt to each dataset for scene in chess fire heads office pumpkin redkitchen stairs; \ do mkdir -p $dataset/$scene/sparse && cp -r $dataset/7scenes_reference_models/$scene/sfm_gt $dataset/$scene/sparse/0 ; done ``` -------------------------------- ### Install Mask2Former Dependencies Source: https://github.com/zju3dv/stdloc/blob/main/README.md Installs Mask2Former and its dependencies, including detectron2, and compiles necessary C++/CUDA operations. This is a prerequisite for processing Cambridge Landmarks data. ```bash cd submodules/Mask2Former pip install -r requirements.txt python -m pip install 'git+https://github.com/facebookresearch/detectron2.git' cd mask2former/modeling/pixel_decoder/ops sh make.sh cd ../../../.. # download model wget https://dl.fbaipublicfiles.com/maskformer/maskformer2/coco/panoptic/maskformer2_swin_large_IN21k_384_bs16_100ep/model_final_f07440.pkl cd ../.. ``` -------------------------------- ### Train Models for 7-Scenes and Cambridge Landmarks Source: https://github.com/zju3dv/stdloc/blob/main/README.md Scripts to initiate the training process for both the 7-Scenes and Cambridge Landmarks datasets. Ensure you are in the correct directory before running. ```bash # For 7-Scenes: bash scripts/train_7scenes.sh # For Cambridge Landmarks bash scripts/train_cambridge.sh ``` -------------------------------- ### Evaluate STDLoc Models via Command Line Source: https://context7.com/zju3dv/stdloc/llms.txt Entry point for evaluating trained STDLoc models on datasets like 7-Scenes or Cambridge Landmarks. Specify the model path, configuration, iteration, and an output prefix. Results are saved as JSON files. ```bash # Evaluate on 7-Scenes (chess scene) python stdloc.py \ -m map_7scenes/chess \ --cfg configs/stdloc_7scenes.yaml \ --iteration 30000 \ --prefix chess_eval # Evaluate all 7-Scenes scenes bash scripts/evaluate_7scenes.sh # Evaluate Cambridge Landmarks bash scripts/evaluate_cambridge.sh # Output files (saved to results/--/): # summary.json — aggregate metrics: # { # "sparse": { # "median_ae": 0.15, # degrees # "median_te": 0.43, # cm # "recall_5cm_5d": 0.987, # "recall_2cm_2d": 0.743 # }, # "dense": { # "median_ae": 0.13, # "median_te": 0.43, # "recall_5cm_5d": 0.994, # "recall_2cm_2d": 0.812 # } # } # results.json — per-image poses and errors ``` -------------------------------- ### Evaluate Models for 7-Scenes and Cambridge Landmarks Source: https://github.com/zju3dv/stdloc/blob/main/README.md Scripts to run the evaluation process for both the 7-Scenes and Cambridge Landmarks datasets using the downloaded pretrained models. ```bash # For 7-Scenes: bash scripts/evaluate_7scenes.sh # For Cambridge Landmarks bash scripts/evaluate_cambridge.sh ``` -------------------------------- ### Download Pretrained Models for Evaluation Source: https://github.com/zju3dv/stdloc/blob/main/README.md Downloads pretrained models for both 7-Scenes and Cambridge Landmarks datasets using gdown, then unzips them. These models are used for reproducing experimental results. ```bash gdown 1gxmmpYD-XjYT01cu0flfNHf0CuJDIXsh gdown 1EbKx9NY2cgtIxkQQ7Spjpl90PG68GKgu unzip map_7scenes.zip unzip map_cambridge.zip ``` -------------------------------- ### Build Argument Namespace Directly for Training Source: https://context7.com/zju3dv/stdloc/llms.txt This snippet shows how to bypass the CLI and directly construct argument namespaces for the training function. It defines configurations for both dataset and optimization parameters. ```python from argparse import Namespace dataset = Namespace( source_path="/data/7scenes/chess", model_path="map_7scenes/chess", feature_type="sp", gaussian_type="3dgs", sh_degree=3, images="", white_background=True, norm_before_render=True, longest_edge=640, data_device="cuda", eval=True, speedup=False, ) opt = Namespace( iterations=30_000, position_lr_init=0.00016, position_lr_final=0.0000016, position_lr_delay_mult=0.01, position_lr_max_steps=30_000, feature_lr=0.0025, opacity_lr=0.05, scaling_lr=0.005, rotation_lr=0.001, loc_feature_lr=0.001, percent_dense=0.01, lambda_dssim=0.2, densification_interval=100, opacity_reset_interval=3000, densify_from_iter=500, densify_until_iter=15_000, densify_grad_threshold=0.0002, lambda_dist=0.0, lambda_normal=0.05, opacity_cull=0.05, ) from train import training training( dataset=dataset, opt=opt, testing_iterations=[7000, 30000], saving_iterations=[7000, 30000], checkpoint=None, # or path to .pth checkpoint to resume train_detector=True, test_detector_iterations=[10_000, 20_000, 30_000], save_detector_iterations=[10_000, 20_000, 30_000], detector_folder="detector", landmark_num=16384, landmark_k=32, ) ``` -------------------------------- ### STDLoc Class for Full Localization Pipeline Source: https://context7.com/zju3dv/stdloc/llms.txt Initializes and runs the STDLoc localization pipeline. Takes a GaussianModel and configuration, then localizes a query image to estimate camera pose. ```python from stdloc import STDLoc from scene import Scene from scene.gaussian_model import GaussianModel from arguments import ModelParams, get_combined_args from utils.pose_utils import cal_pose_error import yaml, torch # Load the Feature Gaussian scene gaussians = GaussianModel(sh_degree=3) # ... (scene loading via Scene class, see stdloc.py __main__ block) # Load configuration config = yaml.load(open("configs/stdloc_7scenes.yaml"), Loader=yaml.FullLoader) config["dense"]["norm_before_render"] = True config["feature_type"] = "sp" config["longest_edge"] = 640 config["model_path"] = "map_7scenes/chess" # Initialize localizer stdloc = STDLoc(gaussians, config) # Load a query image [3, H, W] in [0, 1] range query_image = torch.rand(3, 480, 640).cuda() fovx = 1.047 # horizontal field of view in radians fovy = 0.785 # vertical field of view in radians # Run full localization pipeline result = stdloc.localize(query_image, fovx, fovy) # Sparse stage result sparse_pose = result["sparse"]["pose_w2c"] # np.ndarray [4, 4] sparse_inliers = result["sparse"]["inliers"] # int # Dense refinement results (up to 4 iterations) final_dense = result["dense"][-1] dense_pose = final_dense["pose_w2c"] # np.ndarray [4, 4] dense_inliers = final_dense["inliers"] # int print(f"Sparse inliers: {sparse_inliers}, Dense inliers: {dense_inliers}") # Sparse inliers: 312, Dense inliers: 847 # Evaluate against ground truth gt_w2c = ... # np.ndarray [4, 4] ae, te = cal_pose_error(dense_pose, gt_w2c) print(f"Angular error: {ae:.3f} deg, Translation error: {te:.3f} cm") # Angular error: 0.13 deg, Translation error: 0.43 cm ``` -------------------------------- ### Download 7-Scenes Dataset Images Source: https://github.com/zju3dv/stdloc/blob/main/README.md Use this script to download and extract images for the 7-Scenes dataset. Ensure the dataset directory is set correctly. ```bash export dataset=datasets/7scenes for scene in chess fire heads office pumpkin redkitchen stairs; \ do wget http://download.microsoft.com/download/2/8/5/28564B23-0828-408F-8631-23B1EFF1DAC8/$scene.zip -P $dataset \ && unzip $dataset/$scene.zip -d $dataset && unzip $dataset/$scene/'*.zip' -d $dataset/$scene; done ``` -------------------------------- ### Download Cambridge Landmarks Dataset Images Source: https://github.com/zju3dv/stdloc/blob/main/README.md Downloads and extracts images for the Cambridge Landmarks dataset. Ensure the dataset directory is set correctly. ```bash export dataset=datasets/cambridge export scenes=( "KingsCollege" "OldHospital" "StMarysChurch" "ShopFacade" "GreatCourt" ) export IDs=( "251342" "251340" "251294" "251336" "251291" ) for i in "${!scenes[@]}"; do wget https://www.repository.cam.ac.uk/bitstream/handle/1810/${IDs[i]}/${scenes[i]}.zip -P $dataset \ && unzip $dataset/${scenes[i]}.zip -d $dataset ; done ``` -------------------------------- ### Core Feature Gaussian Training Loop Initialization Source: https://context7.com/zju3dv/stdloc/llms.txt Initializes the core Feature Gaussian training loop by setting up necessary components like scene representation, feature extraction, and rendering. Requires PyTorch and custom STDLoc modules. ```python from arguments import ModelParams, OptimizationParams from gaussian_renderer import render_gsplat from scene import Scene from scene.gaussian_model import GaussianModel from encoders.feature_extractor import FeatureExtractor from train_detector import training_detector from utils.general_utils import safe_state, seed_everything import torch seed_everything(2025) ``` -------------------------------- ### stdloc.py — Localization Evaluation Entry Point Source: https://context7.com/zju3dv/stdloc/llms.txt Run inference on all test images of a trained scene and compute recall metrics at multiple thresholds. Results are saved as JSON. ```APIDOC ## stdloc.py — Localization Evaluation Entry Point ### Description Run inference on all test images of a trained scene and compute recall metrics at multiple thresholds. Results are saved as JSON. ### Usage ```bash # Evaluate on 7-Scenes (chess scene) python stdloc.py \ -m map_7scenes/chess \ --cfg configs/stdloc_7scenes.yaml \ --iteration 30000 \ --prefix chess_eval # Evaluate all 7-Scenes scenes bash scripts/evaluate_7scenes.sh # Evaluate Cambridge Landmarks bash scripts/evaluate_cambridge.sh ``` ### Output Files Results are saved to `results/--/` and include: - **summary.json** — aggregate metrics: ```json { "sparse": { "median_ae": 0.15, # degrees "median_te": 0.43, # cm "recall_5cm_5d": 0.987, "recall_2cm_2d": 0.743 }, "dense": { "median_ae": 0.13, "median_te": 0.43, "recall_5cm_5d": 0.994, "recall_2cm_2d": 0.812 } } ``` - **results.json** — per-image poses and errors ``` -------------------------------- ### Train Feature Gaussian Scene (Cambridge Landmarks) Source: https://context7.com/zju3dv/stdloc/llms.txt Command to train the Feature Gaussian scene representation and detector on the Cambridge Landmarks dataset, including undistorted images and enabling sky/object masking. ```bash python train.py \ -s datasets/cambridge/KingsCollege/ \ -m map_cambridge/KingsCollege \ --iterations 30000 \ --data_device cpu \ -f sp \ -g 3dgs \ --train_detector \ --images images_undistorted ``` -------------------------------- ### Train Scene-Specific Detector with training_detector() Source: https://context7.com/zju3dv/stdloc/llms.txt Trains a KpDetector CNN for scene-specific keypoint detection. It uses binary cross-entropy loss against projected Gaussian landmarks and includes LR scheduling and gradient accumulation. Saves trained weights and landmark indices. ```python from train_detector import training_detector from scene.gaussian_model import GaussianModel from scene import Scene # After Feature Gaussian training is complete: training_detector( gaussians=gaussians, # trained GaussianModel scene=scene, # Scene object with train/test cameras masks=masks, # dict of per-image masks (or None) testing_iterations=[10000, 20000, 30000], saving_iterations=[10000, 20000, 30000], tb_writer=tb_writer, # TensorBoard writer (or None) train_iteration=30000, detector_folder="detector", landmark_num=16384, # number of landmark Gaussians to sample landmark_k=32, # KNN neighborhood size for sampling ) # Saves: # /detector/sampled_idx.pkl — landmark Gaussian indices # /detector/30000_detector.pth — trained detector weights ``` -------------------------------- ### Train Feature Gaussian Scene (7-Scenes) Source: https://context7.com/zju3dv/stdloc/llms.txt Command to train the Feature Gaussian scene representation and the scene-specific keypoint detector on a single 7-Scenes dataset. Specifies SuperPoint features, 3DGS backend, and training the detector. ```bash python train.py \ -s datasets/7scenes/chess/ \ -m map_7scenes/chess \ --iterations 30000 \ --data_device cpu \ -f sp \ -g 3dgs \ --train_detector \ --images "" \ --test_iterations 7000 30000 \ --save_iterations 7000 30000 \ --landmark_num 16384 \ --landmark_k 32 \ --detector_folder detector ``` -------------------------------- ### Landmark Gaussian Sampling with matching_oriented_sample() Source: https://context7.com/zju3dv/stdloc/llms.txt Selects a subset of Gaussians as landmarks based on discriminative power and spatial coverage. It computes average cosine similarity scores and uses KNN-diversified sampling. Requires a scene, Gaussian model, and feature extractor. ```python from train_detector import matching_oriented_sample from encoders.feature_extractor import FeatureExtractor feature_extractor = FeatureExtractor("sp").cuda().eval() render_visible_masks = {} # cache for visibility masks sampled_idx, score_avg, score_num = matching_oriented_sample( scene=scene, gaussians=gaussians, feature_extractor=feature_extractor, render_visible_masks=render_visible_masks, masks=None, # optional per-image masks for outdoor scenes num=16384, # total landmark count to select k=32, # KNN neighborhood for diversity sampling ) print(f"Selected {sampled_idx.shape[0]} landmark Gaussians") # Selected 16384 landmark Gaussians print(f"Mean match score: {score_avg.mean().item():.4f}") # Mean match score: 0.7231 import pickle pickle.dump(sampled_idx, open("map_7scenes/chess/detector/sampled_idx.pkl", "wb")) ``` -------------------------------- ### Preprocess Cambridge Landmarks Data Source: https://github.com/zju3dv/stdloc/blob/main/README.md Executes a script to preprocess the Cambridge Landmarks dataset. This script is located in the 'scripts' directory. ```bash bash scripts/dataset_preprocess.sh ``` -------------------------------- ### Render Gaussian Scene from Arbitrary Pose Source: https://context7.com/zju3dv/stdloc/llms.txt Renders a Gaussian scene using a world-to-camera pose matrix and field of view parameters. Supports rendering RGB, depth, and feature maps. Useful for localization stages. ```python from gaussian_renderer import render_from_pose_gsplat import torch import math # pose_w2c: [4, 4] world-to-camera transform (float32, CUDA) pose_w2c = torch.eye(4, device="cuda", dtype=torch.float32) # identity pose example fovx = 1.047 # radians (~60 degrees) fovy = 0.785 # radians (~45 degrees) W, H = 640, 480 render_pkg = render_from_pose_gsplat( pc=gaussians, pose=pose_w2c, fovx=fovx, fovy=fovy, width=W, height=H, render_mode="RGB+ED", # renders RGB + depth norm_feat_bf_render=True, rasterize_mode="antialiased", ) color = render_pkg["render"] # [3, H, W] depth = render_pkg["depth"] # [1, H, W] — metric depth feature_map = render_pkg["feature_map"] # [C, H, W] print("Depth range:", depth.min().item(), "-", depth.max().item(), "m") # Depth range: 0.23 - 4.87 m ``` -------------------------------- ### PnP Pose Estimation with solve_pose() Source: https://context7.com/zju3dv/stdloc/llms.txt Estimates camera pose from 2D-3D point correspondences using PnP algorithms (poselib or OpenCV). It returns the world-to-camera matrix and inlier indices. Requires 2D pixel coordinates and corresponding 3D world points. ```python from utils.pose_utils import solve_pose, cal_pose_error import numpy as np # 2D keypoints in image space [N, 2] (pixel coordinates, 0-indexed + 0.5 offset) p2d = np.array([[320.5, 240.5], [150.5, 100.5], [500.5, 380.5], [80.5, 200.5]]) # Corresponding 3D world points [N, 3] p3d = np.array([[1.2, 0.5, 3.1], [0.3, -0.2, 2.4], [1.8, 0.1, 4.2], [0.5, 0.8, 2.9]]) ``` -------------------------------- ### render_gsplat Source: https://context7.com/zju3dv/stdloc/llms.txt Renders RGB images and feature maps from a GaussianModel given a camera viewpoint, supporting both 3DGS and 2DGS backends. ```APIDOC ## render_gsplat() ### Description Renders both the RGB image and the feature map from a `GaussianModel` given a camera viewpoint. Automatically handles 3DGS vs 2DGS backends. Returns a dictionary with the rendered color image, feature map, and auxiliary rasterization metadata. ### Usage ```python from gaussian_renderer import render_gsplat from scene.gaussian_model import GaussianModel import torch # Assumes gaussians and viewpoint_cam are already loaded via Scene # viewpoint_cam: Camera object from scene.getTrainCameras() ``` ``` -------------------------------- ### Train All 7-Scenes Scenes Source: https://context7.com/zju3dv/stdloc/llms.txt Executes a shell script to train the Feature Gaussian scene representation and detector for all scenes within the 7-Scenes dataset. ```bash bash scripts/train_7scenes.sh ``` -------------------------------- ### Lift 2D to 3D Points with STDLoc Source: https://context7.com/zju3dv/stdloc/llms.txt Back-projects 2D pixel coordinates to 3D world space using a depth map and camera parameters. Requires 2D points, intrinsic matrix, camera-to-world transform, and the depth map. Useful for generating 3D correspondences for PnP solvers. ```python from stdloc import lift_2d_to_3d import torch import numpy as np # 2D rendered match coordinates [N, 2] (x, y pixel coords) rendered_p2d = torch.tensor([[320., 240.], [150., 100.], [500., 380.]], device="cuda") # Intrinsic matrix [3, 3] K = torch.tensor([[525., 0., 320.], [0., 525., 240.], [0., 0., 1.]], device="cuda") # Camera-to-world transform [4, 4] pose_c2w = torch.eye(4, device="cuda") # Rendered depth map [H, W] depth_map = torch.ones(480, 640, device="cuda") * 2.5 # uniform 2.5m depth points3d = lift_2d_to_3d( points2d=rendered_p2d, # [N, 2] intrinsic=K, # [3, 3] Twc=pose_c2w, # [4, 4] camera-to-world depth_map=depth_map, # [H, W] ) # Returns: [N, 3] world-space 3D points print("3D points shape:", points3d.shape) # 3D points shape: torch.Size([3, 3]) print("3D points:\n", points3d.cpu().numpy()) # [[ 1.527, 1.145, 2.5 ], # [ 0.594, 0.214, 2.5 ], # [ 2.358, 1.905, 2.5 ]] ``` -------------------------------- ### training_detector() Source: https://context7.com/zju3dv/stdloc/llms.txt Trains a Keypoint Detector (KpDetector) CNN for a specified number of iterations using binary cross-entropy loss. It utilizes ground-truth keypoint maps derived from landmark projections and includes learning rate scheduling and gradient accumulation. ```APIDOC ## training_detector() ### Description Trains the `KpDetector` CNN for 30,000 iterations using binary cross-entropy against ground-truth keypoint maps derived from matching-oriented Gaussian landmark projections. Includes cosine annealing LR scheduling and gradient accumulation. ### Parameters * `gaussians` (GaussianModel) - The trained GaussianModel. * `scene` (Scene) - The Scene object containing train/test cameras. * `masks` (dict, optional) - Dictionary of per-image masks. Defaults to None. * `testing_iterations` (list[int]) - Iterations at which to perform testing. * `saving_iterations` (list[int]) - Iterations at which to save the model. * `tb_writer` (object, optional) - TensorBoard writer object. Defaults to None. * `train_iteration` (int) - Total training iterations. * `detector_folder` (str) - Folder to save the detector. * `landmark_num` (int) - Number of landmark Gaussians to sample. * `landmark_k` (int) - KNN neighborhood size for sampling. ### Request Example ```python from train_detector import training_detector from scene.gaussian_model import GaussianModel from scene import Scene # After Feature Gaussian training is complete: training_detector( gaussians=gaussians, # trained GaussianModel scene=scene, # Scene object with train/test cameras masks=masks, # dict of per-image masks (or None) testing_iterations=[10000, 20000, 30000], saving_iterations=[10000, 20000, 30000], tb_writer=tb_writer, # TensorBoard writer (or None) train_iteration=30000, detector_folder="detector", landmark_num=16384, # number of landmark Gaussians to sample landmark_k=32, # KNN neighborhood size for sampling ) ``` ### Output * `/detector/sampled_idx.pkl` — Landmark Gaussian indices. * `/detector/30000_detector.pth` — Trained detector weights. ``` -------------------------------- ### render_gsplat() for Gaussian Feature Rendering Source: https://context7.com/zju3dv/stdloc/llms.txt Renders RGB images and feature maps from a GaussianModel using a given camera viewpoint. This function handles both 3DGS and 2DGS backends and returns rasterization metadata. ```python from gaussian_renderer import render_gsplat from scene.gaussian_model import GaussianModel import torch # Assumes gaussians and viewpoint_cam are already loaded via Scene # viewpoint_cam: Camera object from scene.getTrainCameras() ``` -------------------------------- ### solve_pose() Source: https://context7.com/zju3dv/stdloc/llms.txt Estimates the absolute camera pose (world-to-camera matrix) from 2D-3D point correspondences using either the `poselib` library or OpenCV's `solvePnPRansac`. It returns the pose matrix and the indices of inlier correspondences. ```APIDOC ## solve_pose() ### Description Estimates absolute camera pose from 2D-3D point correspondences using either `poselib` (recommended) or OpenCV's `solvePnPRansac`. Returns the 4×4 world-to-camera matrix and inlier indices. ### Parameters * `p2d` (np.ndarray) - 2D keypoints in image space [N, 2] (pixel coordinates). * `p3d` (np.ndarray) - Corresponding 3D world points [N, 3]. * `solver` (str) - Pose solver to use: 'poselib' or 'opencv'. * `confidence` (float) - RANSAC confidence threshold. * `reprojection_error` (float) - RANSAC inlier threshold in pixels. * `max_iterations` (int) - Maximum RANSAC iterations. * `min_iterations` (int) - Minimum RANSAC iterations. ### Request Example ```python from utils.pose_utils import solve_pose, cal_pose_error import numpy as np # 2D keypoints in image space [N, 2] (pixel coordinates, 0-indexed + 0.5 offset) p2d = np.array([[320.5, 240.5], [150.5, 100.5], [500.5, 380.5], [80.5, 200.5]]) # Corresponding 3D world points [N, 3] p3d = np.array([[1.2, 0.5, 3.1], [0.3, -0.2, 2.4], [1.8, 0.1, 4.2], [0.5, 0.8, 2.9]]) # Example using poselib solver try: pose_w2c, inliers = solve_pose( p2d=p2d, p3d=p3d, solver='poselib', confidence=0.99999, reprojection_error=12.0, max_iterations=100000, min_iterations=1000 ) print("Pose estimated successfully using poselib.") except Exception as e: print(f"Error estimating pose with poselib: {e}") # Example using opencv solver (if poselib is not available or for comparison) try: pose_w2c_cv, inliers_cv = solve_pose( p2d=p2d, p3d=p3d, solver='opencv', confidence=0.99999, reprojection_error=12.0, max_iterations=100000, min_iterations=1000 ) print("Pose estimated successfully using opencv.") except Exception as e: print(f"Error estimating pose with opencv: {e}") ``` ### Response #### Success Response (200) * `pose_w2c` (np.ndarray) - The estimated 4x4 world-to-camera pose matrix. * `inliers` (np.ndarray) - Indices of the inlier correspondences. ``` -------------------------------- ### render_from_pose_gsplat Source: https://context7.com/zju3dv/stdloc/llms.txt Renders a Feature Gaussian scene from a raw 4x4 world-to-camera pose matrix. This function is used during the dense localization stage to generate reference feature maps and depth maps from the current pose estimate. ```APIDOC ## render_from_pose_gsplat() ### Description Renders a Feature Gaussian scene from a raw 4x4 world-to-camera pose matrix (without a `Camera` object). Used during the dense localization stage to generate reference feature maps and depth maps from the current pose estimate. ### Method ```python render_from_pose_gsplat( pc: GaussianModel, pose: torch.Tensor, # [4, 4] world-to-camera transform (float32, CUDA) fovx: float, # horizontal field of view in radians fovy: float, # vertical field of view in radians width: int, height: int, bg_color: torch.Tensor = None, # [3] background color rgb_only: bool = False, # False to also render feature map norm_feat_bf_render: bool = True, # L2-normalize features before splatting longest_edge: int = None, # downsample if max(H, W) > longest_edge rasterize_mode: str = "antialiased", # "antialiased" or "нок" render_mode: str = "RGB+D", # "RGB", "RGB+D", "RGB+ED", "RGB+Feature" ) ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python from gaussian_renderer import render_from_pose_gsplat import torch # Assuming 'gaussians' is a loaded GaussianModel object # pose_w2c: [4, 4] world-to-camera transform (float32, CUDA) pose_w2c = torch.eye(4, device="cuda", dtype=torch.float32) # identity pose example fovx = 1.047 # radians (~60 degrees) fovy = 0.785 # radians (~45 degrees) W, H = 640, 480 render_pkg = render_from_pose_gsplat( pc=gaussians, pose=pose_w2c, fovx=fovx, fovy=fovy, width=W, height=H, render_mode="RGB+ED", # renders RGB + depth norm_feat_bf_render=True, rasterize_mode="antialiased", ) color = render_pkg["render"] # [3, H, W] depth = render_pkg["depth"] # [1, H, W] — metric depth feature_map = render_pkg["feature_map"] # [C, H, W] print("Depth range:", depth.min().item(), "-", depth.max().item(), "m") ``` ### Response #### Success Response (200) - **render** (torch.Tensor) - Rendered RGB image [3, H, W] - **depth** (torch.Tensor) - Rendered depth map [1, H, W] - **feature_map** (torch.Tensor) - Rendered feature map [C, H, W] - **radii** (torch.Tensor) - Per-Gaussian screen radii [N,] - **visibility_filter** (torch.Tensor) - Frustum-visible Gaussians [N,] bool #### Response Example ```json { "render": "[3, 480, 640]", "depth": "[1, 480, 640]", "feature_map": "[256, 480, 640]", "radii": "[N,]", "visibility_filter": "[N,] bool" } ``` ``` -------------------------------- ### matching_oriented_sample() Source: https://context7.com/zju3dv/stdloc/llms.txt Selects a subset of Gaussians to serve as landmarks. It calculates per-Gaussian average cosine similarity scores across training views and then uses KNN-diversified random sampling to ensure spatial coverage. ```APIDOC ## matching_oriented_sample() ### Description Selects the most discriminative subset of Gaussians as landmarks by computing per-Gaussian average cosine similarity scores across all training views, then applying KNN-diversified random sampling to ensure spatial coverage. ### Parameters * `scene` (Scene) - The Scene object. * `gaussians` (GaussianModel) - The GaussianModel containing Gaussians. * `feature_extractor` (FeatureExtractor) - The feature extractor model. * `render_visible_masks` (dict) - Cache for visibility masks. * `masks` (dict, optional) - Optional per-image masks for outdoor scenes. * `num` (int) - Total landmark count to select. * `k` (int) - KNN neighborhood size for diversity sampling. ### Request Example ```python from train_detector import matching_oriented_sample from encoders.feature_extractor import FeatureExtractor feature_extractor = FeatureExtractor("sp").cuda().eval() render_visible_masks = {} # cache for visibility masks sampled_idx, score_avg, score_num = matching_oriented_sample( scene=scene, gaussians=gaussians, feature_extractor=feature_extractor, render_visible_masks=render_visible_masks, masks=None, # optional per-image masks for outdoor scenes num=16384, # total landmark count to select k=32, # KNN neighborhood for diversity sampling ) print(f"Selected {sampled_idx.shape[0]} landmark Gaussians") print(f"Mean match score: {score_avg.mean().item():.4f}") import pickle pickle.dump(sampled_idx, open("map_7scenes/chess/detector/sampled_idx.pkl", "wb")) ``` ### Response * `sampled_idx` (np.ndarray) - Indices of the selected landmark Gaussians. * `score_avg` (np.ndarray) - Average match scores for each Gaussian. * `score_num` (np.ndarray) - Number of matches for each Gaussian. ``` -------------------------------- ### Render Gaussian Scene with Custom Options Source: https://context7.com/zju3dv/stdloc/llms.txt Renders a Gaussian scene with options for feature map generation, normalization, downsampling, and rasterization mode. Useful for debugging or custom rendering pipelines. ```python background = torch.tensor([1.0, 1.0, 1.0], dtype=torch.float32, device="cuda") render_pkg = render_gsplat( viewpoint_camera=viewpoint_cam, pc=gaussians, bg_color=background, rgb_only=False, # False to also render feature map norm_feat_bf_render=True, # L2-normalize features before splatting longest_edge=640, # downsample if max(H, W) > 640 rasterize_mode="antialiased", ) image = render_pkg["render"] # [3, H, W] — rendered RGB feature_map = render_pkg["feature_map"] # [C, H, W] — rendered feature map (L2-normalized) radii = render_pkg["radii"] # [N,] — per-Gaussian screen radii vis_filter = render_pkg["visibility_filter"] # [N,] bool — frustum-visible Gaussians print("RGB:", image.shape, "Feature:", feature_map.shape) # RGB: torch.Size([3, 480, 640]) Feature: torch.Size([256, 480, 640]) ``` -------------------------------- ### Solve Pose with STDLoc Source: https://context7.com/zju3dv/stdloc/llms.txt Solves for the camera pose (world-to-camera matrix) given 2D-3D correspondences, camera intrinsics, and solver parameters. Supports 'poselib' or 'opencv' solvers and allows configuration of reprojection error, confidence, and iteration limits. ```python K = np.array([[525.0, 0.0, 320.0], [0.0, 525.0, 240.0], [0.0, 0.0, 1.0]], dtype=np.float32) pose_w2c, inliers = solve_pose( p2d=p2d, p3d=p3d, K=K, solver="poselib", # or "opencv" reprojection_error=8.0, # inlier threshold in pixels confidence=0.99999, max_iterations=100000, min_iterations=1000, ) print("Pose w2c:\n", pose_w2c) print(f"Inliers: {inliers.shape[0]}/{p2d.shape[0]}") # Inliers: 4/4 # Evaluate pose error against ground truth gt_w2c = np.eye(4, dtype=np.float32) ae, te = cal_pose_error(pose_w2c, gt_w2c) print(f"Angular error: {ae:.3f} deg, Translation error: {te:.3f} cm") ``` -------------------------------- ### lift_2d_to_3d Source: https://context7.com/zju3dv/stdloc/llms.txt Back-projects 2D pixel coordinates into 3D world space using the rendered depth map and known camera parameters. Used in the dense stage to generate 3D correspondences for PnP. ```APIDOC ## lift_2d_to_3d() ### Description Back-projects 2D pixel coordinates into 3D world space using the rendered depth map and known camera parameters. Used in the dense stage to generate 3D correspondences for PnP. ### Parameters - **points2d** (torch.Tensor) - [N, 2] 2D rendered match coordinates (x, y pixel coords) - **intrinsic** (torch.Tensor) - [3, 3] Intrinsic matrix - **Twc** (torch.Tensor) - [4, 4] Camera-to-world transform - **depth_map** (torch.Tensor) - [H, W] Rendered depth map ### Returns - **points3d** (torch.Tensor) - [N, 3] World-space 3D points ### Request Example ```python from stdloc import lift_2d_to_3d import torch import numpy as np # 2D rendered match coordinates [N, 2] (x, y pixel coords) rendered_p2d = torch.tensor([[320., 240.], [150., 100.], [500., 380.]], device="cuda") # Intrinsic matrix [3, 3] K = torch.tensor([[525., 0., 320.], [0., 525., 240.], [0., 0., 1.]], device="cuda") # Camera-to-world transform [4, 4] pose_c2w = torch.eye(4, device="cuda") # Rendered depth map [H, W] depth_map = torch.ones(480, 640, device="cuda") * 2.5 # uniform 2.5m depth points3d = lift_2d_to_3d( points2d=rendered_p2d, # [N, 2] intrinsic=K, # [3, 3] Twc=pose_c2w, # [4, 4] camera-to-world depth_map=depth_map, # [H, W] ) # Returns: [N, 3] world-space 3D points print("3D points shape:", points3d.shape) # 3D points shape: torch.Size([3, 3]) print("3D points:\n", points3d.cpu().numpy()) # [[ 1.527, 1.145, 2.5 ], # [ 0.594, 0.214, 2.5 ], # [ 2.358, 1.905, 2.5 ]] ``` ``` -------------------------------- ### STDLoc Sparse Localization Stage Source: https://context7.com/zju3dv/stdloc/llms.txt Performs the sparse localization stage by extracting features, matching landmarks, and solving for pose using PnP+RANSAC. This is an internal method but can be called directly. ```python # Internal usage within STDLoc.localize(); can also be called directly: fine_feature_map, coarse_feature_map = stdloc.get_feature_map(query_image) # fine_feature_map: [C, H, W] at full resolution (up to longest_edge) # coarse_feature_map: [C, H//8, W//8] sparse_result = stdloc.loc_sparse(fine_feature_map, fovx=1.047, fovy=0.785) # Returns: # { # "pose_w2c": np.ndarray [4, 4], — world-to-camera pose # "inliers": int — RANSAC inlier count # } # Config controlling sparse stage behavior (stdloc_7scenes.yaml): # sparse: ``` -------------------------------- ### KpDetector and simple_nms for Keypoint Detection Source: https://context7.com/zju3dv/stdloc/llms.txt Detects keypoints from a dense feature map using a lightweight CNN and suppresses non-maximum responses with simple_nms. Ensure the detector's input dimension matches the feature extractor. ```python from scene.kpdetector import KpDetector, simple_nms import torch # Instantiate detector matching the feature extractor's dimension detector = KpDetector(in_dim=256).cuda() # in_dim=128 for r2d2 detector.load_state_dict(torch.load("map_7scenes/chess/detector/30000_detector.pth")) detector.eval() # feature_map: [C, H, W] — normalized dense features feature_map = torch.randn(256, 480, 640).cuda() with torch.no_grad(): heat_map = detector(feature_map) # shape: [1, H, W], values in [0, 1] # Apply NMS to suppress nearby peaks (nms_radius=4) nms_scores = simple_nms(heat_map, nms_radius=4).flatten() # shape: [H*W] # Select top-2048 keypoints with positive scores _, kp_ids = torch.topk(nms_scores, 2048) pos_mask = nms_scores > 0 kp_ids = kp_ids[pos_mask[kp_ids]] print(f"Detected {kp_ids.shape[0]} keypoints") # Detected 1843 keypoints ``` -------------------------------- ### STDLoc.loc_sparse() Source: https://context7.com/zju3dv/stdloc/llms.txt Performs the sparse localization stage by extracting scene keypoints, matching them against landmark Gaussians, and solving for absolute pose using PnP+RANSAC. ```APIDOC ## STDLoc.loc_sparse() ### Description Extracts scene-specific keypoints from the query feature map, matches them against pre-sampled landmark Gaussians using cosine similarity, and solves the absolute pose via PnP+RANSAC (poselib or OpenCV). ### Method ```python loc_sparse( fine_feature_map: torch.Tensor, # [C, H, W] at full resolution fovx: float, # horizontal field of view in radians fovy: float # vertical field of view in radians ) ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python # Assuming 'stdloc' is an initialized STDLoc object and 'query_image' is loaded # fine_feature_map, coarse_feature_map = stdloc.get_feature_map(query_image) # Example using a placeholder fine_feature_map fine_feature_map = torch.rand(256, 480, 640).cuda() # Placeholder fovx = 1.047 # horizontal field of view in radians fovy = 0.785 # vertical field of view in radians sparse_result = stdloc.loc_sparse(fine_feature_map, fovx=fovx, fovy=fovy) # Returns: # { # "pose_w2c": np.ndarray [4, 4], — world-to-camera pose # "inliers": int — RANSAC inlier count # } ``` ### Response #### Success Response (200) - **pose_w2c** (np.ndarray) - The estimated world-to-camera pose matrix [4, 4]. - **inliers** (int) - The number of inliers determined by the RANSAC algorithm. #### Response Example ```json { "pose_w2c": "[[...]]", "inliers": 312 } ``` ```