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 examples/01_dummy_training.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,10 @@ def training_step():
while viewer.state == "paused":
time.sleep(0.01)
# Do the training step and compute the number of training rays per second.
tic = time.time()
tic = time.perf_counter()
with viewer.lock:
num_train_rays_per_step = training_step()
num_train_steps_per_sec = 1.0 / (max(time.time() - tic, 1e-10))
num_train_steps_per_sec = 1.0 / (time.perf_counter() - tic)
num_train_rays_per_sec = num_train_rays_per_step * num_train_steps_per_sec
# Update the viewer state.
viewer.render_tab_state.num_train_rays_per_sec = num_train_rays_per_sec
Expand Down
12 changes: 6 additions & 6 deletions examples/04_gsplat_training.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,14 +403,14 @@ def train(self):
trainloader_iter = iter(trainloader)

# Training loop.
tic = time.time()
tic = time.perf_counter()
pbar = tqdm.tqdm(range(init_step, max_steps))
for step in pbar:
if not cfg.disable_viewer:
while self.viewer.state.status == "paused":
time.sleep(0.01)
self.viewer.lock.acquire()
tic = time.time()
tic = time.perf_counter()

try:
data = next(trainloader_iter)
Expand Down Expand Up @@ -607,7 +607,7 @@ def train(self):
# save checkpoint
if step in [i - 1 for i in cfg.save_steps] or step == max_steps - 1:
mem = torch.cuda.max_memory_allocated() / 1024**3
toc = time.time()
toc = time.perf_counter()
stats = {
"mem": mem,
"ellipse_time": toc - tic,
Expand All @@ -631,7 +631,7 @@ def train(self):

if not cfg.disable_viewer:
self.viewer.lock.release()
num_train_steps_per_sec = 1.0 / (max(time.time() - tic, 1e-10))
num_train_steps_per_sec = 1.0 / (time.perf_counter() - tic)
num_train_rays_per_sec = (
num_train_rays_per_step * num_train_steps_per_sec
)
Expand Down Expand Up @@ -810,7 +810,7 @@ def eval(self, step: int):
height, width = pixels.shape[1:3]

torch.cuda.synchronize()
tic = time.time()
tic = time.perf_counter()
colors, _, _ = self.rasterize_splats(
camtoworlds=camtoworlds,
Ks=Ks,
Expand All @@ -822,7 +822,7 @@ def eval(self, step: int):
) # [1, H, W, 3]
colors = torch.clamp(colors, 0.0, 1.0)
torch.cuda.synchronize()
ellipse_time += max(time.time() - tic, 1e-10)
ellipse_time += time.perf_counter() - tic

# write images
canvas = torch.cat([pixels, colors], dim=2).squeeze(0).cpu().numpy()
Expand Down
44 changes: 22 additions & 22 deletions nerfview/_renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,26 +91,25 @@ def _may_interrupt_trace(self, frame, event, arg):
def _get_img_wh(self, aspect: float) -> Tuple[int, int]:
# we always trade off speed for quality
max_img_res = self.viewer.render_tab_state.viewer_res
if self._state in ["high"]:
# if True:
H = max_img_res
W = int(H * aspect)
if W > max_img_res:
W = max_img_res
H = int(W / aspect)
elif self._state in ["low_move", "low_static"]:
num_view_rays_per_sec = self.viewer.render_tab_state.num_view_rays_per_sec
target_fps = self._target_fps
num_viewer_rays = num_view_rays_per_sec / target_fps
H = (num_viewer_rays / aspect) ** 0.5
H = int(round(H, -1))
H = max(min(max_img_res, H), 30)
W = int(H * aspect)
if W > max_img_res:
W = max_img_res
H = int(W / aspect)
else:
raise ValueError(f"Unknown state: {self._state}.")
# if self._state in ["high"]:
H = max_img_res
W = int(H * aspect)
if W > max_img_res:
W = max_img_res
H = int(W / aspect)
# elif self._state in ["low_move", "low_static"]:
# num_view_rays_per_sec = self.viewer.render_tab_state.num_view_rays_per_sec
# target_fps = self._target_fps
# num_viewer_rays = num_view_rays_per_sec / target_fps
# H = (num_viewer_rays / aspect) ** 0.5
# H = int(round(H, -1))
# H = max(min(max_img_res, H), 30)
# W = int(H * aspect)
# if W > max_img_res:
# W = max_img_res
# H = int(W / aspect)
# else:
# raise ValueError(f"Unknown state: {self._state}.")
return W, H

def submit(self, task: RenderTask):
Expand Down Expand Up @@ -145,7 +144,7 @@ def run(self):
assert task.camera_state is not None
try:
with self.lock, set_trace_context(self._may_interrupt_trace):
tic = time.time()
tic = time.perf_counter()
W, H = img_wh = self._get_img_wh(task.camera_state.aspect)
self.viewer.render_tab_state.viewer_width = W
self.viewer.render_tab_state.viewer_height = H
Expand All @@ -171,8 +170,9 @@ def run(self):
else:
img, depth = rendered, None
self.viewer.render_tab_state.num_view_rays_per_sec = (W * H) / (
max(time.time() - tic, 1e-10)
time.perf_counter() - tic
)
# print("FPS:", 1 / (time.perf_counter() - tic))
except InterruptRenderException:
continue
except Exception:
Expand Down
44 changes: 29 additions & 15 deletions nerfview/render_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import threading
import time
from pathlib import Path
from time import perf_counter as perf_counter
from typing import Dict, List, Literal, Optional, Tuple, Union

import imageio
Expand Down Expand Up @@ -912,6 +913,7 @@ def get_max_frame_index() -> int:
return max(1, int(framerate_number.value * duration_number.value) - 1)

preview_camera_handle: Optional[viser.SceneNodeHandle] = None
_last_send = 0.0

def remove_preview_camera() -> None:
nonlocal preview_camera_handle
Expand Down Expand Up @@ -977,18 +979,17 @@ def _(_) -> None:
pose, fov, time = maybe_pose_and_fov_rad
else:
pose, fov = maybe_pose_and_fov_rad

preview_camera_handle = server.scene.add_camera_frustum(
"/preview_camera",
fov=fov,
aspect=render_res_vec2.value[0] / render_res_vec2.value[1],
scale=0.35,
wxyz=pose.rotation().wxyz,
position=pose.translation(),
color=(10, 200, 30),
)
if render_tab_state.preview_render:
with server.atomic():
with server.atomic():
preview_camera_handle = server.scene.add_camera_frustum(
"/preview_camera",
fov=fov,
aspect=render_res_vec2.value[0] / render_res_vec2.value[1],
scale=0.35,
wxyz=pose.rotation().wxyz,
position=pose.translation(),
color=(10, 200, 30),
)
if render_tab_state.preview_render:
for client in server.get_clients().values():
# aspect ratio is not assignable, pass args in get_render instead
client.camera.wxyz = pose.rotation().wxyz
Expand Down Expand Up @@ -1114,17 +1115,21 @@ def play() -> None:
max_frame = int(framerate_number.value * duration_number.value)
if max_frame > 0:
assert preview_frame_slider is not None
nonlocal _last_send
now = perf_counter()
if now - _last_send < 1.0 / framerate_number.value:
continue
_last_send = now
preview_frame_slider.value = (
preview_frame_slider.value + 1
) % max_frame
time.sleep(1.0 / framerate_number.value)

play_thread = threading.Thread(target=play)
play_thread.start()
play_thread.join()
dump_video_button.disabled = not preview_save_camera_path_button.visible

# Play the camera trajectory when the play button is pressed.
# Pause the camera trajectory when the pause button is pressed.
@pause_button.on_click
def _(_) -> None:
play_button.visible = True
Expand Down Expand Up @@ -1366,7 +1371,13 @@ def dump() -> None:
max_frame = int(framerate_number.value * duration_number.value)
assert max_frame > 0 and preview_frame_slider is not None
preview_frame_slider.value = 0
for _ in range(max_frame):
render_count = 0
while True:
nonlocal _last_send
now = perf_counter()
if now - _last_send < 1.0 / framerate_number.value:
continue
_last_send = now
preview_frame_slider.value = (
preview_frame_slider.value + 1
) % max_frame
Expand All @@ -1376,6 +1387,9 @@ def dump() -> None:
width=render_res_vec2.value[0],
)
writer.append_data(image)
render_count += 1
if render_count >= max_frame:
break
writer.close()
print(f"Video saved to {video_outfile}")

Expand Down
2 changes: 1 addition & 1 deletion nerfview/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.1.3"
__version__ = "0.1.4"
4 changes: 2 additions & 2 deletions nerfview/viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ def _connect_client(self, client: viser.ClientHandle):

@client.camera.on_update
def _(_: viser.CameraHandle):
self._last_move_time = time.time()
self._last_move_time = time.perf_counter()
with self.server.atomic():
camera_state = self.get_camera_state(client)
self._renderers[client_id].submit(RenderTask("move", camera_state))
Expand Down Expand Up @@ -240,7 +240,7 @@ def update(self, step: int, num_train_rays_per_step: int):
if len(self._renderers) == 0:
return
# Stop training while user moves camera to make viewing smoother.
while time.time() - self._last_move_time < 0.1:
while time.perf_counter() - self._last_move_time < 0.1:
time.sleep(0.05)
if (
self.state == "training"
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "nerfview"
version = "0.1.3"
version = "0.1.4"
description = "Interactive NeRF rendering web viewer"
readme = "README.md"
license = { text = "MIT" }
Expand Down