Examples
Automated Lens Design
Optimize a multi-element lens for improved imaging performance using gradient descent on surface parameters.
import torch
from deeplens import GeoLens
# Load a starting lens design
lens = GeoLens(filename="datasets/lenses/cellphone/cellphone80deg.json")
# Set which parameters to optimize (curvatures, thicknesses, etc.)
lens.set_target_fov(fov=80)
lens.prepare_optimization(lr=1e-4)
optimizer = torch.optim.Adam(lens.parameters(), lr=1e-4)
for step in range(200):
optimizer.zero_grad()
# Compute RMS spot size across field angles
loss = lens.loss_rms()
loss.backward()
optimizer.step()
if step % 50 == 0:
print(f"Step {step}: RMS spot loss = {loss.item():.4f}")
# Visualize the optimized lens
lens.draw2d()
End-to-End Camera Design
Jointly optimize lens optics and a neural reconstruction network:
import torch
from deeplens import GeoLens, Camera
from deeplens.sensor import RGBSensor
from deeplens.network import NAFNet
# Build the camera pipeline
lens = GeoLens(filename="datasets/lenses/cellphone/cellphone80deg.json")
sensor = RGBSensor(res=(512, 512))
network = NAFNet(in_chan=3, out_chan=3)
camera = Camera(lens=lens, sensor=sensor)
# Optimizers for optics and network separately
opt_lens = torch.optim.Adam(lens.parameters(), lr=1e-4)
opt_net = torch.optim.Adam(network.parameters(), lr=1e-4)
for step in range(500):
opt_lens.zero_grad()
opt_net.zero_grad()
# Forward through the full pipeline
img_gt = ... # ground truth image (1, 3, H, W)
img_degraded = camera.render(img_gt, depth=10000.0)
img_restored = network(img_degraded)
loss = torch.nn.functional.l1_loss(img_restored, img_gt)
loss.backward()
opt_lens.step()
opt_net.step()
Image Simulation
Simulate a photograph captured by a specific lens + sensor combination:
import torchvision
from deeplens import GeoLens
from deeplens.sensor import RGBSensor
# Load lens and sensor
lens = GeoLens(filename="datasets/lenses/cellphone/cellphone80deg.json")
sensor = RGBSensor(res=(1920, 1080))
# Load an image
img = torchvision.io.read_image("datasets/images/example.png").float() / 255.0
img = img.unsqueeze(0)
# Render through lens (applies spatially-varying PSF)
img_lens = lens.render(img, depth=10000.0)
# Apply sensor pipeline (noise + ISP)
img_bayer = sensor.linrgb2bayer(img_lens)
img_out = sensor.forward(img_bayer, iso=800)
Hybrid Lens Design
Design a lens that combines refractive optics with a diffractive optical element:
from deeplens import GeoLens, HybridLens
# Load the refractive part
geolens = GeoLens(filename="datasets/lenses/cellphone/cellphone80deg.json")
# Create hybrid lens (adds DOE at the aperture plane)
lens = HybridLens(geolens=geolens, doe_res=1024)
# Compute PSF (coherent ray tracing + ASM propagation)
psf = lens.psf(point=[0.0, 0.0, -10000.0], ks=128, wvln=0.589)
# Access the refractive lens properties through geolens attribute
print(f"Focal length: {lens.geolens.foclen:.2f} mm")