Skip to content

Commit bd802d7

Browse files
Merge pull request #26 from RongLiu-Leo/main
Accurately trigger the preview slider update based on FPS
2 parents e6d56fd + 9d085c5 commit bd802d7

File tree

7 files changed

+63
-49
lines changed

7 files changed

+63
-49
lines changed

examples/01_dummy_training.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,10 @@ def training_step():
9797
while viewer.state == "paused":
9898
time.sleep(0.01)
9999
# Do the training step and compute the number of training rays per second.
100-
tic = time.time()
100+
tic = time.perf_counter()
101101
with viewer.lock:
102102
num_train_rays_per_step = training_step()
103-
num_train_steps_per_sec = 1.0 / (max(time.time() - tic, 1e-10))
103+
num_train_steps_per_sec = 1.0 / (time.perf_counter() - tic)
104104
num_train_rays_per_sec = num_train_rays_per_step * num_train_steps_per_sec
105105
# Update the viewer state.
106106
viewer.render_tab_state.num_train_rays_per_sec = num_train_rays_per_sec

examples/04_gsplat_training.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -403,14 +403,14 @@ def train(self):
403403
trainloader_iter = iter(trainloader)
404404

405405
# Training loop.
406-
tic = time.time()
406+
tic = time.perf_counter()
407407
pbar = tqdm.tqdm(range(init_step, max_steps))
408408
for step in pbar:
409409
if not cfg.disable_viewer:
410410
while self.viewer.state.status == "paused":
411411
time.sleep(0.01)
412412
self.viewer.lock.acquire()
413-
tic = time.time()
413+
tic = time.perf_counter()
414414

