1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
|
#+TITLE: mrcal C API
#+OPTIONS: toc:t
Internally, the [[file:python-api.org][Python functions]] use the mrcal C API. Only core functionality is
available in the C API (the Python API can do some stuff that the C API cannot),
but with time more and more stuff will be transitioned to a C-internal
representation. Today, end-to-end dense stereo processing in C is possible.
The C API consists of several headers:
- [[https://www.github.com/dkogan/mrcal/blob/master/basic-geometry.h][=basic-geometry.h=]]: /very/ simple geometry structures
- [[https://www.github.com/dkogan/mrcal/blob/master/poseutils.h][=poseutils.h=]]: pose and geometry functions
- [[https://www.github.com/dkogan/mrcal/blob/master/triangulation.h][=triangulation.h=]]: triangulation routines
- [[https://www.github.com/dkogan/mrcal/blob/master/mrcal.h][=mrcal.h=]]: lens models, projections, optimization
Most usages would simply =#include <mrcal.h>=, and this would include all the
headers. This is a C (not C++) library, so [[https://en.wikipedia.org/wiki/X_Macro][X macros]] are used in several places
for templating.
mrcal is a research project, so the capabilities and focus are still evolving.
Thus, the interfaces, /especially/ those in the C API are not yet stable. I do
try to maintain stability, but this is not fully possible, especially in the
higher-level APIs (=mrcal_optimize()= and =mrcal_optimizer_callback()=). For
now, assume that each major release breaks both the API and the ABI. The
migration notes for each release are described in the [[file:versions.org][relevant release notes]].
If you use the C APIs, shoot me an email to let me know, and I'll keep you in
mind when making API updates.
The best documentation for the C interfaces is the comments in the headers. I
don't want to write up anything complete and detailed until I'm sure the
interfaces are stable. The available functions are broken down into categories,
and described in a bit more detail here.
* Geometry structures
We have 3 structures in [[https://www.github.com/dkogan/mrcal/blob/master/basic-geometry.h][=basic-geometry.h=]]:
- =mrcal_point2_t=: a vector containing 2 double-precision floating-point
values. The elements can be accessed individually as =.x= and =.y= or as an
array =.xy[]=
- =mrcal_point3_t=: exactly like =mrcal_point2_t=, but 3-dimensional. A vector
containing 3 double-precision floating-point values. The elements can be
accessed individually as =.x= and =.y= and =.z= or as an array =.xyz[]=
- =mrcal_pose_t=: an unconstrained [[file:conventions.org::#pose-representation][6-DOF pose]]. Contains two sub-structures:
- =mrcal_point3_t r=: a [[https://en.wikipedia.org/wiki/Axis%E2%80%93angle_representation#Rotation_vector][Rodrigues rotation]]
- =mrcal_point3_t t=: a translation
Trivial mathematical operations are defined for these types:
- =double mrcal_point3_inner(const mrcal_point3_t a, const mrcal_point3_t b)=
- =double mrcal_point3_norm2(const mrcal_point3_t a)=
- =double mrcal_point3_mag (const mrcal_point3_t a)=
- =mrcal_point3_t mrcal_point3_add (const mrcal_point3_t a, const mrcal_point3_t b)=
- =mrcal_point3_t mrcal_point3_sub (const mrcal_point3_t a, const mrcal_point3_t b)=
- =mrcal_point3_t mrcal_point3_scale(const mrcal_point3_t a, const double s)=
- =mrcal_point3_t mrcal_point3_cross(const mrcal_point3_t a, const mrcal_point3_t b)=
And similar for =mrcal_point2_t=, except there's no =mrcal_point2_cross()=
And trivial printing operations are defined:
- =mrcal_point2_print(p)=
- =mrcal_point3_print(p)=
- =mrcal_Rt_print(Rt)=
- =mrcal_rt_print(rt)=
* Geometry functions
A number of utility functions are defined in [[https://www.github.com/dkogan/mrcal/blob/master/poseutils.h][=poseutils.h=]]. Each routine has two
forms:
- A =mrcal_..._full()= function that supports a non-contiguous memory layout for
each input and output
- A convenience =mrcal_...()= macro that wraps =mrcal_..._full()=, and expects
contiguous data. This has many fewer arguments, and is easier to call
Each data argument (input or output) has several items in the argument list:
- =double* xxx=: a pointer to the first element in the array
- =int xxx_stride0=, =int xxx_stride1=, ...: the strides, one per dimension
The strides are given in bytes, and work as expected. For a (for instance)
3-dimensional =xxx=, the element at =xxx[i,j,k]= would be accessible as
#+begin_src c
*(double*) &((char*)xxx)[ i*xxx_stride0 +
j*xxx_stride1 +
k*xxx_stride2 ]
#+end_src
These all have direct Python bindings. For instance the Python
[[file:mrcal-python-api-reference.html#-rt_from_Rt][=mrcal.rt_from_Rt()=]] function wraps =mrcal_rt_from_Rt()= C function.
There are also functions to solve the [[https://en.wikipedia.org/wiki/Orthogonal_Procrustes_problem][Orthogonal Procrustes Problem]]:
- =mrcal_align_procrustes_points_Rt01()=
- =mrcal_align_procrustes_vectors_R01()=
The [[https://www.github.com/dkogan/mrcal/blob/master/poseutils.h][=poseutils.h=]] header serves as the listing of available functions.
* Lens models
The lens model structures are defined here:
- =mrcal_lensmodel_type_t=: an enum decribing the lens model /type/. No
[[file:lensmodels.org::#representation][configuration]] is stored here.
- =mrcal_lensmodel_t=: a lens model type /and/ the [[file:lensmodels.org::#representation][configuration]] parameters. The
configuration lives in a =union= supporting all the known lens models
- =mrcal_lensmodel_metadata_t=: some [[file:lensmodels.org::#representation][metadata that decribes a model type]]. These
are inherent properties of a particular model type; answers questions like:
Can this model project behind the camera? Does it have an [[file:lensmodels.org::#core][intrinsics core]]?
Does it have gradients implemented?
The Python API describes a lens model with a [[file:lensmodels.org::#representation][string that contains the model type
and the configuration]], while the C API stores the same information in a
=mrcal_lensmodel_t=.
* Camera models
:PROPERTIES:
:CUSTOM_ID: cameramodel-in-c
:END:
We can also represent a full camera model in C. This is a lens model with a pose
and imager dimension: the full set of things in a [[file:cameramodels.org][=.cameramodel= file]]. The
definitions appear in [[https://www.github.com/dkogan/mrcal/blob/master/types.h][=mrcal/types.h=]]:
#+begin_src c
typedef struct
{
double rt_cam_ref[6];
unsigned int imagersize[2];
mrcal_lensmodel_t lensmodel;
double intrinsics[0];
} mrcal_cameramodel_VOID_t;
typedef union
{
double rt_cam_ref[6];
unsigned int imagersize[2];
mrcal_lensmodel_t lensmodel;
double intrinsics[4];
} mrcal_cameramodel_LENSMODEL_LATLON_t;
...
#+end_src
Note that =mrcal_cameramodel_VOID_t.intrinsics= has size 0 because the size of this
array depends on the specific lens model being used, and is unknown at compile
time.
So it is an error to define this on the stack. *Do not do this*:
#+begin_src c
void f(void)
{
mrcal_cameramodel_VOID_t model; // ERROR
}
#+end_src
If you need to define a known-at-compile-time model on the stack you can use the
[[https://github.com/dkogan/mrcal/blob/88e4c1df1c8cf535516719c5d4257ef49c9df1da/mrcal-types.h#L338][lensmodel-specific cameramodel types]]:
#+begin_src c
void f(void)
{
mrcal_cameramodel_LENSMODEL_OPENCV8_t model; // OK
}
#+end_src
This only exists for models that have a constant number of parameters; notably
there is no =mrcal_cameramodel_LENSMODEL_SPLINED_STEREOGRAPHIC_t=. When reading
a model from disk, mrcal dynamically allocates the right amount of memory, and
returns a =mrcal_cameramodel_VOID_t*=.
* Projections
The fundamental functions for projection and unprojection are defined here.
=mrcal_project()= is the main routine that implements the "forward" direction,
and is available for every camera model. This function can return gradients in
respect to the coordinates of the point being projected and/or in respect to the
intrinsics vector.
=mrcal_unproject()= is the reverse direction, and is implemented as a numerical
optimization to reverse the projection operation. Naturally, this is much slower
than =mrcal_project()=. Since =mrcal_unproject()= is implemented with a
nonlinear optimization, it has no gradient reporting. The Python
[[file:mrcal-python-api-reference.html#-unproject][=mrcal.unproject()=]] routine is higher-level, and it /does/ report gradients.
The gradients of the forward =mrcal_project()= operation are used in this
nonlinear optimization, so models that have no projection gradients defined do
not support =mrcal_unproject()=. The Python [[file:mrcal-python-api-reference.html#-unproject][=mrcal.unproject()=]] routine still
makes this work, using numerical differences for the projection gradients.
Simple, special-case lens models have their own projection and unprojection
functions defined:
#+begin_src c
void mrcal_project_pinhole(...);
void mrcal_unproject_pinhole(...);
void mrcal_project_stereographic(...);
void mrcal_unproject_stereographic(...);
void mrcal_project_lonlat(...);
void mrcal_unproject_lonlat(...);
void mrcal_project_latlon(...);
void mrcal_unproject_latlon(...);
#+end_src
These functions do the same thing as the general =mrcal_project()= and
=mrcal_unproject()= functions, but work much faster.
* Layout of the measurement and state vectors
The [[file:formulation.org][optimization routine]] tries to minimize the 2-norm of the measurement vector
$\vec x$ by moving around the state vector $\vec b$.
We select which parts of the optimization problem we're solving by setting bits
in the =mrcal_problem_selections_t= structure. This defines
- Which elements of the optimization vector are locked-down, and which are given
to the optimizer to adjust
- Whether we apply [[file:index.org::#Regularization][regularization]] to stabilize the solution
- Whether the chessboard should be assumed flat, or if we should optimize
[[file:formulation.org::#board-deformation][deformation]] factors
Thus the state vector may contain any of
- The lens parameters
- The geometry of the cameras
- The geometry of the observed chessboards and discrete points
- The [[file:formulation.org::#board-deformation][chessboard shape]]
The measurement vector may contain
- The errors in observations of the chessboards
- The errors in observations of discrete points
- The penalties in the solved point positions
- The [[file:formulation.org::#Regularization][regularization]] terms
Given =mrcal_problem_selections_t= and a vector $\vec b$ or $\vec x$, it is
useful to know where specific quantities lie inside those vectors. Here we have
4 sets of functions to answer such questions:
- =int mrcal_state_index_THING()=: Returns the index in the state vector $\vec
b$ where the contiguous block of values describing the THING begins. THING is
any of
- intrinsics
- extrinsics
- frames
- points
- calobject_warp
If we're not optimizing the THING, return <0
- =int mrcal_num_states_THING()=: Returns the number of values in the contiguous
block in the state vector $\vec b$ that describe the given THING. THING is any
of
- intrinsics
- extrinsics
- frames
- points
- calobject_warp
- =int mrcal_measurement_index_THING()=: Returns the index in the measurement
vector $\vec x$ where the contiguous block of values describing the THING
begins. THING is any of
- boards
- points
- regularization
- =int mrcal_num_measurements_THING()=: Returns the number of values in the
contiguous block in the measurement vector $\vec x$ that describe the given
THING. THING is any of
- boards
- points
- regularization
* State packing
The optimization routine works in the [[file:formulation.org::#state-packing][space of scaled parameters]], and several
functions are available to pack/unpack the state vector $\vec b$:
#+begin_src c
void mrcal_pack_solver_state_vector(...);
void mrcal_unpack_solver_state_vector(...);
#+end_src
* Optimization
The mrcal [[file:formulation.org][optimization routines]] are defined in [[https://www.github.com/dkogan/mrcal/blob/master/mrcal.h][=mrcal.h=]]. There are two primary
functions, each accessing a /lot/ of functionality, and taking /many/ arguments.
At this time, the prototypes will likely change in each release of mrcal, so try
not to rely on these being stable.
- =mrcal_optimize()= is the entry point to the optimization routine. This
function ingests the state, runs the optimization, and returns the optimal
state in the same variables. The optimization routine tries out different
values of the state vector by calling an optimization callback function to
evaluate each one.
- =mrcal_optimizer_callback()= provides access to the optimization callback
function standalone, /without/ being wrapped into the optimization loop
** Helper structures
This is correct as of mrcal 2.1. It may change in future releases.
We define some structures to organize the input to these functions. Each
observation has a =mrcal_camera_index_t= to identify the observing camera:
#+begin_src c
// Used to specify which camera is making an observation. The "intrinsics" index
// is used to identify a specific camera, while the "extrinsics" index is used
// to locate a camera in space. If I have a camera that is moving over time, the
// intrinsics index will remain the same, while the extrinsics index will change
typedef struct
{
// indexes the intrinsics array
int intrinsics;
// indexes the extrinsics array. -1 means "at coordinate system reference"
int extrinsics;
} mrcal_camera_index_t;
#+end_src
When solving a vanilla calibration problem, we have a set of stationary cameras
observing a moving scene. By convention, in such a problem we set the reference
coordinate system to camera 0, so that camera has no extrinsics. So in a vanilla
calibration problem =mrcal_camera_index_t.intrinsics= will be in $[0,
N_\mathrm{cameras})$ and =mrcal_camera_index_t.extrinsics= will always be
=mrcal_camera_index_t.intrinsics - 1=.
When solving a vanilla structure-from-motion problem, we have a set of moving
cameras observing a stationary scene. Here =mrcal_camera_index_t.intrinsics=
would be in $[0, N_\mathrm{cameras})$ and =mrcal_camera_index_t.extrinsics=
would be specify the camera pose, unrelated to
=mrcal_camera_index_t.intrinsics=.
These are the limiting cases; anything in-between is allowed.
A board observation is defined by a =mrcal_observation_board_t=:
#+begin_src c
// An observation of a calibration board. Each "observation" is ONE camera
// observing a board
typedef struct
{
// which camera is making this observation
mrcal_camera_index_t icam;
// indexes the "frames" array to select the pose of the calibration object
// being observed
int iframe;
} mrcal_observation_board_t;
#+end_src
And an observation of a discrete point is defined by a
=mrcal_observation_point_t=:
#+begin_src c
// An observation of a discrete point. Each "observation" is ONE camera
// observing a single point in space
typedef struct
{
// which camera is making this observation
mrcal_camera_index_t icam;
// indexes the "points" array to select the position of the point being
// observed
int i_point;
// Observed pixel coordinates. This works just like elements of
// observations_board_pool:
//
// .x, .y are the pixel observations
// .z is the weight of the observation. Most of the weights are expected to
// be 1.0. Less precise observations have lower weights.
// .z<0 indicates that this is an outlier. This is respected on
// input
//
// Unlike observations_board_pool, outlier rejection is NOT YET IMPLEMENTED
// for points, so outlier points will NOT be found and reported on output in
// .z<0
mrcal_point3_t px;
} mrcal_observation_point_t;
#+end_src
Note that the details of the handling of discrete points may change in the
future.
We have =mrcal_problem_constants_t= to define some details of the optimization
problem. These are similar to =mrcal_problem_selections_t=, but consist of
numerical values, rather than just bits. Currently this structure contains valid
ranges for interpretation of discrete points. These may change in the future.
#+begin_src c
// Constants used in a mrcal optimization. This is similar to
// mrcal_problem_selections_t, but contains numerical values rather than just
// bits
typedef struct
{
// The min,max distance of an observed discrete point from its observing
// camera. Any observation of a point outside this range will be penalized to
// encourage the optimizer to move the point into the acceptable range from the camera
double point_min_range, point_max_range;
} mrcal_problem_constants_t;
#+end_src
The optimization function returns most of its output in the same memory as its
input variables. A few metrics that don't belong there are returned in a
separate =mrcal_stats_t= structure:
#+begin_src c
// This structure is returned by the optimizer, and contains some statistics
// about the optimization
typedef struct
{
// generated by an X-macro
/* The RMS error of the optimized fit at the optimum. Generally the residual */
/* vector x contains error values for each element of q, so N observed pixels */
/* produce 2N measurements: len(x) = 2*N. And the RMS error is */
/* sqrt( norm2(x) / N ) */
double rms_reproj_error__pixels;
/* How many pixel observations were thrown out as outliers. Each pixel */
/* observation produces two measurements. Note that this INCLUDES any */
/* outliers that were passed-in at the start */
int Noutliers_board;
} mrcal_stats_t;
#+end_src
This contains some statistics describing the discovered optimal solution.
* Camera model reading/writing
:PROPERTIES:
:CUSTOM_ID: cameramodel-io-in-c
:END:
Simple interfaces for reading/writing [[file:cameramodels.org][=.cameramodel=]] data from C is available:
#+begin_src c
//// These allocate memory for the model; the caller MUST
//// mrcal_free_cameramodel(&model) when done. Return NULL on error
//
// if len>0, the string doesn't need to be 0-terminated. If len<=0, the end of
// the buffer IS indicated by a '\0' byte
mrcal_cameramodel_VOID_t* mrcal_read_cameramodel_string(const char* string,
const int len);
mrcal_cameramodel_VOID_t* mrcal_read_cameramodel_file (const char* filename);
void mrcal_free_cameramodel(mrcal_cameramodel_VOID_t** cameramodel);
//// These read the model into a preallocated buffer *model. The given buffer is
//// big-enough for a model with *Nintrinsics_max intrinsics. Return true on
//// success. On failure, return false. If the error was a too-small
//// Nintrinsics_max, a big-enough value will be reported in *Nintrinsics_max.
//// Otherwise *Nintrinsics_max will be <= 0.
//
// if len>0, the string doesn't need to be 0-terminated. If len<=0, the end of
// the buffer IS indicated by a '\0' byte
bool mrcal_read_cameramodel_string_into(// out
mrcal_cameramodel_VOID_t* model,
// in,out
int* Nintrinsics_max,
// in
const char* string,
const int len);
bool mrcal_read_cameramodel_file_into (// out
mrcal_cameramodel_VOID_t* model,
// in,out
int* Nintrinsics_max,
// in
const char* filename);
bool mrcal_write_cameramodel_file(const char* filename,
const mrcal_cameramodel_VOID_t* cameramodel);
#+end_src
This reads and write the [[#cameramodel-in-c][=mrcal_cameramodel_VOID_t= structures]]. Only the
=.cameramodel= file format is supported by these C functions. The Python API
supports more formats.
* Images
mrcal defines simple image types in [[https://www.github.com/dkogan/mrcal/blob/master/image.h][=mrcal/image.h=]]:
- =mrcal_image_int8_t=
- =mrcal_image_uint8_t=
- =mrcal_image_int16_t=
- =mrcal_image_uint16_t=
- =mrcal_image_int32_t=
- =mrcal_image_uint32_t=
- =mrcal_image_int64_t=
- =mrcal_image_uint64_t=
- =mrcal_image_float_t=
- =mrcal_image_double_t=
- =mrcal_image_bgr_t=
- =mrcal_image_void_t=
These are the basic not-necessarily-contiguous arrays. The =void= type is meant
to be used to accept arguments to functions that can operate on multiple types.
The =bgr= type is used for color images:
#+begin_src c
typedef struct { uint8_t bgr[3]; } mrcal_bgr_t;
#+end_src
Simple accessor and manipulation functions are available for each of these
types (except =void=; replacing each =T= below):
#+begin_src c
T* mrcal_image_T_at(mrcal_image_T_t* image, int x, int y);
const T* mrcal_image_T_at_const(const mrcal_image_T_t* image, int x, int y);
mrcal_image_T_t mrcal_image_T_crop(mrcal_image_T_t* image,
int x0, int y0,
int w, int h);
#+end_src
And for =uint8_t=, =uint16_t= and =mrcal_bgr_t= we can also read and write image
files:
#+begin_src c
bool mrcal_image_T_save (const char* filename, const mrcal_image_T_t* image);
bool mrcal_image_T_load( mrcal_image_T_t* image, const char* filename);
#+end_src
These use libraries for their core functionality, and are here for convenience.
These aren't interesting, or better than any other functions you may have
already; if you already have an image read/write implementation, use it. The
declarations are in [[https://www.github.com/dkogan/mrcal/blob/master/image.h][=mrcal/image.h=]], and the documentation lives there.
* Heat maps
mrcal can produce a colored visualization of any of the image types defined
above:
#+begin_src c
bool
mrcal_apply_color_map_T(
mrcal_image_bgr_t* out,
const mrcal_image_T_t* in,
/* If true, I set in_min/in_max from the */
/* min/max of the input data */
const bool auto_min,
const bool auto_max,
/* If true, I implement gnuplot's default 7,5,15 mapping. */
/* This is a reasonable default choice. */
/* function_red/green/blue are ignored if true */
const bool auto_function,
/* min/max input values to use if not */
/* auto_min/auto_max */
T in_min, /* will map to 0 */
T in_max, /* will map to 255 */
/* The color mappings to use. If !auto_function */
int function_red,
int function_green,
int function_blue);
#+end_src
* Dense stereo
:PROPERTIES:
:CUSTOM_ID: dense-stereo-in-c
:END:
A number of dense stereo routines are available. These make it possible to
implement a full mrcal dense stereo pipeline in C; an [[https://github.com/dkogan/mrcal/blob/master/doc/examples/dense-stereo-demo/dense-stereo-demo.cc][example is provided]]. The
available functions are declared in [[https://www.github.com/dkogan/mrcal/blob/master/stereo.h][=stereo.h=]]:
- =mrcal_rectified_resolution()= computes the resolution of the rectified system
from the resolution of the input. Usually =mrcal_rectified_system()= does this
internally, and there's no reason to call it directly. The Python wrapper is
[[file:mrcal-python-api-reference.html#-rectified_resolution][=mrcal.rectified_resolution()=]], and further documentation is in its docstring
- =mrcal_rectified_system2()= computes the geometry of the rectified system. The
Python wrapper is [[file:mrcal-python-api-reference.html#-rectified_system][=mrcal.rectified_system()=]], and further documentation is in
its docstring.
- =mrcal_rectification_maps()= computes the image transformation maps used to
compute the rectified images. To apply the maps, and actually remap the
images, [[https://docs.opencv.org/4.6.0/da/d54/group__imgproc__transform.html#gab75ef31ce5cdfb5c44b6da5f3b908ea4][the OpenCV =cv::remap()= function]] can be used. The Python wrapper is
[[file:mrcal-python-api-reference.html#-rectification_maps][=mrcal.rectification_maps()=]], and further documentation is in its docstring
- =mrcal_stereo_range_sparse()=, =mrcal_stereo_range_dense()= compute ranges
from disparities. The former function converts a set of discrete disparity
values, while the latter function processes a whole disparity image
* Triangulation
A number of triangulation routines are available in [[https://www.github.com/dkogan/mrcal/blob/master/triangulation.h][=triangulation.h=]]. These
estimate the position of the 3D point that produced a given pair of
observations.
* Sensor topology
=mrcal_traverse_sensor_links()= is available to compute the best path through a
graph of sensors, trying to maximize the common observations between each
successive pair of sensors in the path. This is used in the calibration seeding
routine to initialize a solve where every sensor's observations don't overlap
with every other sensor's observations.
* Heap routines
The [[https://www.github.com/dkogan/mrcal/blob/master/heap.h][=heap.h=]] header provides a simple min-priority-queue implementation. This
exposes the STL code in a C API. This is for the most part an internal
implementation detail of =mrcal_traverse_sensor_links()=, but could potentially
be useful somewhere on its own, so I'm exposing it here
* Python utilities
=mrcal_cameramodel_converter()= is a "converter" function that can be used with
=O&= conversions in [[https://docs.python.org/3/c-api/arg.html#c.PyArg_ParseTupleAndKeywords][=PyArg_ParseTupleAndKeywords()=]] calls. Can interpret either
path strings or [[file:mrcal-python-api-reference.html#cameramodel][=mrcal.cameramodel=]] objects as =mrcal_cameramodel_VOID_t= C
structures. Useful for writing Python extension modules for C code that uses
=mrcal_cameramodel_VOID_t=. This allocates memory on success. Call
=free(*model)= when done
|