Remap applies a generic geometrical transformation to an image. Typical uses include:
Lens distortion correction.
User-defined border extension.
Conversion between different projections.
The algorithm can work on dense or sparse warp maps. A dense warp map stores the remapped position of all pixels in the output image, whereas a sparse map stores a subset of that. It's more efficient to process the latter than the former, but quality might decrease depending on how much distortion is applied by the mapping.
The example below shows the famous "Little Planet" (stereographic) projection applied to a equirectangular panorama image, where \(R\) is the planet radius.
The algorithm uses a user-provided VPIWarpMap that maps every pixel in the output image to the corresponding pixel in the input image. It supports dense and sparse mappings.
Mapping operation
The mapping operation is composed of two steps:
A dense map is generated by up-sampling the input sparse map using bi-quadratic interpolation.
The pixel in the input image corresponding to the control point in the output image is sampled using the user-provided interpolator.
When the corresponding source pixel falls outside image border, Remap will use the border extension to decide what pixel value to pick.
Warp grid definition
Warp grids can be of 3 types:
dense: provides maximum quality in exchange for some performance hit.
uniformly sparse: provides a balance between quality and speed. Useful when the distribution of details in the resulting image isn't known a priori.
non-uniformly sparse: Useful when distribution of details in the resulting image is known. This allows increased quality and performance by sampling less in areas with low detail, and sampling more densely in areas with more detail.
When defining a sparse map, the output image can be split into at most 16 regions (4 horizontally and 4 vertically), with different control point interval (density) in each row or column of regions. The interval spacing must be expressed in power-of-two number of pixels in between control points. There are some other restrictions in the grid layout. Please consult VPIWarpGrid for more information.
Non-uniform grid
To define a dense map, simply set up the warp grid to have just one region, and both horizontal and vertical spacing to 1.
C API functions
For list of limitations, constraints and backends that implements the algorithm, consult reference documentation of the following functions:
Create a identity warp map, i.e., all control points' position will match their position in the output image. Here the warp map is dense with same dimensions as input image.
warp = vpi.WarpMap(vpi.WarpGrid(input.size))
Interpret warp map coordinates as a numpy array. No copies are made. The numpy array has shape (H,W,2) and is a view of the warp map. The shape transposition to (2,W,H) is just to have the x and y coordinates in the arrays wx and wy respectively. This makes coordinates' manipulation easier and more efficient.
wx,wy = np.asarray(warp).transpose(2,1,0)
Generate a custom mapping suitable to render an equirectangular panorama with the "Little Planet" effect. A similar approach is also taken when performing lens distortion correction for a lens whose distortion model doesn't match the ones provided by VPI. See Lens Distortion Correction for more details.
Generate a custom mapping suitable to render an equirectangular panorama as a little planet. vpiWarpMapGenerateIdentity will fill the warp map with an identity mapping, i.e., all control points' position will match their position in the output image. Once this is done, the code loops through all control points and using the output coordinate, calculates the corresponding coordinate in the input image. This approach is also taken when performing lens distortion correction for a lens whose distortion model doesn't match the ones provided by VPI. See Lens Distortion Correction for more details.