MRCAL(1)

MRCAL(1) β€” mrcal: camera projection, calibration toolkit πŸ’–

okay so you found the manual page for mrcal-stereo, part of the mrcal toolkit (camera projection + calibration, it's giving very serious computer vision energy ✨). Sit down, hydrate, let's go. 🧚


πŸŽ€ NAME πŸŽ€

mrcal-stereo β€” stereo processing. that's it, that's the whole vibe. πŸ’…


πŸ¦‹ SYNOPSIS πŸ¦‹

lowkey the whole thing in one look:

$ mrcal-stereo                        \
   --az-fov-deg               90      \
   --el-fov-deg               70      \
   --pixels-per-deg           -0.5    \
   --disparity-range          0 100   \
   --sgbm-block-size          5       \
   --sgbm-p1                  600     \
   --sgbm-p2                  2400    \
   --sgbm-uniqueness-ratio    5       \
   --sgbm-disp12-max-diff     1       \
   --sgbm-speckle-window-size 200     \
   --sgbm-speckle-range       2       \
   --outdir /tmp                      \
   left.cameramodel right.cameramodel \
   left.jpg         right.jpg

Processing left.jpg and right.jpg
Wrote '/tmp/rectified0.cameramodel'
Wrote '/tmp/rectified1.cameramodel'
Wrote '/tmp/left-rectified.png'
Wrote '/tmp/right-rectified.png'
Wrote '/tmp/left-disparity.png'
Wrote '/tmp/left-range.png'

### To "manually" stereo-rectify a pair of images
$ mrcal-stereo          \
    --az-fov-deg 80     \
    --el-fov-deg 50     \
    --outdir /tmp       \
    left.cameramodel    \
    right.cameramodel
Wrote '/tmp/rectified0.cameramodel'
Wrote '/tmp/rectified1.cameramodel'

$ mrcal-reproject-image         \
    --outdir /tmp               \
    /tmp/left.cameramodel       \
    /tmp/rectified0.cameramodel \
    left.jpg
Wrote /tmp/left-reprojected.jpg

$ mrcal-reproject-image          \
    --outdir /tmp                \
    /tmp/right.cameramodel       \
    /tmp/rectified1.cameramodel  \
    right.jpg
Wrote /tmp/right-reprojected.jpg

$ mrcal-stereo                       \
    --already-rectified              \
    --outdir /tmp                    \
    /tmp/rectified[01].cameramodel   \
    /tmp/left-reprojected.jpg        \
    /tmp/right-reprojected.jpg

# This is the same as using mrcal-stereo to do all the work:
$ mrcal-stereo          \
    --az-fov-deg 80     \
    --el-fov-deg 50     \
    --outdir /tmp       \
    left.cameramodel    \
    right.cameramodel   \
    left.jpg            \
    right.jpg

πŸ’œ DESCRIPTION πŸ’œ

So here's the deal, bestie. You hand this tool a pair of calibrated cameras plus pairs of images that those cameras captured, and it runs the entire stereo processing sequence for you, top to bottom. The output? disparity images, range images, and a point cloud array. iconic, honestly. 🌈

The rectified system itself gets built with mrcal functions. For the actual stereo matching, right now the only option available is the OpenCV SGBM routine β€” more choices will show up eventually, we're just early to the party. πŸŽ‰

✨ the SGBM thing ✨

The commandline args that configure the SGBM matcher (all the --sgbm-... ones) map straight onto the corresponding OpenCV APIs. If you leave an --sgbm-... argument out, you just get whatever the defaults are in the cv2.StereoSGBM_create() call. And ngl? the cv2.StereoSGBM_create() defaults are usually terrible and produce a disparity map that isn't great. 😭 The --sgbm-... values up in the synopsis are a good starting point to get stereo that's actually usable. take the freebie. 🫢

🧚 the rectified system's axes 🧚

The rectified system is constructed with these axes:

  • x β€” from the origin of the first camera to the origin of the second camera (that's the baseline direction)
  • y β€” completes the system from x,z
  • z β€” the mean "forward" direction of the two input cameras, with the component parallel to the baseline subtracted off

🌸 the active window 🌸

The active window in this system is specified using a few parameters, and they refer to:

  • the "azimuth" (or "az") β€” the direction along the baseline: rectified x axis
  • the "elevation" (or "el") β€” the direction across the baseline: rectified y axis

The rectified field of view comes from the --az-fov-deg and --el-fov-deg arguments. rn there's no auto-detection logic, so you must pass these. Changing them is a "zoom" operation. πŸ”

Want to pan the stereo system? Pass --az0-deg and/or --el0-deg. Those set the center of the rectified images, and they're optional. 🎯

Finally, the resolution of the rectified images is given with --pixels-per-deg. Also optional β€” it defaults to the resolution of the first input image. If you want to scale the input resolution, pass a value <0. For instance, to generate rectified images at half the first-input-image resolution, pass --pixels-per-deg=-0.5. ⚠️ And here's the gotcha: Python's argparse has a problem with negative numbers, so "--pixels-per-deg -0.5" does not work. fr fr, use the =.

πŸ’€ not me learning about the argparse negative-number thing the hard way. use the equals sign. always.

πŸŽ€ input images πŸŽ€

The input images are specified by a pair of globs, so you can process a whole pile of images in a single call. Each glob gets expanded, the filenames get sorted, and the resulting lists of files are assumed to match up. (yes, assumed. it's trusting you. don't make it regret that. πŸ™ˆ)

🌈 modes of operation 🌈

There are several modes, and picking one is a whole vibe check:

  1. No images given β€” we compute the rectified system only, and write the models to disk.
  2. No --viz argument given β€” we compute the rectified system and the disparity, and we write all output as images on disk.
  3. --viz geometry β€” we compute the rectified system and display its geometry as a plot. No rectification is computed, the images aren't used, and they don't need to be passed in.
  4. --viz stereo β€” compute the rectified system and the disparity. We don't write anything to disk initially; instead we invoke an interactive visualization tool to display the results. This one requires pyFLTK (homepage: https://pyfltk.sourceforge.io) and GL_image_display (homepage: https://github.com/dkogan/GL_image_display).

πŸ‘‘ bulk mode, because of course πŸ‘‘

It is often desired to compute dense stereo for lots of images in bulk. To make that go faster, this tool supports the -j JOBS option. It works just like in Make: the work gets parallelized among JOBS simultaneous processes. Unlike make, though β€” and this is the important bit β€” the JOBS value must be specified. no sneaky defaults here. πŸ’…

✨ OPTIONS ✨

okay bestie, this is the part where we tell mrcal what to actually do πŸ’… every flag, every value, every default β€” no skips, no cap. let's get into it.

πŸŽ€ POSITIONAL ARGUMENTS πŸŽ€

  • models β€” the camera models representing the cameras used to capture the images. both intrinsics and extrinsics get used here, so yeah, they matter.
  • images β€” the image globs to use for the stereo. if you omit this, we only write out the rectified models. if you give it, you must give exactly two image globs. no more, no less, periodt.

🌸 OPTIONAL ARGUMENTS 🌸

  • -h, --help β€” show this help message and exit. classic.
  • --az-fov-deg AZ_FOV_DEG β€” the field of view in the azimuth direction, in degrees. there's no auto-detection at this time, so this argument is required (unless --already-rectified). like, you gotta tell it.
  • --el-fov-deg EL_FOV_DEG β€” the field of view in the elevation direction, in degrees. again, no auto-detection at this time, so this argument is required (unless --already-rectified).
  • --az0-deg AZ0_DEG β€” the azimuth center of the rectified images. "0" means "the horizontal center of the rectified system is the mean forward direction of the two cameras projected to lie perpendicular to the baseline". if omitted, we align the center of the rectified system with the center of the two cameras' views.
  • --el0-deg EL0_DEG β€” the elevation center of the rectified system. "0" means "the vertical center of the rectified system lies along the mean forward direction of the two cameras" defaults to 0.
  • --az-edge-margin-deg AZ_EDGE_MARGIN_DEG β€” the nearest the rectified view is allowed to approach az = -90 or az = +90. defaults to 10deg, for a maximum az field of view of 160deg. applies ONLY to LENSMODEL_LATLON rectification.
  • --pixels-per-deg PIXELS_PER_DEG β€” the resolution of the rectified images. this is either a whitespace-less, comma-separated list of two values (az,el) or a single value to be applied to both axes. if a resolution of >0 is requested, the value is used as is. if a resolution of <0 is requested, we use this as a scale factor on the resolution of the first input image. for instance, to downsample by a factor of 2, pass -0.5. by default, we use -1 for both axes: the resolution of the input image at the center of the rectified system.
  • --rectification {LENSMODEL_PINHOLE,LENSMODEL_LATLON} β€” the lens model to use for rectification. currently two models are supported: LENSMODEL_LATLON (the default) and LENSMODEL_PINHOLE. pinhole stereo works badly for wide lenses and suffers from varying angular resolution across the image. LENSMODEL_LATLON rectification uses a transverse equirectangular projection, and does not suffer from these effects. it is thus the recommended model. πŸ’―
  • --already-rectified β€” if given, assume the given models and images already represent a rectified system. this will be checked, and the models will be used as-is if the checks pass.
  • --equalization {clahe,fieldscale,stretch} β€” the equalization method to use for the input images. "fieldscale" requires mrcam to be installed, and can only operate on uint16 images. --equalization implies --force-grayscale.
  • --clahe β€” equivalent to "--equalization clahe".
  • --force-grayscale β€” if given, convert the images to grayscale prior to doing anything else with them. by default, read the images in their default format, and pass those possibly-color images to all the processing steps.
  • --viz {geometry,stereo} β€” if given, we visualize either the rectified geometry or the stereo results. if --viz geometry: we construct the rectified stereo system, but instead of continuing with the stereo processing, we render the geometry of the stereo world; the images are ignored in this mode. if --viz stereo: we launch an interactive graphical tool to examine the rectification and stereo matching results; the Fl_Gl_Image_Widget Python library must be available.
  • --axis-scale AXIS_SCALE β€” used if --viz geometry. scale for the camera axes. by default a reasonable default is chosen (see mrcal.show_geometry() for the logic).
  • --title TITLE β€” used if --viz geometry. title string for the plot.
  • --hardcopy HARDCOPY β€” used if --viz geometry. write the output to disk, instead of making an interactive plot. the output filename is given in the option.
  • --terminal TERMINAL β€” used if --viz geometry. the gnuplotlib terminal. the default is almost always right, so most people don't need this option.
  • --set SET β€” used if --viz geometry. extra 'set' directives to pass to gnuplotlib. may be given multiple times.
  • --unset UNSET β€” used if --viz geometry. extra 'unset' directives to pass to gnuplotlib. may be given multiple times.
  • --force, -f β€” by default existing files are not overwritten. pass --force to overwrite them without complaint. no drama.
  • --outdir OUTDIR β€” directory to write the output into. if omitted, we use the current directory.
  • --tag TAG β€” string to use in the output filenames. non-specific output filenames if omitted.
  • --disparity-range DISPARITY_RANGE DISPARITY_RANGE β€” the disparity limits to use in the search, in pixels. two integers are expected: MIN_DISPARITY MAX_DISPARITY. completely arbitrarily, we default to MIN_DISPARITY=0 and MAX_DISPARITY=100.
  • --valid-intrinsics-region β€” if given, annotate the image with its valid-intrinsics region. this will end up in the rectified images, and make it clear where successful matching shouldn't be expected.
  • --range-image-limits RANGE_IMAGE_LIMITS RANGE_IMAGE_LIMITS β€” the nearest,furthest range to encode in the range image. defaults to 1,1000, arbitrarily.
  • --stereo-matcher {SGBM,ELAS} β€” the stereo-matching method. by default we use the "SGBM" method from OpenCV. libelas isn't always available, and must be enabled at compile-time by setting USE_LIBELAS=1 during the build.
  • --sgbm-block-size SGBM_BLOCK_SIZE β€” a parameter for the OpenCV SGBM matcher. if omitted, 5 is used.
  • --sgbm-p1 SGBM_P1 β€” a parameter for the OpenCV SGBM matcher. if omitted, the OpenCV default is used.
  • --sgbm-p2 SGBM_P2 β€” a parameter for the OpenCV SGBM matcher. if omitted, the OpenCV default is used.
  • --sgbm-disp12-max-diff SGBM_DISP12_MAX_DIFF β€” a parameter for the OpenCV SGBM matcher. if omitted, the OpenCV default is used.
  • --sgbm-pre-filter-cap SGBM_PRE_FILTER_CAP β€” a parameter for the OpenCV SGBM matcher. if omitted, the OpenCV default is used.
  • --sgbm-uniqueness-ratio SGBM_UNIQUENESS_RATIO β€” a parameter for the OpenCV SGBM matcher. if omitted, the OpenCV default is used.
  • --sgbm-speckle-window-size SGBM_SPECKLE_WINDOW_SIZE β€” a parameter for the OpenCV SGBM matcher. if omitted, the OpenCV default is used.
  • --sgbm-speckle-range SGBM_SPECKLE_RANGE β€” a parameter for the OpenCV SGBM matcher. if omitted, the OpenCV default is used.
  • --sgbm-mode {SGBM,HH,HH4,SGBM_3WAY} β€” a parameter for the OpenCV SGBM matcher. must be one of ('SGBM','HH','HH4','SGBM_3WAY'). if omitted, the OpenCV default (SGBM) is used.
  • --write-point-cloud β€” if given, we write out the point cloud as a .ply file. each point is reported in the reference coordinate system, colored with the nearest-neighbor color of the camera0 image. this is disabled by default because this is potentially a very large file. the interactive button in the tool ALWAYS writes the point cloud.
  • --jobs, -j JOBS β€” parallelize the processing JOBS-ways. this is like Make, except you're required to explicitly specify a job count. this applies when processing multiple sets of images with the same set of models.
  • --verbose β€” report more diagnostics. this is dependent on the specific matcher being used. some matchers (SGBM) do not have any verbose diagnostics.

🌈 REPOSITORY 🌈

<https://www.github.com/dkogan/mrcal>

πŸ‘‘ AUTHOR πŸ‘‘

Dima Kogan, "<dima@secretsauce.net>"

Copyright (c) 2017-2023 California Institute of Technology ("Caltech"). U.S. Government sponsorship acknowledged. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License"); You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

and that's the whole page, bestie πŸ’… this was mrcal version 2.5.2-4build1, dated 2026-03-20, and the manual section is MRCAL(1). go forth and rectify something iconic 🫢✨

πŸ“¦ where this page comes from