Lens Calibration#
Overview#
Lens-distortion API schemas let a camera reproduce measured camera intrinsics and distortion. ovrtx supports OpenCV pinhole and fisheye calibration, lookup-table-based generalized projection, and omni-directional stereo.
When you apply one of these schemas, its calibration parameters drive
projection instead of focalLength and the aperture attributes. Depth of
field still uses focalLength, focusDistance, and fStop.
Three camera views of the same scene showing three different lens calibration schemata. Clockwise from top-left: OmniLensDistortionOpenCvPinholeAPI, OmniLensDistortionOpenCvFisheyeAPI, OmniLensDistortionOmniDirectionalStereoAPI#
To fit calibration parameters from checkerboard photographs, run Python: Camera calibration. The example includes the photographs, an OpenCV calibration script and output checks.
Creating A Calibrated Camera#
Apply one lens-distortion API schema to a Camera prim. The following
examples create the same OpenCV pinhole calibration.
#usda 1.0
def Camera "Camera" (
prepend apiSchemas = ["OmniLensDistortionOpenCvPinholeAPI"]
)
{
token omni:lensdistortion:model = "opencvPinhole"
float omni:lensdistortion:opencvPinhole:cx = 1024
float omni:lensdistortion:opencvPinhole:cy = 512
float omni:lensdistortion:opencvPinhole:fx = 900
float omni:lensdistortion:opencvPinhole:fy = 800
int2 omni:lensdistortion:opencvPinhole:imageSize = (2048, 1024)
float omni:lensdistortion:opencvPinhole:k1 = 0
float omni:lensdistortion:opencvPinhole:k2 = 0
float omni:lensdistortion:opencvPinhole:p1 = 0
float omni:lensdistortion:opencvPinhole:p2 = 0
}
from pxr import Gf, UsdGeom
prim = UsdGeom.Camera.Define(stage, "/Camera").GetPrim()
prim.ApplyAPI("OmniLensDistortionOpenCvPinholeAPI")
prim.GetAttribute("omni:lensdistortion:model").Set("opencvPinhole")
prim.GetAttribute("omni:lensdistortion:opencvPinhole:imageSize").Set(Gf.Vec2i(2048, 1024))
for name, value in {
"fx": 900.0,
"fy": 800.0,
"cx": 1024.0,
"cy": 512.0,
"k1": 0.0,
"k2": 0.0,
"p1": 0.0,
"p2": 0.0,
}.items():
prim.GetAttribute(f"omni:lensdistortion:opencvPinhole:{name}").Set(value)
See Python: Camera Lens Calibration for a runnable example.
Available Schemas#
Applied API schema |
Purpose |
|---|---|
|
Uses OpenCV pinhole projection with radial, tangential, and thin-prism coefficients. |
|
Uses OpenCV fisheye projection with four radial coefficients. |
|
Defines projection with ray-direction and ray-position textures. |
|
Renders one eye of a 360-degree stereo projection. |
|
Preserves calibration data that uses the NVIDIA f-theta model. |
|
Preserves calibration data that uses the Kannala-Brandt K3 model. |
|
Preserves calibration data that uses the radial-tangent thin-prism model. |
For new calibrated cameras, prefer the OpenCV, LUT, or omni-directional stereo schemas. Use the compatibility schemas when preserving existing calibration data.
OpenCV Pinhole#
USD declaration |
Description |
|---|---|
|
Selects OpenCV pinhole projection. |
|
Calibration resolution in pixels. |
|
Horizontal focal length in calibration pixels. |
|
Vertical focal length in calibration pixels. |
|
Horizontal principal point in calibration pixels. |
|
Vertical principal point in calibration pixels. |
|
Radial coefficient. |
|
Radial coefficient. |
|
Radial coefficient. |
|
Radial coefficient. |
|
Radial coefficient. |
|
Radial coefficient. |
|
Tangential coefficient. |
|
Tangential coefficient. |
|
Thin-prism coefficient. |
|
Thin-prism coefficient. |
|
Thin-prism coefficient. |
|
Thin-prism coefficient. |
OpenCV pinhole projection with radial and tangential distortion.#
OpenCV Fisheye#
USD declaration |
Description |
|---|---|
|
Selects OpenCV fisheye projection. |
|
Calibration resolution in pixels. |
|
Horizontal focal length in calibration pixels. |
|
Vertical focal length in calibration pixels. |
|
Horizontal principal point in calibration pixels. |
|
Vertical principal point in calibration pixels. |
|
Radial coefficient. |
|
Radial coefficient. |
|
Radial coefficient. |
|
Radial coefficient. |
The fisheye k1 default is nonzero, so applying the schema without authoring
coefficients introduces some distortion. Author all four coefficients for a
measured calibration; the calibration script does this automatically.
OpenCV fisheye projection using four equidistant distortion coefficients.#
imageSize makes an OpenCV calibration independent of output resolution.
When the RenderProduct resolution differs, ovrtx scales fx, fy, cx,
and cy to the output resolution.
Generalized Projection#
OmniLensDistortionLutAPI defines non-parametric projection with two
floating-point textures.
USD declaration |
Description |
|---|---|
|
Selects lookup-table projection. |
|
Calibrated sensor width. |
|
Calibrated sensor height. |
|
Optical center in calibrated sensor coordinates. |
|
Maps normalized image-plane positions to normalized camera-space ray directions stored in RGB. |
|
Inverse map from camera-space ray directions to normalized image-plane positions stored in RG. Directions index the texture using octahedral encoding after negating their Z component. |
Both lookup textures must have the same aspect ratio. Until both textures are
available, the camera renders as a pinhole camera. The textures define the
projection; nominalWidth, nominalHeight and opticalCenter do not
reshape the texture-based projection.
Warning
Low-resolution lookup textures can produce artifacts at larger output resolutions.
Omni-Directional Stereo#
OmniLensDistortionOmniDirectionalStereoAPI configures one eye of a
360-degree stereo camera. Use separate left- and right-eye cameras. Each eye
produces an equirectangular panorama covering 360° horizontally and 180°
vertically. Use a 2:1 output resolution for equal angular sampling along both
axes.
Each ray starts at an eye position offset sideways from the camera center by half the interpupillary distance. This offset rotates with the ray’s azimuth, so the eye positions follow the viewing direction around the panorama.
USD declaration |
Description |
|---|---|
|
Selects omni-directional stereo projection. |
|
Selects the left eye when true and the right eye when false. |
|
Eye separation in meters. |
A 1024 by 512 single-eye omni-directional stereo panorama.#
Calibration resolution versus output resolution#
imageSize makes an OpenCV calibration independent of the output
resolution, for the pinhole and the fisheye schema alike. Set it to the
resolution of the images the calibration was solved from and author fx,
fy, cx and cy in pixels of those images. When the RenderProduct’s
resolution differs from imageSize, the renderer scales the four values to
the output resolution, so the rendered field of view is the one you
calibrated; if the aspect ratio differs as well, the horizontal field of view
is kept and the vertical one is cropped or extended to fill the output.