Gradient-based optimization (steady state)¶
mitransient’s integrators can be used to solve inverse problems just like in Mitsuba 3. Importantly, mitransient extends this idea into the transient domain, where the signal that you obtain from the scene is time-dependent.
This tutorial deals with one of the two forms of inverse rendering: backward inverse rendering, in the transient domain. Mathematically, consider \(\textbf{x}\) as your set of scene parameters (e.g. material properties, albedos…). Our transient path tracing algorithms are functions \(f\) that transform them into a time-resolved image \(\textbf{y}\). Given that we are in the transient domain:
The goal of the problem is to match time-resolved image \(\textbf{y}\) to an observation \(\textbf{y}^\ast\). Thus, you can define a loss function:
This tutorial has two variants: steady-state and transient. The first one assumes that \(\textbf{y}\) is steady-state i.e. there is no time dimension. The second one can handle time-dependent estimations \(\textbf{y}(t)\). This way, the temporal information could give extra information to the optimization if handled correctly.
With this formulation, backward mode differentiation allows you to compute \(\nabla_{\textbf{x}_i}L\) for a subset \(\textbf{x}_i \subseteq \textbf{x}\) of the scene parameters. As you will see, the backward mode is very useful to optimize scene parameters:
With a learning rate \(\eta\). If your goal is instead to generate visualizations of the effect of individual scene parameters over time, you should look at forward mode automatic differentiation in mitransient.
🚀 You will learn:
What is backward inverse rendering and how to use it for gradient-based optimization
How to compute gradients of scene parameters from the render
Set up an optimization with one of Mitsuba’s optimizers
Visualize and understand the results of the optimization
Importing mitransient¶
You need to use a Mitsuba variant that enables Automatic Differentiation (AD). Any *_ad_* variant will do. Common choices should be llvm_ad_rgb for CPU and cuda_ad_rgb for GPU.
[1]:
# If you have compiled Mitsuba 3 yourself, you will need to specify the path
# to the compilation folder
# import sys
# sys.path.insert(0, '<mitsuba-path>/mitsuba3/build/python')
import mitsuba as mi
# To set a variant, you need to have set it in the mitsuba.conf file
# https://mitsuba.readthedocs.io/en/latest/src/key_topics/variants.html
mi.set_variant('llvm_ad_rgb')
import mitransient as mitr
import drjit as dr
print('Using mitsuba version:', mi.__version__)
print('Using Dr.JIT version:', dr.__version__)
print('Using mitransient version:', mitr.__version__)
Using mitsuba version: 3.7.0
Using Dr.JIT version: 1.1.0
Using mitransient version: 1.2.0
Reference image¶
We render a reference image of the original scene that will later be used in the objective function for the optimization. Ideally, this reference image should expose very little noise as it will pertube optimization process otherwise. For best results, we should render it with an even larger sample count.
[2]:
scene = mi.load_file('cornell-box/cbox_volumetric.xml')
[3]:
image_ref, transient_ref = mi.render(scene, spp=128)
# Preview the reference image
mi.util.convert_to_bitmap(image_ref)
[3]:
[4]:
transient_ref_tonemap = mitr.vis.tonemap_transient(transient_ref)
mitr.vis.show_video(transient_ref_tonemap)