Radiance fields¶
inro.nerf, documented module by module; the radiance field tutorial shows the workflow.
Fields¶
fields
¶
Radiance fields assembled from spatial, color and direction modules.
As in Instant-NGP, a spatial network predicts density logits and geometry features, and a color network combines those features with an encoded view direction. Holding the color network and the renderer fixed compares spatial representations directly.
SphericalHarmonicsEncoding
¶
Real spherical-harmonics encoding of unit directions.
Evaluates the bands l = 0, ..., degree - 1, so degree counts bands, as in
tiny-cuda-nn, and gives degree**2 features. degree=4 matches the
view-direction encoding of Instant-NGP.
Parameters:
-
degree(int, default:4) –Number of bands, an integer from 1 to 4.
Shape
- Input:
(..., 3)unit directions. - Output:
(..., degree**2).
Source code in inro/nerf/fields.py
IdentityEncoding
¶
Identity encoding of unit directions, as in FINER's NeRF network.
Shape
- Input:
(..., 3)unit directions. - Output:
(..., 3).
RadianceField
¶
RadianceField(density_net: ModuleSpec, color_net: ModuleSpec, *, geometry_features: int = 15, direction_encoding: ModuleSpec = 'sh', aabb: Tensor | Sequence[float] = (-1.0, -1.0, -1.0, 1.0, 1.0, 1.0), density_activation: Callable[[Tensor], Tensor] = trunc_exp, density_bias: float = 0.0)
Radiance field with separate density, color and direction modules.
The density network maps points to one density logit followed by geometry features,
and the color network maps geometry and direction features to RGB logits. This class
applies the density activation and the RGB sigmoid, so neither network should have
an output activation. Each module is a ModuleSpec: an instance,
a registry key, a class or a (key_or_class, kwargs) pair.
Parameters:
-
density_net(ModuleSpec) –Spatial network spec, without registry keys. A class receives
in_features=3andout_features=1 + geometry_features. Its inputs are coordinates in[-1, 1]. -
color_net(ModuleSpec) –Color network spec, with registry keys
"linear"and"mlp", returning three RGB logits. A class receives the input width andout_features=3. -
geometry_features(int, default:15) –Number of features passed to the color network, excluding density; at least 1.
-
direction_encoding(ModuleSpec, default:'sh') –Direction encoding spec, exposing
out_features, with registry keys"sh", degree-4 spherical harmonics as in Instant-NGP, and"identity", raw directions as in FINER. -
aabb(Tensor | Sequence[float], default:(-1.0, -1.0, -1.0, 1.0, 1.0, 1.0)) –Scene box
(xmin, ymin, zmin, xmax, ymax, zmax), kept in the state dict. World points map affinely to[-1, 1]and clamp at its boundary. -
density_activation(Callable[[Tensor], Tensor], default:trunc_exp) –Callable from density logits to nonnegative densities.
-
density_bias(float, default:0.0) –Offset added to the density logits before the activation.
Shape
- Input:
xand unitdirections, each(N, 3). - Output:
(rgb, sigma), RGB(N, 3)in[0, 1]and density(N,).
Examples:
>>> import inro
>>> field = RadianceField(
... (inro.InstantNGP, {"log2_hashmap_size": 14}),
... ("mlp", {"hidden_features": 64, "hidden_layers": 2}),
... )
>>> directions = torch.tensor([0.0, 0.0, 1.0]).expand(8, 3)
>>> rgb, sigma = field(torch.rand(8, 3), directions)
>>> rgb.shape, sigma.shape
(torch.Size([8, 3]), torch.Size([8]))
Source code in inro/nerf/fields.py
normalize_coordinates
¶
Map world coordinates from aabb to [-1, 1], clamping outliers.
Parameters:
-
x(Tensor) –World coordinates
(..., 3).
Source code in inro/nerf/fields.py
query_density
¶
Return densities (N,), skipping the color network for occupancy updates.
Parameters:
-
x(Tensor) –World coordinates
(N, 3); the batch may be empty.
Source code in inro/nerf/fields.py
forward
¶
Return RGB and density at world points seen along unit directions.
Parameters:
-
x(Tensor) –World coordinates
(N, 3); the batch may be empty. -
directions(Tensor) –Unit view directions
(N, 3).
Source code in inro/nerf/fields.py
trunc_exp
¶
Compute exp(x), clamping the input of its gradient to [-15, 15].
The clamp limits large density gradients early in training.
Parameters:
-
x(Tensor) –Input of any shape.
Renderers¶
renderers
¶
Occupancy-grid volume rendering with PyTorch and nerfacc backends.
Both backends march rays uniformly and composite emission and absorption. Ray directions
must be unit vectors, so that near and far bounds, step size and depth are world
distances. Call update_occupancy(field, step) before each training step.
Defaults follow torch-ngp's Blender recipe: the box [-1, 1]^3, near plane 0.2, a
step of sqrt(3) * extent / 1024, and a 128**3 density grid thresholded at
min(mean density, 10).
VolumeRenderer
¶
VolumeRenderer(aabb: Tensor | Sequence[float] = (-1.0, -1.0, -1.0, 1.0, 1.0, 1.0), near: float = 0.2, far: float | None = None, render_step_size: float | None = None, max_samples_per_ray: int | None = 1024, grid_resolution: int = 128, update_interval: int = 16, density_threshold: float = 10.0, ema_decay: float = 0.95, warmup_steps: int = 256)
Configuration and interface shared by occupancy-grid volume renderers.
Subclasses implement update_occupancy and forward. Build a backend
with create_renderer.
Parameters:
-
aabb(Tensor | Sequence[float], default:(-1.0, -1.0, -1.0, 1.0, 1.0, 1.0)) –Scene box
(xmin, ymin, zmin, xmax, ymax, zmax), left out of the state dict. Samples lie inside it. -
near(float, default:0.2) –Near-plane distance; marching starts at the box entry if that is farther.
-
far(float | None, default:None) –Far-plane distance;
Noneuses the box exit and stores infinity. -
render_step_size(float | None, default:None) –Marching step;
Noneusessqrt(3) * extent / 1024, withextentthe longest side of the box. -
max_samples_per_ray(int | None, default:1024) –Most occupied samples per ray, front to back;
Noneremoves the cap. Samples past it count as empty. It bounds the queries of a radiance field, not the PyTorch backend's marching buffers. -
grid_resolution(int, default:128) –Occupancy-grid cells per axis.
-
update_interval(int, default:16) –Training steps between occupancy updates.
-
density_threshold(float, default:10.0) –A cell is occupied when its density exceeds
min(grid mean, density_threshold). -
ema_decay(float, default:0.95) –Decay in the cell update
max(ema_decay * density, sigma). -
warmup_steps(int, default:256) –Steps during which an update covers every cell. Later updates sample
num_cells // 4uniform cells and up to that many occupied ones.
Attributes:
-
num_marching_steps–Steps that cover the box diagonal, the longest crossing of a ray:
ceil(diagonal / render_step_size), at least 1.
Source code in inro/nerf/renderers.py
update_occupancy
¶
Update the occupancy grid from field.query_density.
Call once per training step, before rendering.
Parameters:
-
field(Module) –Radiance field with the interface of
RadianceField. -
step(int) –Zero-based training step. The grid updates only when
step % update_interval == 0, all of it ifstep < warmup_steps.
Source code in inro/nerf/renderers.py
forward
¶
forward(field: Module, rays_o: Tensor, rays_d: Tensor, background: Tensor | None = None) -> dict[str, Tensor | int]
Render a batch of rays through a radiance field.
Parameters:
-
field(Module) –Radiance field with the interface of
RadianceField. -
rays_o(Tensor) –Ray origins
(N, 3). -
rays_d(Tensor) –Unit ray directions
(N, 3). -
background(Tensor | None, default:None) –Background color, shared
(3,)or per ray(N, 3);Noneuses white.
Returns:
-
dict[str, Tensor | int]–Dictionary with these keys.
rgb: Colors(N, 3).opacity: Summed compositing weights(N, 1).depth: Expected distance along the ray given a hit,(N, 1).num_samples: Number of samples composited.
Source code in inro/nerf/renderers.py
PyTorchRenderer
¶
Occupancy-grid volume renderer in pure PyTorch.
Marches each ray from box entry to exit at a fixed step and queries the radiance field at occupied samples only; skipped samples have zero density. The grid starts fully occupied, and it is in the state dict, as nerfacc's is, so a saved run renders with the grid it was scored with.
Parameters:
-
**kwargs(Any, default:{}) –Arguments of
VolumeRenderer.
Attributes:
-
density_grid–Running cell densities
(G, G, G), forG = grid_resolution. -
binaries–Boolean occupancy mask
(G, G, G), named after nerfacc's estimator.
Source code in inro/nerf/renderers.py
update_occupancy
¶
Update selected cells from one jittered point each and threshold the grid.
Queries run in chunks of 2**16, in training or eval mode.
Parameters:
-
field(Module) –Radiance field with the interface of
RadianceField. -
step(int) –Zero-based training step. The grid updates only when
step % update_interval == 0, all of it ifstep < warmup_steps.
Source code in inro/nerf/renderers.py
forward
¶
forward(field: Module, rays_o: Tensor, rays_d: Tensor, background: Tensor | None = None) -> dict[str, Tensor | int]
Render a batch of rays through a radiance field.
Allocates (N, num_marching_steps) marching buffers. Each sample is jittered
within its step in training mode and sits at its midpoint in eval mode.
Parameters:
-
field(Module) –Radiance field with the interface of
RadianceField. -
rays_o(Tensor) –Ray origins
(N, 3). -
rays_d(Tensor) –Unit ray directions
(N, 3). -
background(Tensor | None, default:None) –Background color, shared
(3,)or per ray(N, 3);Noneuses white.
Returns:
-
dict[str, Tensor | int]–Dictionary with
rgb,opacity,depthandnum_samples; seeVolumeRenderer.forward.
Source code in inro/nerf/renderers.py
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 | |
NerfAccRenderer
¶
Occupancy-grid volume renderer on nerfacc.OccGridEstimator and CUDA kernels.
Requires a working nerfacc extension; see is_nerfacc_available. Unlike
PyTorchRenderer, it renders only background until update_occupancy
runs, and sampling queries density to stop rays at transmittance below 1e-4,
before the sample cap applies. The state dict holds the grid under estimator..
Parameters:
-
**kwargs(Any, default:{}) –Arguments of
VolumeRenderer.
Source code in inro/nerf/renderers.py
update_occupancy
¶
Update the grid through OccGridEstimator.update_every_n_steps.
Queries all selected cells in one batch and requires training mode.
Parameters:
-
field(Module) –Radiance field with the interface of
RadianceField. -
step(int) –Zero-based training step. The grid updates only when
step % update_interval == 0, all of it ifstep < warmup_steps.
Source code in inro/nerf/renderers.py
forward
¶
forward(field: Module, rays_o: Tensor, rays_d: Tensor, background: Tensor | None = None) -> dict[str, Tensor | int]
Render a batch of rays through a radiance field.
Samples are stratified in training mode.
Parameters:
-
field(Module) –Radiance field with the interface of
RadianceField. -
rays_o(Tensor) –Ray origins
(N, 3). -
rays_d(Tensor) –Unit ray directions
(N, 3). -
background(Tensor | None, default:None) –Background color, shared
(3,)or per ray(N, 3);Noneuses white.
Returns:
-
dict[str, Tensor | int]–Dictionary with
rgb,opacity,depthandnum_samples; seeVolumeRenderer.forward.
Source code in inro/nerf/renderers.py
is_nerfacc_available
¶
Return whether nerfacc imports and its CUDA intersection kernel runs.
Some installations import but lack usable CUDA kernels, so this runs a small
ray_aabb_intersect.
Source code in inro/nerf/renderers.py
create_renderer
¶
create_renderer(backend: Literal['auto', 'pytorch', 'nerfacc'] = 'auto', **kwargs: Any) -> VolumeRenderer
Create a volume renderer, preferring a working nerfacc backend.
Parameters:
-
backend(Literal['auto', 'pytorch', 'nerfacc'], default:'auto') –"nerfacc"forNerfAccRenderer,"pytorch"forPyTorchRenderer, or"auto"for nerfacc whenis_nerfacc_availableand PyTorch otherwise. -
**kwargs(Any, default:{}) –Arguments of
VolumeRenderer.
Source code in inro/nerf/renderers.py
Datasets¶
datasets
¶
Posed RGBA images and ray sampling for NeRF synthetic (Blender) scenes.
Camera defaults follow torch-ngp's Blender recipe, as used by FINER:
scene_scale=0.8, bound=1 and near=0.2. Images load at full resolution;
downsample=4, skip=4 gives FINER's 25 training views at 200 x 200. Straight RGBA
keeps the background a rendering choice.
BlenderDataset
¶
BlenderDataset(root: str | PathLike[str], split: str = 'train', downsample: int = 1, skip: int = 1, scene_scale: float = 0.8, bound: float = 1.0, near: float = 0.2, background: float | Sequence[float] | Tensor = 1.0)
Blender scene with full-view access and random ray sampling.
dataset[i] returns one view's rays and RGBA, and sample_rays generates
rays from the stored poses, without a ray buffer. Poses keep Blender's convention,
with translations multiplied by scene_scale.
Parameters:
-
root(str | PathLike[str]) –Scene directory holding
transforms_{split}.jsonand the images. -
split(str, default:'train') –Split name, usually
"train","val"or"test". -
downsample(int, default:1) –Integer factor of resolution reduction by area averaging;
4gives 200 x 200 Blender images. -
skip(int, default:1) –Keep every
skip-th frame in file order;4selects 25 of the 100 training views, and evaluation uses1. -
scene_scale(float, default:0.8) –Scale applied to camera positions.
-
bound(float, default:1.0) –Half-extent of the scene box
[-bound, bound]^3. -
near(float, default:0.2) –Near-plane distance, stored for the renderer.
-
background(float | Sequence[float] | Tensor, default:1.0) –Background color in
[0, 1], a scalar or three channels. White is the standard for evaluating Blender scenes.
Attributes:
-
images–Straight RGBA images
(views, H, W, 4)in[0, 1]. -
poses–Camera-to-world poses
(views, 4, 4), with scaled translations. -
directions–Camera-frame ray directions
(H, W, 3), shared by all views. -
radius–Mean camera distance from the origin, after scaling.
-
focal–Focal length in pixels at the loaded resolution.
-
height–Image height
Hin pixels at the loaded resolution. -
width–Image width
Win pixels at the loaded resolution. -
far(float | None) –Far-plane distance, always
None: each ray ends at the box exit. -
aabb–Scene box
(xmin, ymin, zmin, xmax, ymax, zmax), frombound. -
background–Background color
(3,).
Source code in inro/nerf/datasets.py
to
¶
Move the stored tensors to a device in place and return this dataset.
Parameters:
-
device(str | device) –Device to move to; sampling then runs there, without transfers.
Source code in inro/nerf/datasets.py
composite
¶
Composite straight RGBA onto a background color.
Parameters:
-
rgba(Tensor) –Straight RGBA
(..., 4)in[0, 1]. -
background(Tensor | None, default:None) –Background color broadcastable to
(..., 3);Noneusesbackground.
Returns:
-
Tensor–Composited RGB
(..., 3).
Source code in inro/nerf/datasets.py
rays_for_pose
¶
Generate the rays of a full image for any camera pose.
Parameters:
-
c2w(Tensor) –Camera-to-world pose
(4, 4)or(3, 4), such as frompose_spherical, used as given: its translation must be scaled likeposes.
Returns:
-
tuple[Tensor, Tensor]–Ray origins and unit directions, each
(H, W, 3), on the device ofdirections.
Source code in inro/nerf/datasets.py
sample_rays
¶
Sample rays uniformly over all views and pixels, with replacement.
Parameters:
-
num_rays(int) –Number of rays
N. -
generator(Generator | None, default:None) –Random number generator, which may be on another device than the data, such as a CPU generator with data on CUDA.
Noneuses the global generator of the data's device.
Returns:
-
dict[str, Tensor]–Dictionary with
rays_oand unitrays_d, each(N, 3), andrgba, straight RGBA(N, 4), on the device ofimages.
Source code in inro/nerf/datasets.py
Training¶
training
¶
Per-scene NeRF training with random ray batches and mean squared error.
Adam keeps PyTorch's defaults, as in inro.train, so the learning rate is the one
setting to tune. As in torch-ngp, it decays exponentially to 0.1 * lr and each step
composites onto a fresh random background, while evaluation uses the dataset's. Results
and logging follow inro.train.
train
¶
train(field: Module, renderer: VolumeRenderer, train_dataset: BlenderDataset, eval_dataset: BlenderDataset | None = None, *, num_steps: int = 25000, num_rays: int = 4096, max_samples_per_ray: int | None = 1024, lr: float = 0.01, color_lr: float | None = None, weight_decay: float = 0.0, adam_betas: tuple[float, float] = (0.9, 0.999), adam_eps: float = 1e-08, random_background: bool = True, metrics: Mapping[str, Callable[[Tensor, Tensor], float]] | None = None, eval_interval: int | None = None, eval_indices: Sequence[int] | None = None, log_interval: int = 100, device: str | device | None = None, log_dir: str | PathLike[str] | None = None, seed: int = 0) -> dict[str, Any]
Fit a radiance field to one scene with random ray batches.
Each step updates the occupancy grid, renders num_rays rays and minimizes their
RGB mean squared error with Adam. A batch without occupied samples skips the
optimizer update and counts towards skipped_steps.
Parameters:
-
field(Module) –Radiance field, moved to
device. -
renderer(VolumeRenderer) –Volume renderer, moved to
device. -
train_dataset(BlenderDataset) –Posed images, moved to
devicein place. -
eval_dataset(BlenderDataset | None, default:None) –Held-out views;
Nonedisables evaluation. -
num_steps(int, default:25000) –Number of training steps.
-
num_rays(int, default:4096) –Rays sampled per step.
-
max_samples_per_ray(int | None, default:1024) –Most occupied samples per ray, front to back;
Noneremoves the cap. Overrides the renderer's setting. -
lr(float, default:0.01) –Initial learning rate of Adam, decayed exponentially to
0.1 * lr. -
color_lr(float | None, default:None) –Initial learning rate of
field.color_net, decayed alike;Noneuseslr. -
weight_decay(float, default:0.0) –Weight decay of Adam.
-
adam_betas(tuple[float, float], default:(0.9, 0.999)) –Moment decay rates of Adam.
-
adam_eps(float, default:1e-08) –Epsilon of Adam.
-
random_background(bool, default:True) –Whether to composite predictions and targets onto a fresh random color per ray, which discourages white haze in empty space. Otherwise, and always in evaluation, they use the dataset's background.
-
metrics(Mapping[str, Callable[[Tensor, Tensor], float]] | None, default:None) –Metrics passed to
evaluate;Noneuses PSNR, SSIM and LPIPS. -
eval_interval(int | None, default:None) –Steps between evaluations, the final step always included;
Noneevaluates only there and non-positive values never. -
eval_indices(Sequence[int] | None, default:None) –View indices to evaluate;
Noneevaluates all views. -
log_interval(int, default:100) –Steps between history records; final and evaluation steps are always recorded, and non-positive values record only those.
-
device(str | device | None, default:None) –Device to run on;
Noneuses CUDA when available, else the CPU. -
log_dir(str | PathLike[str] | None, default:None) –Directory for
log.txt(truncated first),log.json(appended), the finalcheckpoint.ptoffieldandrenderer.pt, the renderer's state with its occupancy grid;Nonewrites no files. -
seed(int, default:0) –Seed of the global PyTorch RNG, set after
fieldandrendererare built, so it does not control their initialization.
Returns:
-
dict[str, Any]–Dictionary with these keys.
config: Settings of the run, withskipped_stepsandpeak_memory, the most bytes a training step allocated beyond what the device already held (zero off CUDA).model_dict: Final state dict offield.history: One record per logged step, withstep,elapsed(seconds spent training so far),loss,psnr,num_samplesand, if the step evaluated, the mean held-out metrics undereval.
Source code in inro/nerf/training.py
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 | |
Evaluation and rendering¶
evaluation
¶
Rendering and held-out-view evaluation for radiance fields.
render_image
¶
render_image(field: Module, renderer: VolumeRenderer, rays_o: Tensor, rays_d: Tensor, *, background: Tensor | None = None, chunk_size: int | None = None) -> dict[str, Tensor]
Render rays in chunks, without gradients or stratified jitter.
Both modules enter eval mode, and return to training mode if field was training.
Parameters:
-
field(Module) –Radiance field; rendering runs on the device of its parameters.
-
renderer(VolumeRenderer) –Volume renderer on the device of
field, such as fromcreate_renderer. -
rays_o(Tensor) –Ray origins
(..., 3), such as(H, W, 3)for a view. -
rays_d(Tensor) –Unit ray directions
(..., 3). -
background(Tensor | None, default:None) –Background color
(3,);Noneuses white. -
chunk_size(int | None, default:None) –Rays per forward pass;
Nonefits2**19marching samples.
Returns:
-
dict[str, Tensor]–Dictionary with
rgb(..., 3),opacity(..., 1)anddepth(..., 1), with the leading dimensions ofrays_o.
Source code in inro/nerf/evaluation.py
evaluate
¶
evaluate(field: Module, renderer: VolumeRenderer, dataset: BlenderDataset, *, indices: Iterable[int] | None = None, metrics: Mapping[str, Callable[[Tensor, Tensor], float]] | None = None, chunk_size: int | None = None, return_images: bool = False) -> dict[str, Any]
Score held-out views, composited onto the dataset's background.
Renders are clamped to [0, 1] before scoring. Both modules enter eval mode, and
return to training mode if field was training.
Parameters:
-
field(Module) –Radiance field; rendering runs on the device of its parameters.
-
renderer(VolumeRenderer) –Volume renderer on the device of
field, such as fromcreate_renderer. -
dataset(BlenderDataset) –Posed RGBA images and the background they are composited onto.
-
indices(Iterable[int] | None, default:None) –View indices;
Noneevaluates all views. -
metrics(Mapping[str, Callable[[Tensor, Tensor], float]] | None, default:None) –Metrics by name, called as
fn(pred, target)on images(3, H, W)in[0, 1];Noneuses PSNR, SSIM and LPIPS (VGG). -
chunk_size(int | None, default:None) –Rays per forward pass;
Nonefits2**19marching samples. -
return_images(bool, default:False) –Whether to include the rendered images in the result.
Returns:
-
dict[str, Any]–Dictionary with these keys.
views: One record per view, withview(its index),duration(seconds of its render),peak_memory(the most bytes it allocated beyond what the device already held, zero off CUDA) and the metric values.mean: Average of these entries except the index, empty without views.images: Rendered CPU tensors(H, W, 3), ifreturn_images.
Source code in inro/nerf/evaluation.py
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | |
render_views
¶
render_views(field: Module, renderer: VolumeRenderer, dataset: BlenderDataset, poses: Sequence[Tensor], *, chunk_size: int | None = None) -> list[NDArray[uint8]]
Render camera poses, such as an orbit, as uint8 frames for a video.
Both modules enter eval mode, and return to training mode if field was training.
Parameters:
-
field(Module) –Radiance field; rendering runs on the device of its parameters.
-
renderer(VolumeRenderer) –Volume renderer on the device of
field, such as fromcreate_renderer. -
dataset(BlenderDataset) –Source of the camera intrinsics and the background color.
-
poses(Sequence[Tensor]) –Camera-to-world poses
(4, 4), such as frompose_spherical. -
chunk_size(int | None, default:None) –Rays per forward pass;
Nonefits2**19marching samples.
Returns:
-
list[NDArray[uint8]]–List of
uint8NumPy arrays(H, W, 3), one per pose.
Source code in inro/nerf/evaluation.py
Cameras¶
cameras
¶
Camera utilities for novel view synthesis.
Follows the Blender and OpenGL convention of the NeRF synthetic dataset: in the camera
frame, x points right, y up, and the camera looks along -z. A
camera-to-world pose is a (4, 4) matrix whose upper (3, 4) block is [R | t].
focal_from_fov
¶
Convert a full field of view to a focal length in pixels.
Parameters:
-
fov(float) –Full field of view in radians, such as
camera_angle_xof the Blender transforms files, which pairs with the image width. -
size(int) –Image size in pixels along the axis of
fov.
Source code in inro/nerf/cameras.py
generate_ray_directions
¶
generate_ray_directions(height: int, width: int, focal: float, cx: float | None = None, cy: float | None = None, *, device: str | device | None = None, dtype: dtype = float32) -> Tensor
Generate camera-frame ray directions (H, W, 3) through the pixel centers.
Directions have z = -1. They stay unnormalized, so that poses with the same
intrinsics can share them.
Parameters:
-
height(int) –Image height
Hin pixels. -
width(int) –Image width
Win pixels. -
focal(float) –Focal length in pixels.
-
cx(float | None, default:None) –Principal point x in pixels;
Noneuseswidth / 2. -
cy(float | None, default:None) –Principal point y in pixels;
Noneusesheight / 2. -
device(str | device | None, default:None) –Device to run on;
Noneuses the default device. -
dtype(dtype, default:float32) –Floating-point dtype of the directions.
Source code in inro/nerf/cameras.py
generate_rays
¶
Generate world-space rays from camera poses and camera-frame directions.
Parameters:
-
c2w(Tensor) –Camera-to-world poses
(..., 4, 4)or(..., 3, 4). -
directions(Tensor) –Camera-frame directions
(..., 3), whose leading dimensions broadcast with those ofc2w: one pose(4, 4)with a grid(H, W, 3), or poses(N, 4, 4)with directions(N, 3). -
normalize(bool, default:True) –Whether to normalize the directions, so that distances along a ray are in world units.
Returns:
-
tuple[Tensor, Tensor]–Ray origins and directions, each
(..., 3). The origins are an expanded view of the translations ofc2w.
Source code in inro/nerf/cameras.py
pose_spherical
¶
Compute a camera-to-world pose on a sphere, looking at the origin.
Uses the original NeRF convention, with world +z up. At theta = phi = 0 the
camera sits at (0, radius, 0).
Parameters:
-
theta(float) –Azimuth in degrees from
+y, clockwise about+zseen from above:90places the camera on+x. -
phi(float) –Pitch in degrees. Negative values place the camera above the
xyplane; the original NeRF render path uses-30. -
radius(float) –Distance from the origin.
Returns:
-
Tensor–Pose
(4, 4)on the default device, with the default dtype.