Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/core_code_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ jobs:

steps:
- uses: actions/checkout@v3
- name: Set up Python 3.8.13
- name: Set up Python 3.11.13
uses: actions/setup-python@v4
with:
python-version: '3.8.13'
python-version: '3.11.13'
- uses: actions/cache@v3
with:
path: ${{ env.pythonLocation }}
Expand Down
6 changes: 3 additions & 3 deletions nerfstudio/cameras/camera_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def get_interpolated_poses(pose_a: NDArray, pose_b: NDArray, steps: int = 10) ->
quat_b = quaternion_from_matrix(pose_b[:3, :3])

ts = np.linspace(0, 1, steps)
quats = [quaternion_slerp(quat_a, quat_b, t) for t in ts]
quats = [quaternion_slerp(quat_a, quat_b, float(t)) for t in ts]
trans = [(1 - t) * pose_a[:3, 3] + t * pose_b[:3, 3] for t in ts]

poses_ab = []
Expand All @@ -199,7 +199,7 @@ def get_interpolated_k(
List of interpolated camera poses
"""
Ks: List[Float[Tensor, "3 3"]] = []
ts = np.linspace(0, 1, steps)
ts = torch.linspace(0, 1, steps, dtype=k_a.dtype, device=k_a.device)
for t in ts:
new_k = k_a * (1.0 - t) + k_b * t
Ks.append(new_k)
Expand All @@ -218,7 +218,7 @@ def get_interpolated_time(
steps: number of steps the interpolated pose path should contain
"""
times: List[Float[Tensor, "1"]] = []
ts = np.linspace(0, 1, steps)
ts = torch.linspace(0, 1, steps, dtype=time_a.dtype, device=time_a.device)
for t in ts:
new_t = time_a * (1.0 - t) + time_b * t
times.append(new_t)
Expand Down
1 change: 1 addition & 0 deletions nerfstudio/cameras/rays.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ def get_weights(self, densities: Float[Tensor, "*batch num_samples 1"]) -> Float
Weights for each sample
"""

assert self.deltas is not None, "Deltas must be set to compute weights"
delta_density = self.deltas * densities
alphas = 1 - torch.exp(-delta_density)

Expand Down
1 change: 1 addition & 0 deletions nerfstudio/data/dataparsers/colmap_dataparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@ def _load_3D_points(self, colmap_path: Path, transform_matrix: torch.Tensor, sca
points3D_image_ids.append(
torch.cat((nids, torch.full((max_num_points - len(nids),), -1, dtype=torch.int64)))
)
assert downscale_factor is not None
points3D_image_xy.append(
torch.cat((nxy, torch.full((max_num_points - len(nxy), nxy.shape[-1]), 0, dtype=torch.float32)))
/ downscale_factor
Expand Down
4 changes: 2 additions & 2 deletions nerfstudio/data/dataparsers/dycheck_dataparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,8 @@ def process_frames(self, frame_names: List[str], time_ids: np.ndarray) -> Tuple[
cam_json = load_from_json(self.data / f"camera/{frame}.json")
c2w = torch.as_tensor(cam_json["orientation"]).T
position = torch.as_tensor(cam_json["position"])
position -= self._center # some scenes look weird (wheel)
position *= self._scale * self.config.scale_factor
position -= torch.as_tensor(self._center) # some scenes look weird (wheel)
position *= torch.as_tensor(self._scale) * self.config.scale_factor
pose = torch.zeros([3, 4])
pose[:3, :3] = c2w
pose[:3, 3] = position
Expand Down
1 change: 1 addition & 0 deletions nerfstudio/data/dataparsers/nerfstudio_dataparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ def _get_fname(self, filepath: Path, data_dir: Path, downsample_folder_prefix="i
CONSOLE.log(f"Auto image downscale factor of {self.downscale_factor}")
else:
self.downscale_factor = self.config.downscale_factor
assert self.downscale_factor is not None

if self.downscale_factor > 1:
return data_dir / f"{downsample_folder_prefix}{self.downscale_factor}" / filepath.name
Expand Down
1 change: 1 addition & 0 deletions nerfstudio/data/pixel_samplers.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ def sample_method_fisheye(

rand_samples = torch.rand((samples_needed, 2), device=device)
# Convert random samples to radius and theta.
assert self.config.fisheye_crop_radius is not None
radii = self.config.fisheye_crop_radius * torch.sqrt(rand_samples[:, 0])
theta = 2.0 * torch.pi * rand_samples[:, 1]

Expand Down
2 changes: 1 addition & 1 deletion nerfstudio/data/utils/data_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def get_depth_image_from_path(
else:
image = cv2.imread(str(filepath.absolute()), cv2.IMREAD_ANYDEPTH)
image = image.astype(np.float32) * scale_factor
image = cv2.resize(image, (width, height), interpolation=interpolation)
image = cv2.resize(image, (width, height), interpolation=interpolation) # type: ignore
return torch.from_numpy(image[:, :, np.newaxis])


Expand Down
1 change: 1 addition & 0 deletions nerfstudio/exporter/exporter_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ def collect_camera_poses(pipeline: VanillaPipeline) -> Tuple[List[Dict[str, Any]
camera_optimizer = None
if hasattr(pipeline.model, "camera_optimizer"):
camera_optimizer = pipeline.model.camera_optimizer
assert isinstance(camera_optimizer, CameraOptimizer)

train_frames = collect_camera_poses_for_dataset(train_dataset, camera_optimizer)
# Note: returning original poses, even if --eval-mode=all
Expand Down
6 changes: 1 addition & 5 deletions nerfstudio/field_components/encodings.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,6 @@ def __init__(self, in_dim: int) -> None:
raise ValueError("Input dimension should be greater than zero")
super().__init__(in_dim=in_dim)

@classmethod
def get_tcnn_encoding_config(cls) -> dict:
"""Get the encoding configuration for tcnn if implemented"""
raise NotImplementedError("Encoding does not have a TCNN implementation")

@abstractmethod
def forward(self, in_tensor: Shaped[Tensor, "*bs input_dim"]) -> Shaped[Tensor, "*bs output_dim"]:
"""Call forward and returns and processed tensor
Expand Down Expand Up @@ -217,6 +212,7 @@ def __init__(
self.min_freq = min_freq_exp
self.max_freq = max_freq_exp
self.register_buffer(name="b_matrix", tensor=basis)
self.b_matrix: Tensor
self.include_input = include_input

def get_out_dim(self) -> int:
Expand Down
1 change: 1 addition & 0 deletions nerfstudio/fields/sdf_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ def get_alpha(
) # always non-positive

# Estimate signed distances at section points
assert ray_samples.deltas is not None, "Ray samples must have deltas for alpha computation."
estimated_next_sdf = sdf + iter_cos * ray_samples.deltas * 0.5
estimated_prev_sdf = sdf - iter_cos * ray_samples.deltas * 0.5

Expand Down
4 changes: 2 additions & 2 deletions nerfstudio/models/generfacto.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from __future__ import annotations

from dataclasses import dataclass, field
from typing import Dict, List, Optional, Tuple, Type
from typing import Dict, List, Optional, Tuple, Type, cast

import numpy as np
import torch
Expand Down Expand Up @@ -444,7 +444,7 @@ def get_loss_dict(self, outputs, batch, metrics_dict=None) -> Dict[str, torch.Te
loss_dict = misc.scale_dict(loss_dict, self.config.loss_coefficients)
if self.train_normals:
# orientation loss for computed normals
loss_dict["orientation_loss"] = self.orientation_loss_mult * torch.mean(
loss_dict["orientation_loss"] = cast(float, self.orientation_loss_mult) * torch.mean(
outputs["rendered_orientation_loss"]
)
else:
Expand Down
6 changes: 3 additions & 3 deletions nerfstudio/models/instant_ngp.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from __future__ import annotations

from dataclasses import dataclass, field
from typing import Dict, List, Literal, Optional, Tuple, Type, Union
from typing import Dict, List, Literal, Optional, Tuple, Type, Union, cast

import nerfacc
import torch
Expand Down Expand Up @@ -152,7 +152,7 @@ def get_training_callbacks(
def update_occupancy_grid(step: int):
self.occupancy_grid.update_every_n_steps(
step=step,
occ_eval_fn=lambda x: self.field.density_fn(x) * self.config.render_step_size,
occ_eval_fn=lambda x: self.field.density_fn(x) * cast(float, self.config.render_step_size),
)

return [
Expand All @@ -170,7 +170,7 @@ def get_param_groups(self) -> Dict[str, List[Parameter]]:
param_groups["fields"] = list(self.field.parameters())
return param_groups

def get_outputs(self, ray_bundle: RayBundle):
def get_outputs(self, ray_bundle: RayBundle): # type: ignore
assert self.field is not None
num_rays = len(ray_bundle)

Expand Down
4 changes: 2 additions & 2 deletions nerfstudio/models/splatfacto.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ def populate_modules(self):
)
self.strategy_state = self.strategy.initialize_state()
else:
raise ValueError(f"""Splatfacto does not support strategy {self.config.strategy}
raise ValueError(f"""Splatfacto does not support strategy {self.config.strategy}
Currently, the supported strategies include default and mcmc.""")

@property
Expand Down Expand Up @@ -552,7 +552,7 @@ def get_outputs(self, camera: Cameras) -> Dict[str, Union[torch.Tensor, List]]:
colors_crop = torch.sigmoid(colors_crop).squeeze(1) # [N, 1, 3] -> [N, 3]
sh_degree_to_use = None

render, alpha, self.info = rasterization(
render, alpha, self.info = rasterization( # type: ignore[reportPossiblyUnboundVariable]
means=means_crop,
quats=quats_crop, # rasterization does normalization internally
scales=torch.exp(scales_crop),
Expand Down
6 changes: 3 additions & 3 deletions nerfstudio/process_data/process_data_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import sys
from enum import Enum
from pathlib import Path
from typing import List, Literal, Optional, OrderedDict, Tuple, Union
from typing import List, Literal, Optional, OrderedDict, Tuple, Union, cast

import cv2
import imageio
Expand Down Expand Up @@ -95,7 +95,7 @@ def get_image_filenames(directory: Path, max_num_images: int = -1) -> Tuple[List
else:
idx = np.arange(num_orig_images)

image_filenames = list(np.array(image_paths)[idx])
image_filenames = cast(List[Path], list(np.array(image_paths)[idx]))

return image_filenames, num_orig_images

Expand Down Expand Up @@ -596,7 +596,7 @@ def generate_circle_mask(height: int, width: int, percent_radius) -> Optional[np
mask = np.zeros((height, width), dtype=np.uint8)
center = (width // 2, height // 2)
radius = int(percent_radius * np.sqrt(width**2 + height**2) / 2.0)
cv2.circle(mask, center, radius, 1, -1)
cv2.circle(mask, center, radius, 1, -1) # type: ignore
return mask


Expand Down
2 changes: 1 addition & 1 deletion nerfstudio/scripts/downloads/eyeful_tower.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def scale_metashape_transform(xml_tree: ET.ElementTree, target_width: int, targe

root = transformed.getroot()
assert len(root) == 1
chunk = root[0]
chunk = root[0] # type: ignore[reportOptionalSubscript]
sensors = chunk.find("sensors")
assert sensors is not None

Expand Down
4 changes: 2 additions & 2 deletions nerfstudio/scripts/process_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import zipfile
from dataclasses import dataclass
from pathlib import Path
from typing import Optional, Union
from typing import List, Optional, Union, cast

import numpy as np
import tyro
Expand Down Expand Up @@ -90,7 +90,7 @@ def main(self) -> None:
record3d_image_filenames = list(np.array(record3d_image_filenames)[idx])
# Copy images to output directory
copied_image_paths = process_data_utils.copy_images_list(
record3d_image_filenames,
cast(List[Path], record3d_image_filenames),
image_dir=image_dir,
verbose=self.verbose,
num_downscales=self.num_downscales,
Expand Down
1 change: 1 addition & 0 deletions nerfstudio/scripts/train.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ def launch(
process_context.join()
except KeyboardInterrupt:
for i, process in enumerate(process_context.processes):
assert process is not None
if process.is_alive():
CONSOLE.log(f"Terminating process {i}...")
process.terminate()
Expand Down
5 changes: 4 additions & 1 deletion nerfstudio/utils/colormaps.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,10 @@ def apply_float_colormap(image: Float[Tensor, "*bs 1"], colormap: Colormaps = "v
image_long_max = torch.max(image_long)
assert image_long_min >= 0, f"the min value is {image_long_min}"
assert image_long_max <= 255, f"the max value is {image_long_max}"
return torch.tensor(matplotlib.colormaps[colormap].colors, device=image.device)[image_long[..., 0]]
return torch.tensor(
matplotlib.colormaps[colormap].colors, # type: ignore
device=image.device,
)[image_long[..., 0]]


def apply_depth_colormap(
Expand Down
4 changes: 2 additions & 2 deletions nerfstudio/utils/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def get_dict_to_torch(stuff: T, device: Union[torch.device, str] = "cpu", exclud
stuff[k] = get_dict_to_torch(v, device)
return stuff
if isinstance(stuff, torch.Tensor):
return stuff.to(device)
return stuff.to(device) # type: ignore[reportReturnType]
return stuff


Expand All @@ -59,7 +59,7 @@ def get_dict_to_cpu(stuff: T) -> T:
stuff[k] = get_dict_to_cpu(v)
return stuff
if isinstance(stuff, torch.Tensor):
return stuff.detach().cpu()
return stuff.detach().cpu() # type: ignore[reportReturnType]
return stuff


Expand Down
2 changes: 1 addition & 1 deletion nerfstudio/utils/profiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def time_function(name_or_func: Union[CallableT, str]) -> Union[CallableT, Conte
Returns:
A wrapped function or context to use in a `with` statement.
"""
return _TimeFunction(name_or_func)
return _TimeFunction(name_or_func) # type: ignore[reportReturnType]


class _TimeFunction(ContextDecorator):
Expand Down
6 changes: 4 additions & 2 deletions nerfstudio/viewer/render_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,9 @@ def update_spline(self) -> None:
points_array = self._position_spline.evaluate(
self.spline_t_from_t_sec(np.linspace(0, transition_times_cumsum[-1], num_frames))
)
colors_array = np.array([colorsys.hls_to_rgb(h, 0.5, 1.0) for h in np.linspace(0.0, 1.0, len(points_array))])
colors_array = np.array(
[colorsys.hls_to_rgb(float(h), 0.5, 1.0) for h in np.linspace(0.0, 1.0, len(points_array))],
)

# Clear prior spline nodes.
for node in self._spline_nodes:
Expand All @@ -377,7 +379,7 @@ def update_spline(self) -> None:
self._spline_nodes.append(
self._server.scene.add_spline_catmull_rom(
"/render_camera_spline",
positions=points_array,
points=points_array,
color=(220, 220, 220),
closed=self.loop,
line_width=1.0,
Expand Down
8 changes: 5 additions & 3 deletions nerfstudio/viewer/render_state_machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,9 @@ def _render_img(self, camera_state: CameraState):
[color[0] / 255.0, color[1] / 255.0, color[2] / 255.0],
device=self.viewer.get_model().device,
)
self.viewer.get_model().set_background(background_color)
self.viewer.get_model().set_background(background_color) # type: ignore[reportCallIssue]
was_training = self.viewer.get_model().training
self.viewer.get_model().eval()
step = self.viewer.step
try:
if self.viewer.control_panel.crop_viewport:
color = self.viewer.control_panel.background_color
Expand Down Expand Up @@ -201,7 +200,10 @@ def _render_img(self, camera_state: CameraState):
render_time = vis_t.duration
if writer.is_initialized() and render_time != 0:
writer.put_time(
name=EventName.VIS_RAYS_PER_SEC, duration=num_rays / render_time, step=step, avg_over_steps=True
name=EventName.VIS_RAYS_PER_SEC,
duration=num_rays / render_time,
step=self.viewer.step,
avg_over_steps=True,
)
return outputs

Expand Down
9 changes: 4 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ dependencies = [
"torchvision>=0.14.1",
"torchmetrics[image]>=1.0.1",
"typing_extensions>=4.4.0",
"viser==0.2.7",
"viser==1.0.0",
"nuscenes-devkit>=1.1.1",
"wandb>=0.13.3",
"xatlas",
Expand Down Expand Up @@ -93,7 +93,7 @@ dev = [
"pre-commit==3.3.2",
"pytest==7.1.2",
"pytest-xdist==2.5.0",
"ruff>=0.6.1",
"ruff==0.12.2",
"sshconf==0.2.5",
"pycolmap>=0.3.0", # NOTE: pycolmap==0.3.0 is not available on newer python versions
"diffusers==0.16.1",
Expand All @@ -103,8 +103,7 @@ dev = [
# NOTE: Disabling projectaria-tools because it doesn't have prebuilt windows wheels
# Syntax comes from here: https://pip.pypa.io/en/stable/reference/requirement-specifiers/
"projectaria-tools>=1.3.1; sys_platform != 'win32'",
# pin torch to <=2.1 to fix https://github.com/pytorch/pytorch/issues/118736
"torch>=1.13.1,<2.2",
"torch==2.7.1",
"awscli==1.33.18"
]

Expand Down Expand Up @@ -161,7 +160,6 @@ reportMissingImports = "warning"
reportMissingTypeStubs = false
reportPrivateImportUsage = false

pythonVersion = "3.8"
pythonPlatform = "Linux"

[tool.ruff]
Expand All @@ -185,6 +183,7 @@ lint.ignore = [
"PLR0915", # Too many statements.
"PLR0913", # Too many arguments.
"PLC0414", # Import alias does not rename variable. (this is used for exporting names)
"PLC0415", # `import` should be at the top-level of a file
"PLC1901", # Use falsey strings.
"PLR5501", # Use `elif` instead of `else if`.
"PLR0911", # Too many return statements.
Expand Down