MRCAL(1)

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

okay bestie, welcome to the mrcal corner of the manual. pull up a chair, grab a snack πŸ“


✨ NAME ✨

mrcal-show-projection-diff β€” visualize the difference in projection between N models


🌈 SYNOPSIS 🌈

$ mrcal-show-projection-diff before.cameramodel after.cameramodel
... a plot pops up showing how these two models differ in their projections

πŸ¦‹ DESCRIPTION πŸ¦‹

The whole operation of this tool is documented at

L<https://mrcal.secretsauce.net/differencing.html>

This tool visualizes the results of mrcal.projection_diff()

ngl this is one of the genuinely most useful things in the whole toolkit. It is often useful to compare the projection behavior of two camera models. For instance, one may want to validate a calibration by comparing the results of two different chessboard dances. Or one may want to evaluate the stability of the intrinsics in response to mechanical or thermal stresses. This tool makes these comparisons, and produces a visualization of the results. periodt πŸ’…

In the most common case we're given exactly 2 models to compare. We then display the projection difference as either a vector field or a heat map. If we're given more than 2 models, then a vector field isn't possible and we instead display as a heatmap the standard deviation of the differences between models 1..N and model0. (more models = more chaos = heatmap only, sorry babes)

The top-level operation of this tool:

  • Grid the imager - Unproject each point in the grid using one camera model - Apply a transformation to map this point from one camera's coord system to the other. How we obtain this transformation is described below - Project the transformed points to the other camera - Look at the resulting pixel difference in the reprojection

Several arguments control how we obtain the transformation. Top-level logic:

if --intrinsics-only:
    Rt10 = identity_Rt()
else:
    if --radius 0:
        Rt10 = relative_extrinsics(models)
    else:
        Rt10 = implied_Rt10__from_unprojections()

The details of how the comparison is computed, and the meaning of the arguments controlling this, are in the docstring of mrcal.projection_diff(). iykyk πŸ’œ


🌸 OPTIONS 🌸

πŸ’« POSITIONAL ARGUMENTS

models                Camera models to diff

πŸŽ€ OPTIONAL ARGUMENTS

-h, --help            show this help message and exit
--gridn GRIDN GRIDN   How densely we should sample the imager. By default we
                      use a 60x40 grid
--distance DISTANCE   Has an effect only without --intrinsics-only. The
                      projection difference varies depending on the range to
                      the observed world points, with the queried range set
                      in this argument. If omitted we look out to infinity.
                      We can also fit multiple distances at the same time by
                      passing them here in a comma-separated, whitespace-
                      less list. If multiple distances are given, we fit the
                      implied-by-the-intrinsics transformation using ALL the
                      distances, but we display the difference for the FIRST
                      distance given.
--intrinsics-only     If given, we evaluate the intrinsics of each lens in
                      isolation by assuming that the coordinate systems of
                      each camera line up exactly
--where WHERE WHERE   Center of the region of interest for this diff. Used
                      only without --intrinsics-only and without "--radius
                      0". It is usually impossible for the models to match
                      everywhere, but focusing on a particular area can work
                      better. The implied transformation will be fit to
                      match as large as possible an area centered on this
                      argument. If omitted, we will focus on the center of
                      the imager
--radius RADIUS       Radius of the region of interest. If ==0, we do NOT
                      fit an implied transformation at all, but use the
                      transformations in the models. If omitted or <0, we
                      use a "reasonable" value: the whole imager if we're
                      using uncertainties, or min(width,height)/6 if --no-
                      uncertainties. To fit with data across the whole
                      imager in either case, pass in a very large radius
--observations        If given, I show where the chessboard corners were
                      observed at calibration time. These should correspond
                      to the low-diff regions.
--valid-intrinsics-region
                      If given, I overlay the valid-intrinsics regions onto
                      the plot
--cbmax CBMAX         Maximum range of the colorbar
--title TITLE         Title string for the plot. Overrides the default
                      title. Exclusive with --extratitle
--extratitle EXTRATITLE
                      Additional string for the plot to append to the
                      default title. Exclusive with --title
--vectorfield         Plot the diff as a vector field instead of as a heat
                      map. The vector field contains more information
                      (magnitude AND direction), but is less clear at a
                      glance
--vectorscale VECTORSCALE
                      If plotting a vectorfield, scale all the vectors by
                      this factor. Useful to improve legibility if the
                      vectors are too small to see
--directions          If given, the plots are color-coded by the direction
                      of the error, instead of the magnitude
