4
0
mirror of https://github.com/nerfstudio-project/nerfstudio.git synced 2026-11-10 18:17:31 +08:00

Misc viewer cleanup (#591)

* Misc viewer cleanup

* fix lint
This commit is contained in:
Matthew Tancik 2022-09-30 10:32:44 -07:00 committed by GitHub
parent 1bb0c88fb5
commit 5fac867502
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 7013 additions and 7142 deletions

View File

@ -34,7 +34,7 @@ conda install -c conda-forge pandoc
To ensure that you will be passing all tests and checks on github, you will need to run the following command:
```bash
python scripts/debugging/run_actions.py
ns-dev-test
```
This will perform the following checks and actions:

View File

@ -19,7 +19,7 @@ from rich.text import Text
class ItersPerSecColumn(ProgressColumn):
"""Renders human readable fps."""
"""Renders the iterations per second for a progress bar."""
def __init__(self, suffix="it/s") -> None:
super().__init__()

View File

@ -1,7 +1,7 @@
{
"name": "viewer",
"homepage": ".",
"version": "22-09-27-0",
"version": "22-09-30-0",
"private": true,
"dependencies": {
"@emotion/react": "^11.10.4",
@ -34,7 +34,6 @@
"redux": "^4.2.0",
"sass": "^1.54.8",
"socket.io-client": "^4.5.1",
"stats.js": "^0.17.0",
"three": "^0.142.0",
"three-wtm": "^1.0",
"websocket": "^1.0.34",

View File

@ -2,8 +2,6 @@ import React from 'react';
import { useDispatch } from 'react-redux';
import Button from '@mui/material/Button';
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
import GitHubIcon from '@mui/icons-material/GitHub';
import DescriptionRoundedIcon from '@mui/icons-material/DescriptionRounded';
import LandingModal from '../LandingModal';
@ -25,18 +23,8 @@ function getWebsocketEndpoint() {
}
export default function Banner() {
// const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const [anchorEl, setAnchorEl] = React.useState(0);
const dispatch = useDispatch();
const open = Boolean(anchorEl);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
let open_modal = true;
const websocket_url_from_argument = getWebsocketEndpoint();
if (websocket_url_from_argument !== undefined) {
@ -51,34 +39,6 @@ export default function Banner() {
return (
<div className="banner">
<LandingModal initial_state={open_modal} />
<Button
id="basic-button"
className="banner-button"
variant="outlined"
size="small"
aria-controls={open ? 'basic-menu' : undefined}
aria-haspopup="true"
aria-expanded={open ? 'true' : undefined}
onClick={handleClick}
>
Options
</Button>
<Menu
id="basic-menu"
anchorEl={anchorEl}
open={open}
onClose={handleClose}
MenuListProps={{
'aria-labelledby': 'basic-button',
}}
>
<MenuItem onClick={handleClose}>Load Training Config</MenuItem>
<MenuItem onClick={handleClose}>Export Training Config</MenuItem>
<MenuItem onClick={handleClose}>Dark Mode</MenuItem>
</Menu>
<Button className="banner-button" variant="outlined" size="small">
Download Desktop App
</Button>
<Button // button with view in ar icon
className="banner-button"
variant="outlined"

View File

@ -29,8 +29,7 @@ export default function StatusPanel(props: StatusPanelProps) {
const isWebrtcConnected = useSelector(
(state) => state.webrtcState.isConnected,
);
const eval_fps = useSelector((state) => state.renderingState.eval_fps);
const train_eta = useSelector((state) => state.renderingState.train_eta);
const eval_res = useSelector((state) => state.renderingState.eval_res);
const vis_train_ratio = useSelector(
(state) => state.renderingState.vis_train_ratio,
);
@ -109,10 +108,7 @@ export default function StatusPanel(props: StatusPanelProps) {
<WebSocketUrlField />
<div className="StatusPanel-metrics">
<div>
<b>Eval FPS:</b> {eval_fps}
</div>
<div>
<b>Train ETA:</b> {train_eta}
<b>Resolution:</b> {eval_res}
</div>
<div>
<b>Time Allocation:</b> {vis_train_ratio}

View File

@ -8,22 +8,12 @@ import { IconButton, ToggleButtonGroup, ToggleButton } from '@mui/material';
import OpenWithIcon from '@mui/icons-material/OpenWith';
import PublicOffSharpIcon from '@mui/icons-material/PublicOffSharp';
import PublicSharpIcon from '@mui/icons-material/PublicSharp';
import Stats from 'stats.js';
import SyncOutlinedIcon from '@mui/icons-material/SyncOutlined';
import WebRtcWindow from '../WebRtcWindow/WebRtcWindow';
import { WebSocketContext } from '../WebSocket/WebSocket';
const msgpack = require('msgpack-lite');
function createStats() {
const stats = new Stats();
stats.setMode(0);
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0';
stats.domElement.style.top = '0';
return stats;
}
function CameraToggle() {
const dispatch = useDispatch();
const camera_choice = useSelector(
@ -129,8 +119,6 @@ export default function ViewerWindow(props) {
// on change, update the camera and controls
sceneTree.metadata.camera = sceneTree.find_object(['Cameras', camera_choice]);
let stats = null;
const get_window_width = () => {
const width = myRef.current.clientWidth;
return width - (width % 2);
@ -208,14 +196,11 @@ export default function ViewerWindow(props) {
requestAnimationFrame(render);
renderer.render(scene, sceneTree.metadata.camera);
labelRenderer.render(scene, sceneTree.metadata.camera);
stats.update();
};
// start the three.js rendering loop
// when the DOM is ready
useEffect(() => {
stats = createStats();
myRef.current.append(stats.domElement);
myRef.current.append(renderer.domElement);
render();
}, []);

View File

@ -30,7 +30,7 @@ const initialState = {
colormap_choice: 'default', // the selected colormap
maxResolution: 1024,
targetTrainUtil: 0.9,
eval_fps: 'Paused',
eval_res: '?',
train_eta: 'Paused',
vis_train_ratio: 'Paused',
log_errors: '',

File diff suppressed because it is too large Load Diff

View File

@ -22,7 +22,7 @@ import sys
import threading
import time
from pathlib import Path
from typing import Any, Dict, Optional
from typing import Any, Dict, Optional, Tuple
import numpy as np
import torch
@ -464,22 +464,21 @@ class ViewerState:
image = selected_output.cpu().numpy()
self.vis.set_image(image)
def _update_viewer_stats(self, render_time: float, num_rays: int, image_height: int) -> None:
def _update_viewer_stats(self, render_time: float, num_rays: int, image_height: int, image_width: int) -> None:
"""Function that calculates and populates all the rendering statistics accordingly
Args:
render_time: total time spent rendering current view
num_rays: number of rays rendered
image_height: resolution of the current view
image_width: resolution of the current view
"""
writer.put_time(
name=EventName.VIS_RAYS_PER_SEC, duration=num_rays / render_time, step=self.step, avg_over_steps=True
)
is_training = self.vis["renderingState/isTraining"].read()
self.vis["renderingState/eval_res"].write(f"{image_height}x{image_width}px")
if is_training is None or is_training:
# process the current rendering fps
eval_fps = f"{1 / render_time:.2f} fps at {image_height} res"
self.vis["renderingState/eval_fps"].write(eval_fps)
# process remaining training ETA
self.vis["renderingState/train_eta"].write(GLOBAL_BUFFER["events"].get(EventName.ETA.value, "Starting"))
# process ratio time spent on vis vs train
@ -491,11 +490,10 @@ class ViewerState:
else:
self.vis["renderingState/vis_train_ratio"].write("Starting")
else:
self.vis["renderingState/eval_fps"].write("Paused")
self.vis["renderingState/train_eta"].write("Paused")
self.vis["renderingState/vis_train_ratio"].write("100% spent on viewer")
def _calculate_image_height(self, camera_object, is_training: bool) -> Optional[int]:
def _calculate_image_res(self, camera_object, is_training: bool) -> Optional[Tuple[int, int]]:
"""Calculate the maximum image height that can be rendered in the time budget
Args:
@ -503,6 +501,7 @@ class ViewerState:
is_training: whether or not we are training
Returns:
image_height: the maximum image height that can be rendered in the time budget
image_width: the maximum image width that can be rendered in the time budget
"""
max_resolution = self.vis["renderingState/maxResolution"].read()
if max_resolution:
@ -535,7 +534,7 @@ class ViewerState:
image_height = int(round(image_height, -1))
image_height = min(self.max_resolution, image_height)
return image_height
return image_height, int(image_height * aspect_ratio)
def _process_invalid_output(self, output_type: str) -> str:
"""Check to see whether we are in the corner case of RGB; if still invalid, throw error
@ -587,7 +586,7 @@ class ViewerState:
# Calculate camera pose and intrinsics
try:
image_height = self._calculate_image_height(camera_object, is_training)
image_height, image_width = self._calculate_image_res(camera_object, is_training)
except ZeroDivisionError as e:
self.vis["renderingState/log_errors"].write("Error: Screen too small; no rays intersecting scene.")
time.sleep(0.03) # sleep to allow buffer to reset
@ -649,4 +648,6 @@ class ViewerState:
if outputs is not None:
stuff_colors = graph.stuff_colors if hasattr(graph, "stuff_colors") else None
self._send_output_to_viewer(outputs, stuff_colors=stuff_colors)
self._update_viewer_stats(vis_t.duration, num_rays=len(camera_ray_bundle), image_height=image_height)
self._update_viewer_stats(
vis_t.duration, num_rays=len(camera_ray_bundle), image_height=image_height, image_width=image_width
)

View File

@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "nerfstudio"
version = "0.0.1"
version = "0.0.2"
description = "All-in-one repository for state-of-the-art NeRFs"
readme = "README.md"
license = { text="Apache 2.0"}