When you have a calibrated image and perform a geometric operation, the resulting image does not retain its camera calibration information. However, you can create an appropriately warped version of the camera calibration context and associate it with the uncalibrated geometrically transformed image.
McalWarp() allows you to apply a warping to the pixel-to-world mapping of a camera calibration context and use it to configure a specified camera calibration context. The newly configured context can then be associated with a similarly warped image. McalWarp() is meant to be used in conjunction with MimWarp(). As such, it takes the same warping parameter values used to transform the image. Therefore, McalWarp() can perform first-order polynomial warpings, perspective polynomial warpings, and custom warpings using LUTs.
If you want to apply a flip, resize, rotate, or translate operation on an image and wanted the destination image to be appropriately calibrated, you must perform the transformation of the image using MimWarp() instead of MimFlip(), MimResize(), MimRotate(), and MimTranslate(); you can then use McalWarp() followed by McalAssociate() to appropriately calibrate the transformed image. Note that, MimWarp() and McalWarp() use a matrix of coefficients (or LUTs) to describe its transformations. To generate the coefficients that represent the required transform, you can use MgenWarpParameter() to first generate the required transformation matrix (or LUTs) and subsequently call MimWarp() and McalWarp().
To perform a geometric operation on an image and preserve the camera calibration information, perform the following:
Call MimWarp() on the calibrated image to warp your image.
Allocate a new camera calibration context using McalAlloc() and specify the camera calibration mode best suited for the geometric transform.
Source camera calibration mode |
Destination's camera calibration mode after a linear geometric transform (translation, rotation, resize) |
Destination's camera calibration mode after a non-linear geometric transform (perspective, LUTs) |
Uniform |
Uniform |
Piecewise linear interpolation |
Piecewise linear interpolation |
Piecewise linear interpolation |
Piecewise linear interpolation |
Perspective transformation |
Perspective transformation |
Piecewise linear interpolation |
Tsai-based/Robotics |
Piecewise linear interpolation |
Piecewise linear interpolation |
Note that, the piecewise linear interpolation mode can accurately represent all geometric transforms and McalWarp() does not generate 3D-based camera calibration contexts.
Call McalWarp() as follows:
Set the original calibrated image as the source image for McalWarp(), and set the newly allocated camera calibration context as the destination.
Use the same matrix coefficients or LUTs used by MimWarp() for McalWarp(), and set the transformation type to M_WARP_LUT or M_WARP_POLYNOMIAL based on the warping applied to the image.
Associate the newly configured camera calibration context with the warped image of MimWarp().
When warping the pixel-to-world mapping of a camera calibration context, the destination camera calibration context need not be in the same camera calibration mode as the source context. McalWarp() approximates the equivalent calibration when converting from one mode to the other.
The following code snippet shows how to perform a rotation using MimWarp(). It generates the required transformation matrices for the rotation using MgenWarpParameter(). It then shows how to warp the pixel-to-world mapping of the existing camera calibration context and propagate the new camera calibration information to the warped image using McalWarp() and then McalAssociate() respectively.
// Generate the warping matrix to rotate the source image +90 degrees around its center.
// This is the composition of a translation to the source's center, a rotation, and then a
// translation from the destination's center.
MIL_DOUBLE SrcCenterX = 0.5*(SrcSizeX-1);
MIL_DOUBLE SrcCenterY = 0.5*(SrcSizeY-1);
MIL_DOUBLE DstCenterX = 0.5*(DstSizeX-1);
MIL_DOUBLE DstCenterY = 0.5*(DstSizeY-1);
MIL_ID WarpMatrixArrayBufId = MbufAlloc2d(SysId, 3, 3, 32+M_FLOAT, M_ARRAY, M_NULL);
MgenWarpParameter(M_NULL, WarpMatrixArrayBufId, M_NULL, M_WARP_POLYNOMIAL,
M_TRANSLATE, -SrcCenterX, -SrcCenterY);
MgenWarpParameter(WarpMatrixArrayBufId, WarpMatrixArrayBufId, M_NULL, M_WARP_POLYNOMIAL,
M_ROTATE, 90.0, M_NULL);
MgenWarpParameter(WarpMatrixArrayBufId, WarpMatrixArrayBufId, M_NULL, M_WARP_POLYNOMIAL,
M_TRANSLATE, DstCenterX, DstCenterY);
// Warp the image.
MimWarp(SrcImageBufId, DstImageBufId, WarpMatrixArrayBufId, M_NULL, M_WARP_POLYNOMIAL,
M_BILINEAR+M_OVERSCAN_CLEAR);
// Same as:
// MimRotate(SrcImageBufId, DstImageBufId, 90.0, M_DEFAULT, M_DEFAULT, M_DEFAULT,
// M_DEFAULT, M_BILINEAR+M_OVERSCAN_CLEAR);
// Warp the pixel-to-world mapping of the calibration context
// and associate the context to the warped image.
MIL_ID DstContextCalId = McalAlloc(SysId, M_LINEAR_INTERPOLATION, M_DEFAULT, M_NULL);
McalWarp(SrcImageBufId, DstContextCalId, WarpMatrixArrayBufId, M_NULL, 0.0, 0.0,
(MIL_DOUBLE)DstSizeX, (MIL_DOUBLE)DstSizeY, M_DEFAULT, M_DEFAULT, M_WARP_POLYNOMIAL,
M_DEFAULT);
if (McalInquire(DstContextCalId, M_CALIBRATION_STATUS, M_NULL) == M_CALIBRATED)
{
McalAssociate(DstContextCalId, DstImageBufId, M_DEFAULT);
}
else
{
MosPrintf(MIL_TEXT("Calibration warping has failed.\n"));
}