--no-uncertainties    Used only without --intrinsics-only and without "--
                      radius 0". By default we use the uncertainties in the
                      model to weigh the fit. This will focus the fit on the
                      confident region in the models without --where or
                      --radius. The computation will run faster with --no-
                      uncertainties, but the default --where and --radius
                      may need to be adjusted
--hardcopy HARDCOPY   Write the output to disk, instead of making an
                      interactive plot
--terminal TERMINAL   gnuplotlib terminal. The default is good almost
                      always, so most people don't need this option
--set SET             Extra 'set' directives to gnuplotlib. Can be given
                      multiple times
--unset UNSET         Extra 'unset' directives to gnuplotlib. Can be given
                      multiple times

ok bestie, here's the same list but in group-chat form so it actually sticks πŸ’– (every flag, every default, all of it, no cap):

  • models β€” the camera models you're diffing. give me them. πŸ‘‘
  • -h, --help β€” shows this help message and exits. the classic. 🫢
  • --gridn GRIDN GRIDN β€” how densely we should sample the imager. By default we use a 60x40 grid. more grid = more detail = slower, choose your fighter
  • --distance DISTANCE β€” has an effect only without --intrinsics-only. The projection difference varies depending on the range to the observed world points, with the queried range set in this argument. If omitted we look out to infinity. We can also fit multiple distances at the same time by passing them here in a comma-separated, whitespace-less list. If multiple distances are given, we fit the implied-by-the-intrinsics transformation using ALL the distances, but we display the difference for the FIRST distance given. (first one gets the spotlight, the rest are just backstage supporting the fit)
  • --intrinsics-only β€” if given, we evaluate the intrinsics of each lens in isolation by assuming that the coordinate systems of each camera line up exactly. ignoring extrinsics like they don't exist πŸ’…
  • --where WHERE WHERE β€” center of the region of interest for this diff. Used only without --intrinsics-only and without --radius 0. It is usually impossible for the models to match everywhere, but focusing on a particular area can work better. The implied transformation will be fit to match as large as possible an area centered on this argument. If omitted, we will focus on the center of the imager. (pick your fave spot and make it the main character)
  • --radius RADIUS β€” radius of the region of interest. If ==0, we do NOT fit an implied transformation at all, but use the transformations in the models. If omitted or <0, we use a "reasonable" value: the whole imager if we're using uncertainties, or min(width,height)/6 if --no-uncertainties. To fit with data across the whole imager in either case, pass in a very large radius. (zero means no fitting, negative/omitted means vibes-based auto-pick)
  • --observations β€” if given, I show where the chessboard corners were observed at calibration time. These should correspond to the low-diff regions. πŸŽ€
  • --valid-intrinsics-region β€” if given, I overlay the valid-intrinsics regions onto the plot. ✨
  • --cbmax CBMAX β€” maximum range of the colorbar. 🌈
  • --title TITLE β€” title string for the plot. Overrides the default title. Exclusive with --extratitle. it's giving custom branding
  • --extratitle EXTRATITLE β€” additional string for the plot to append to the default title. Exclusive with --title. (tag it onto the existing title instead of replacing it)
  • --vectorfield β€” plot the diff as a vector field instead of as a heat map. The vector field contains more information (magnitude AND direction), but is less clear at a glance. more info, more squinting, that's the trade
  • --vectorscale VECTORSCALE β€” if plotting a vectorfield, scale all the vectors by this factor. Useful to improve legibility if the vectors are too small to see. πŸ”₯
  • --directions β€” if given, the plots are color-coded by the direction of the error, instead of the magnitude. direction girlies rise
  • --no-uncertainties β€” used only without --intrinsics-only and without --radius 0. By default we use the uncertainties in the model to weigh the fit. This will focus the fit on the confident region in the models without --where or --radius. The computation will run faster with --no-uncertainties, but the default --where and --radius may need to be adjusted. (faster, but you might have to go tweak the defaults yourself)
  • --hardcopy HARDCOPY β€” write the output to disk, instead of making an interactive plot. πŸ’Ύ
  • --terminal TERMINAL β€” gnuplotlib terminal. The default is good almost always, so most people don't need this option. don't touch it unless you know why you're touching it
  • --set SET β€” extra 'set' directives to gnuplotlib. Can be given multiple times. πŸŽ€
  • --unset UNSET β€” extra 'unset' directives to gnuplotlib. Can be given multiple times. πŸŽ€

πŸ‘‘ 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, you ate that 🫢✨

this was mrcal version 2.5.2-4build1, dated 2026-03-20, and it's the MRCAL(1) manual page. go forth and diff your cameras, ily, bye πŸ’–πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from