lensfun
0.3.99.0
|
A modifier object contains optimized data required to rectify a image. More...
#include <lensfun.h>
Public Member Functions | |
lfModifier (const lfLens *lens, float imgfocal, float imgcrop, int imgwidth, int imgheight, lfPixelFormat pixel_format, bool reverse=false) | |
Create an empty image modifier object. More... | |
~lfModifier () | |
Modifier object destructor. | |
int | EnableDistortionCorrection (const lfLensCalibDistortion &lcd) |
Enable distortion correction. More... | |
int | EnableDistortionCorrection () |
Enable distortion correction. More... | |
int | EnableTCACorrection (const lfLensCalibTCA &lctca) |
Enable TCA correction. More... | |
int | EnableTCACorrection () |
Enable TCA correction. More... | |
int | EnableVignettingCorrection (const lfLensCalibVignetting &lcv) |
Enable vignetting correction. More... | |
int | EnableVignettingCorrection (float aperture, float distance) |
Enable vignetting correction. More... | |
int | EnableProjectionTransform (lfLensType target_projection) |
Enable projection transform. More... | |
int | EnableScaling (float scale) |
Enable image scaling. More... | |
int | EnablePerspectiveCorrection (float *x, float *y, int count, float d) |
Enable the perspective correction. More... | |
int | GetModFlags () |
Return the current set of LF_MODIFY_XXX flags. | |
float | GetAutoScale (bool reverse) |
Compute the automatic scale factor for the image. More... | |
bool | ApplyColorModification (void *pixels, float x, float y, int width, int height, int comp_role, int row_stride) const |
Image correction step 1: fix image colors. More... | |
bool | ApplyGeometryDistortion (float xu, float yu, int width, int height, float *res) const |
Image correction step 2: apply the transforms on a block of pixel coordinates. More... | |
bool | ApplySubpixelDistortion (float xu, float yu, int width, int height, float *res) const |
Image correction step 3: apply subpixel distortions. More... | |
bool | ApplySubpixelGeometryDistortion (float xu, float yu, int width, int height, float *res) const |
Apply stage 2 & 3 in one step. More... | |
A modifier object contains optimized data required to rectify a image.
The desired image modifications are added by the EnableXXX() member functions. Every image modification has a corresponding inverse function, e.g. the library allows both to correct lens distortions and to simulate lens characteristics.
The normal order of applying a lens correction on a image is:
This is the theoretical order. But in reality, when using this library, the order is reversed (see How the corrections work for an explanation):
This process is divided into three stages.
In the first stage, the colors of the image pixels are fixed (vignetting). You pass a pointer to your pixel data, and it will be modified in place.
Then, the distortions introduced by the lens are removed (distortion and geometry), perspective is corrected if desired, and an additional scaling factor is applied if required. This operation requires building new image in a new allocated buffer: you cannot modify the image in place, or bad things will happen. Note that Lensfun does not provide pixel interpolation routines. You have to implement the lookup in the original image yourself.
And finally, in the subpixel distortion stage, application corrects transversal chromatic aberrations. For every target pixel coordinate the modifier will return you three new coordinates: the first will tell you the coordinates of the red component, second of the green, and third of the blue component. This again requires copying the image, but you can use the same buffers as in stage two, just in reverse order.
Of course, you can skip some stages of the process, e.g. if you, for example, don't want to change a fisheye image to a rectilinear you can omit that step.
Obviously, when simulating lens distortions, the modification stages must be applied in reverse order. While the library takes care to reverse the steps which are grouped into a single stage, the application must apply the stages themselves in reverse order.
HOWEVER. Doing it in three stages is not memory efficient, and is prone to error accumulation because you have to interpolate pixels twice - once during stage 2 and once during stage 3. To avoid this, it is sensful to do stages 2 & 3 in one step. In this case the output R,G,B coordinates from stage 2, which treats the colour channels equally, are fed directly into stage 3, which will correct the R,G,B coordinates further. ApplySubpixelGeometryDistortion() does this in a convenient fashion.
lfModifier::lfModifier | ( | const lfLens * | lens, |
float | imgfocal, | ||
float | imgcrop, | ||
int | imgwidth, | ||
int | imgheight, | ||
lfPixelFormat | pixel_format, | ||
bool | reverse = false |
||
) |
Create an empty image modifier object.
Before using the returned object you must enable the desired kind of correction.
You must provide the original image width/height even if you plan to correct just a part of the image.
lens | Lens object with calibration data to be used for the modifications. |
imgcrop | The crop factor for the image to be processed. The distortion models will take this into account if lens models were measured on a camera with a different crop factor. |
imgwidth | The width of the image you want to correct. |
imgheight | The height of the image you want to correct. |
pixel_format | Pixel format of your image (bits per pixel component). |
reverse | If this parameter is true, a reverse transform will be prepared. That is, you take a undistorted image at input and convert it so that it will look as if it would be a shot made with lens. |
bool lfModifier::ApplyColorModification | ( | void * | pixels, |
float | x, | ||
float | y, | ||
int | width, | ||
int | height, | ||
int | comp_role, | ||
int | row_stride | ||
) | const |
Image correction step 1: fix image colors.
This currently is only vignetting transform.
pixels | This points to image pixels. The actual pixel format depends on both pixel_format and comp_role arguments. The results are stored in place in the same format. Warning: this array should be aligned at least on a 16-byte boundary. |
x | The X coordinate of the corner of the block. |
y | The Y coordinate of the corner of the block. |
width | The width of the image block in pixels. |
height | The height of the image block in pixels. |
comp_role | The role of every pixel component. This is a bitfield, made by one of the LF_CR_X macros which defines the roles of every pixel field. For example, LF_CR_4(RED,GREEN,BLUE,UNKNOWN) will define a RGBA (or RGBX) pixel format, and the UNKNOWN field will not be modified. |
row_stride | The size of a image row in bytes. This can be actually different from width * pixel_width as some image formats use funny things like alignments, filler bytes etc. |
bool lfModifier::ApplyGeometryDistortion | ( | float | xu, |
float | yu, | ||
int | width, | ||
int | height, | ||
float * | res | ||
) | const |
Image correction step 2: apply the transforms on a block of pixel coordinates.
The undistorted coordinates are computed for every pixel in a rectangular block: \((x_u, y_u), (x_u+1, y_u), \ldots, (x_u + \mathrm{width} - 1, y_u), (x_u, y_u + 1), \ldots, (x_u + \mathrm{width} - 1, y_u + \mathrm{height} - 1)\).
The corrected coordinates are put into the output buffer sequentially, X and Y values.
This routine has been designed to be safe to use in parallel from several threads.
xu | The undistorted X coordinate of the start of the block of pixels. |
yu | The undistorted Y coordinate of the start of the block of pixels. |
width | The width of the block in pixels. |
height | The height of the block in pixels. |
res | A pointer to an output array which receives the respective X and Y distorted coordinates for every pixel of the block. The size of this array must be at least width*height*2 elements. Warning: this array should be aligned at least on a 16-byte boundary. |
bool lfModifier::ApplySubpixelDistortion | ( | float | xu, |
float | yu, | ||
int | width, | ||
int | height, | ||
float * | res | ||
) | const |
Image correction step 3: apply subpixel distortions.
The undistorted R,G,B coordinates are computed for every pixel in a square block: \((x_u, y_u), (x_u+1, y_u), \ldots, (x_u + \mathrm{width} - 1, y_u), (x_u, y_u + 1), \ldots, (x_u + \mathrm{width} - 1, y_u + \mathrm{height} - 1)\).
Returns the corrected coordinates separately for R/G/B channels The resulting coordinates are put into the output buffer sequentially, X and Y values.
This routine has been designed to be safe to use in parallel from several threads.
xu | The undistorted X coordinate of the start of the block of pixels. |
yu | The undistorted Y coordinate of the start of the block of pixels. |
width | The width of the block in pixels. |
height | The height of the block in pixels. |
res | A pointer to an output array which receives the respective X and Y distorted coordinates of the red, green and blue channels for every pixel of the block. The size of this array must be at least width*height*2*3 elements. Warning: this array should be aligned at least on a 16-byte boundary. |
bool lfModifier::ApplySubpixelGeometryDistortion | ( | float | xu, |
float | yu, | ||
int | width, | ||
int | height, | ||
float * | res | ||
) | const |
Apply stage 2 & 3 in one step.
See the main comment to the lfModifier class. The undistorted (R, G, B) coordinates are computed for every pixel in a square block: \((x_u, y_u), (x_u+1, y_u), \ldots, (x_u + \mathrm{width} - 1, y_u), (x_u, y_u + 1), \ldots, (x_u + \mathrm{width} - 1, y_u + \mathrm{height} - 1)\).
Returns the corrected coordinates separately for R/G/B channels The resulting coordinates are put into the output buffer sequentially, X and Y values.
This routine has been designed to be safe to use in parallel from several threads.
xu | The undistorted X coordinate of the start of the block of pixels. |
yu | The undistorted Y coordinate of the start of the block of pixels. |
width | The width of the block in pixels. |
height | The height of the block in pixels. |
res | A pointer to an output array which receives the respective X and Y distorted coordinates for every pixel of the block. The size of this array must be at least width*height*2*3 elements. Warning: this array should be aligned at least on a 16-byte boundary. |
int lfModifier::EnableDistortionCorrection | ( | ) |
Enable distortion correction.
lens | Lens object to be used for the correction. |
focal | The focal length in mm at which the image was taken. |
int lfModifier::EnableDistortionCorrection | ( | const lfLensCalibDistortion & | lcd | ) |
Enable distortion correction.
lcd | Lens calibration data to be used for the correction. |
int lfModifier::EnablePerspectiveCorrection | ( | float * | x, |
float * | y, | ||
int | count, | ||
float | d | ||
) |
Enable the perspective correction.
Depending on the number of control points given, there are three possible modes:
4 control points: c0 and c1 define one vertical lines, c2 and c3 the other. The focal length defined in the creation of the modifier is used to get the proper aspect ratio.
6 control points: c0 to c3 like above. c4 and c5 define a horizontal line. The focal length is used to get the proper aspect ratio.
8 control points: c0 to c5 like above. c6 and c7 define a second horizontal line. The focal length is not used.
5 control points: They all must lie on an ellipse that is actually a rotated circle. If they lie in a clockwise ordering, the vertex is assumed to be above the ellipse centre in the image. If they lie in a counter-clockwise ordering, the vertex is assumed to be below the ellipse. The focal length is needed to find the proper vertex.
7 control points: c0 to c4 like above. c5 and c6 define a horizontal line which is used to rotate the final image nicely.
If the lines constructed from the first four control points for the 4, 6 and 8 points case (or the last two for the 7 points case) are more horizontal than vertical, in all of the above, "horizontal" and "vertical" need to be swapped.
All control points must be given as pixel coordinates in the original image. For best precision, anti-distortion should have been applied before taking the coordinates. Moreover, fisheye images must have been transformed into rectilinear of the same focal length. In contrast, cropping, rotating, shifting, or scaling must be switched off.
lens | Lens object to be used for the transform. |
focal | The focal length in mm at which the image was taken. |
x | The x coordinates of the control points. |
y | The y coordinates of the control points. |
count | The number of control points. |
d | This parameter is supposed to be offered to the user as a slider. It can take values from -1 to +1. 0 denotes the perfect correction. -1 is the unchanged image. +1 is an increase of the tilting angle by 25%. |
int lfModifier::EnableProjectionTransform | ( | lfLensType | target_projection | ) |
Enable projection transform.
lens | Lens object to be used for the transform. |
focal | The focal length in mm at which the image was taken. |
target_projection | The target projection type. |
int lfModifier::EnableScaling | ( | float | scale | ) |
Enable image scaling.
scale | Scale factor. |
int lfModifier::EnableTCACorrection | ( | ) |
Enable TCA correction.
lens | Lens object to be used for the correction. |
focal | The focal length in mm at which the image was taken. |
int lfModifier::EnableTCACorrection | ( | const lfLensCalibTCA & | lctca | ) |
Enable TCA correction.
lctca | Lens calibration data to be used for the correction. |
int lfModifier::EnableVignettingCorrection | ( | const lfLensCalibVignetting & | lcv | ) |
Enable vignetting correction.
lcv | Lens calibration data to be used for the correction. |
int lfModifier::EnableVignettingCorrection | ( | float | aperture, |
float | distance | ||
) |
Enable vignetting correction.
lens | Lens object to be used for the correction. |
focal | The focal length in mm at which the image was taken. |
aperture | The aperture (f-number) at which the image was taken. |
distance | The approximative focus distance in meters (distance > 0). |
float lfModifier::GetAutoScale | ( | bool | reverse | ) |
Compute the automatic scale factor for the image.
This expects that all coordinate distortion callbacks are already set up and working. The function will try at its best to find a scale value that will ensure that no pixels with coordinates out of range will get into the resulting image. But since this is an approximative method, the returned scale sometimes is a little less than the optimal scale (e.g. you can still get some black corners with some high-distortion cases).
reverse | If true, the reverse scaling factor is computed. |