415415
try:
416416
data = next(trainloader_iter)
@@ -607,7 +607,7 @@ def train(self):
607607
# save checkpoint
608608
if step in [i - 1 for i in cfg.save_steps] or step == max_steps - 1:
609609
mem = torch.cuda.max_memory_allocated() / 1024**3
610-
toc = time.time()
610+
toc = time.perf_counter()
611611
stats = {
612612
"mem": mem,
613613
"ellipse_time": toc - tic,
@@ -631,7 +631,7 @@ def train(self):
631631

632632
if not cfg.disable_viewer:
633633
self.viewer.lock.release()
634-
num_train_steps_per_sec = 1.0 / (max(time.time() - tic, 1e-10))
634+
num_train_steps_per_sec = 1.0 / (time.perf_counter() - tic)
635635
num_train_rays_per_sec = (
636636
num_train_rays_per_step * num_train_steps_per_sec
637637
)
@@ -810,7 +810,7 @@ def eval(self, step: int):
810810
height, width = pixels.shape[1:3]
811811

812812
torch.cuda.synchronize()
813-
tic = time.time()
813+
tic = time.perf_counter()
814814
colors, _, _ = self.rasterize_splats(
815815
camtoworlds=camtoworlds,
816816
Ks=Ks,
@@ -822,7 +822,7 @@ def eval(self, step: int):
822822
) # [1, H, W, 3]
823823
colors = torch.clamp(colors, 0.0, 1.0)
824824
torch.cuda.synchronize()
825-
ellipse_time += max(time.time() - tic, 1e-10)
825+
ellipse_time += time.perf_counter() - tic
826826

827827
# write images
828828
canvas = torch.cat([pixels, colors], dim=2).squeeze(0).cpu().numpy()

nerfview/_renderer.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -91,26 +91,25 @@ def _may_interrupt_trace(self, frame, event, arg):
9191
def _get_img_wh(self, aspect: float) -> Tuple[int, int]:
9292
# we always trade off speed for quality
9393
max_img_res = self.viewer.render_tab_state.viewer_res
94-
if self._state in ["high"]:
95-
# if True:
96-
H = max_img_res
97-
W = int(H * aspect)
98-
if W > max_img_res:
99-
W = max_img_res
100-
H = int(W / aspect)
101-
elif self._state in ["low_move", "low_static"]:
102-
num_view_rays_per_sec = self.viewer.render_tab_state.num_view_rays_per_sec
103-
target_fps = self._target_fps
104-
num_viewer_rays = num_view_rays_per_sec / target_fps
105-
H = (num_viewer_rays / aspect) ** 0.5
106-
H = int(round(H, -1))
107-
H = max(min(max_img_res, H), 30)
108-
W = int(H * aspect)
109-
if W > max_img_res:
110-
W = max_img_res
111-
H = int(W / aspect)
112-
else:
113-
raise ValueError(f"Unknown state: {self._state}.")
94+
# if self._state in ["high"]:
95+
H = max_img_res
96+
W = int(H * aspect)
97+
if W > max_img_res:
98+
W = max_img_res
99+
H = int(W / aspect)
100+
# elif self._state in ["low_move", "low_static"]:
101+
# num_view_rays_per_sec = self.viewer.render_tab_state.num_view_rays_per_sec
102+
# target_fps = self._target_fps
103+
# num_viewer_rays = num_view_rays_per_sec / target_fps
104+
# H = (num_viewer_rays / aspect) ** 0.5
105+
# H = int(round(H, -1))
106+
# H = max(min(max_img_res, H), 30)
107+
# W = int(H * aspect)
108+
# if W > max_img_res:
109+
# W = max_img_res
110+
# H = int(W / aspect)
111+
# else:
112+
# raise ValueError(f"Unknown state: {self._state}.")
114113
return W, H
115114

116115
def submit(self, task: RenderTask):
@@ -145,7 +144,7 @@ def run(self):
145144
assert task.camera_state is not None
146145
try:
147146
with self.lock, set_trace_context(self._may_interrupt_trace):
148-
tic = time.time()
147+
tic = time.perf_counter()
149148
W, H = img_wh = self._get_img_wh(task.camera_state.aspect)
150149
self.viewer.render_tab_state.viewer_width = W
151150
self.viewer.render_tab_state.viewer_height = H
@@ -171,8 +170,9 @@ def run(self):
171170
else:
172171
img, depth = rendered, None
173172
self.viewer.render_tab_state.num_view_rays_per_sec = (W * H) / (
174-
max(time.time() - tic, 1e-10)
173+
time.perf_counter() - tic
175174
)
175+
# print("FPS:", 1 / (time.perf_counter() - tic))
176176
except InterruptRenderException:
177177
continue
178178
except Exception:

nerfview/render_panel.py

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import threading
2222
import time
2323
from pathlib import Path
24+
from time import perf_counter as perf_counter
2425
from typing import Dict, List, Literal, Optional, Tuple, Union
2526

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

914915
preview_camera_handle: Optional[viser.SceneNodeHandle] = None
916+
_last_send = 0.0
915917

916918
def remove_preview_camera() -> None:
917919
nonlocal preview_camera_handle
@@ -977,18 +979,17 @@ def _(_) -> None:
977979
pose, fov, time = maybe_pose_and_fov_rad
978980
else:
979981
pose, fov = maybe_pose_and_fov_rad
980-
981-
preview_camera_handle = server.scene.add_camera_frustum(
982-
"/preview_camera",
983-
fov=fov,
984-
aspect=render_res_vec2.value[0] / render_res_vec2.value[1],
985-
scale=0.35,
986-
wxyz=pose.rotation().wxyz,
987-
position=pose.translation(),
988-
color=(10, 200, 30),
989-
)
990-
if render_tab_state.preview_render:
991-
with server.atomic():
982+
with server.atomic():
983+
preview_camera_handle = server.scene.add_camera_frustum(
984+
"/preview_camera",
985+
fov=fov,
986+
aspect=render_res_vec2.value[0] / render_res_vec2.value[1],
987+
scale=0.35,
988+
wxyz=pose.rotation().wxyz,
989+
position=pose.translation(),
990+
color=(10, 200, 30),
991+
)
992+
if render_tab_state.preview_render:
992993
for client in server.get_clients().values():
993994
# aspect ratio is not assignable, pass args in get_render instead
994995
client.camera.wxyz = pose.rotation().wxyz
@@ -1114,17 +1115,21 @@ def play() -> None:
11141115
max_frame = int(framerate_number.value * duration_number.value)
11151116
if max_frame > 0:
11161117
assert preview_frame_slider is not None
1118+
nonlocal _last_send
1119+
now = perf_counter()
1120+
if now - _last_send < 1.0 / framerate_number.value:
1121+
continue
1122+
_last_send = now
11171123
preview_frame_slider.value = (
11181124
preview_frame_slider.value + 1
11191125
) % max_frame
1120-
time.sleep(1.0 / framerate_number.value)
11211126

11221127
play_thread = threading.Thread(target=play)
11231128
play_thread.start()
11241129
play_thread.join()
11251130
dump_video_button.disabled = not preview_save_camera_path_button.visible
11261131

1127-
# Play the camera trajectory when the play button is pressed.
1132+
# Pause the camera trajectory when the pause button is pressed.
11281133
@pause_button.on_click
11291134
def _(_) -> None:
11301135
play_button.visible = True
@@ -1366,7 +1371,13 @@ def dump() -> None:
13661371
max_frame = int(framerate_number.value * duration_number.value)
13671372
assert max_frame > 0 and preview_frame_slider is not None
13681373
preview_frame_slider.value = 0
1369-
for _ in range(max_frame):
1374+
render_count = 0
1375+
while True:
1376+
nonlocal _last_send
1377+
now = perf_counter()
1378+
if now - _last_send < 1.0 / framerate_number.value:
1379+
continue
1380+
_last_send = now
13701381
preview_frame_slider.value = (
13711382
preview_frame_slider.value + 1
13721383
) % max_frame
@@ -1376,6 +1387,9 @@ def dump() -> None:
13761387
width=render_res_vec2.value[0],
13771388
)
13781389
writer.append_data(image)
1390+
render_count += 1
1391+
if render_count >= max_frame:
1392+
break
13791393
writer.close()
13801394
print(f"Video saved to {video_outfile}")
13811395

nerfview/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.1.3"
1+
__version__ = "0.1.4"

nerfview/viewer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ def _connect_client(self, client: viser.ClientHandle):
206206

207207
@client.camera.on_update
208208
def _(_: viser.CameraHandle):
209-
self._last_move_time = time.time()
209+
self._last_move_time = time.perf_counter()
210210
with self.server.atomic():
211211
camera_state = self.get_camera_state(client)
212212
self._renderers[client_id].submit(RenderTask("move", camera_state))
@@ -240,7 +240,7 @@ def update(self, step: int, num_train_rays_per_step: int):
240240
if len(self._renderers) == 0:
241241
return
242242
# Stop training while user moves camera to make viewing smoother.
243-
while time.time() - self._last_move_time < 0.1:
243+
while time.perf_counter() - self._last_move_time < 0.1:
244244
time.sleep(0.05)
245245
if (
246246
self.state == "training"

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "nerfview"
7-
version = "0.1.3"
7+
version = "0.1.4"
88
description = "Interactive NeRF rendering web viewer"
99
readme = "README.md"
1010
license = { text = "MIT" }

0 commit comments

Comments
 (0)