The Flat-field correction (FFC) is a method used to correct:
The goal is to correct the pixels of the captured (raw) images in such a way that when a uniform background is captured by the system (camera & lens), the resulting output image is uniform.
This correction is achieved by applying the following operation to each pixel of the raw image:
CorrectedPixel = (RawPixel - Offset) * Gain
where both coefficients
OffsetandGainare specific values for each pixel.
The evaluation of the coefficients Offset and
Gain requires a calibration
procedure explained in the next paragraph.
The calibration procedure to compute the coefficients is done in two steps:
Dark image acquisition
A dark image is acquired1 by the system. This is typically achieved by covering the lens with the cap. The captured image represents the dark current of the sensors, and is considered as a fixed bias that we want to eliminate when acquiring images in normal conditions. This correction is called dark-frame subtraction.
CorrectedPixel = RawPixel - DarkPixel
For each pixel, the DarkPixel value corresponds to the
Offset in the above FFC formula.
Flat image acquisition
A flat image is acquired2 by the system. For example by capturing a flat (uniform) background, not too bright to avoid saturation and not too dark.
From dark and flat acquisitions, we have enough data to compute the
Gain value of the FFC formula.
For this we define CorrectedPixel as the pixel value we
consider to be correct for the flat image. Let’s set this value as the
average pixel value of the flat image (average(Flat)),
corrected3 by the average of the dark image
(average(Flat)). In the FFC formula
terms, this gives:
average(Flat) - average(Dark) = (FlatPixel - DarkPixel) * Gain
This leads to the Gain value
Gain = (average(Flat) - average(Dark)) / (FlatPixel - DarkPixel)
The same computation is repeated (width *
height) times, to cover all pixels of both flat and dark
images. This results in a specific correction for each pixel of the
image.
Note: this calibration procedure must be redone if any part of the system is changed, including the camera unit, lighting or optics equipment.
For color pixel formats, we have several ways of computing the value
of average(Flat). In all cases, the Gain
computation is repeated (width * height *
componentsPerPixel) times to cover all pixel components,
which results in specific corrections for each pixel component of the
image.
I.e. in RGB:
average(Flat[Red]) for computing the
Gain values of Red components;average(Flat[Green]) for computing the
Gain values of Green components;average(Flat[Blue]) for computing the
Gain values of Blue components.I.e. in RGB, using
average(average(Flat[Red]), average(Flat[Green]), average(Flat[Blue]))
for computing the Gain values of Red,
Green and Blue components.
This way of computing the average (i.e. over the pixel components) results in FFC coefficients that also correct the balance between components. Therefore, depending on the quality of the uniform background used to acquire the flat image, the FFC can effectively perform a white balance correction.
Some cameras have a built-in FFC module while other cameras do not implement this feature. The devices without that functionality can however be corrected by the FFC core of the Coaxlink card4.
The FFC core of the Coaxlink firmware corrects the pixels
directly coming from the camera by applying the FFC formula
using the coefficients (Offset and Gain)
corresponding to their locations in the image. Because the correction
happens at a very early stage in the Coaxlink pixel processing chain, the other
pixel processing functions such as RedBlueSwap,
LUT, and Bayer Decoding are performed on
corrected pixels.
The coefficients calculated in the calibration procedure can be loaded into the Coaxlink card, provided they are encoded as follows:
Offset and Gain values for one pixel
component are packed together into a 16-bit little-endian value:
Gain is encoded in UQ2.8
on bits 9..0Offset is a 6-bit unsigned integer on bits 15..10RGB8 format, one pixel is encoded as 3
successive 8-bit values (Red, Green,
Blue), therefore we need 3 successive 16-bit packed
coefficients to correct one RGB8 pixel.If the 16-bit packed coefficients are stored (in sequence) in a
binary file (let’s say 'path/to/coefficients.ffc'), they
can be easily loaded from a Euresys script by calling
require("egrabber://ffc/load")(grabber, 'path/to/coefficients.ffc');
where grabber is the script variable referencing the
grabber to configure.
Note: such a binary file can be created by the Euresys sample application presented in the next paragraph.
Euresys provides the source code of a sample application, called
ffc-wizard, that computes the coefficients and packs them
in a binary file targeting the Coaxlink cards.
The purpose of this sample code is threefold:
The source code lies in a single source file:
src/ffc-wizard.cpp. Building the application should be
straightforward;
ffc-wizard.vcproj;Makefile is provided.The wizard is a console application. The help message is displayed
when the flag -h (or --help) is given:
> ffc-wizard.exe --help
Flat Field Correction Wizard
fcc-wizard [OPTIONS]
Options:
--if=INT Index of GenTL interface to use
--dev=INT Index of GenTL device to use
--ds=INT Index of GenTL data stream to use
--average=INT Number of images to average (default: 10)
--roi_x=INT Horizontal offset in pixels of ROI upper-left corner (default: 0)
--roi_y=INT Vertical offset in pixels of ROI upper-left corner (default: 0; ignored for line-scan)
--roi_width=INT Width of ROI (default: whole image)
--roi_height=INT Height of ROI (default: whole image; ignored for line-scan)
--balance Compute flat image average on all components rather than on each component
--linescan Force line-scan mode i.e. average image lines (automatically enabled for line-scan cards)
--dark-setup=SCRIPT Path to setup script for dark acquisitions
--flat-setup=SCRIPT Path to setup script for flat acquisitions
--timeout=MS Maximum time in milliseconds to wait for an image (default: 1000)
--dark-histogram=FILE Path to histogram html page of average dark image to output and open
--flat-histogram=FILE Path to histogram html page of average flat image to output and open
--output-ffc=FILE Path to coefficients output file (Coaxlink ffc binary format)
--load-ffc=FILE Load coefficients into Coaxlink coefficients partition (default: computed coefficients)
--no-interact Skip user interaction
-h --help Display help message
Note: the ROI options allow defining a rectangular region to consider while computing averages,
this is useful to eliminate pixels close to borders in images subject to vignetting.
| Flags | Details |
|---|---|
--if, --def,
--ds |
the indexes of the GenTL modules that identify the data stream to use (and/or to configure) |
--average |
the number of images to acquire for dark and flat acquisitions; only the average of those acquisitions is further used in the calibration procedure |
--roi_x,
--roi_y, --roi_width,
--roi_height |
an optional rectangular region to consider
when computing the average pixel value of the flat image
(average(Flat)); this impacts the evaluation of the gain
value for each pixel |
--balance |
enables the white balance; i.e. whether the coefficients of color pixel components are computed to balance the component values or not; obviously, this requires the flat background used to acquire the flat image(s) to be as close as possible to a true gray (for which all RGB components would have identical values) |
--dark-setup,
--flat-setup |
optional configuration scripts to run before dark and flat acquisitions |
--dark-histogram,
--flat-histogram |
optional; path to output file showing the histogram of dark and flat image pixel components; this gives a visual overview of the dark current variations as well as the variations in the flat image |
--no-interact |
normally the wizard waits for the user to setup the system before starting the dark and flat acquisitions; when this flag is used, the wizard does not wait for the user (nor does it open the created histogram html pages) |
Here is an illustrated example that generates FFC coefficients (written to the file
coefficients.ffc) using the white balance functionality. The command to run from a
console window is the following:
The program starts and tells you what to do:
You can prepare your setup for the dark acquisitions and press Enter when you are ready. It will then acquire the series of dark images and display the instructions for the next step
You can prepare your setup for the flat acquisitions and press Enter
when you are ready. It will then acquire the series of flat images,
compute the corresponding coefficients and write them to the file
coefficients.ffc
Later on you can load the coefficients from the genicam-browser for
example, by running the load-ffc script as follows:
Then you can select the previously created file
coefficients.ffc
From that moment, the coefficients are loaded into the Coaxlink memory and the FFC processing is enabled.
The calibration procedure as well as the
packing of the coefficients is controlled by the main function
ffcWizard.
ffcWizard tasks| Task | Done by function |
|---|---|
| acquiring a series of dark images to build an average dark image | acquireImages |
| acquiring a series of flat images to build an average flat image | acquireImages |
computing the gain values for
each pixel component |
computeGain |
using the dark pixel component values as
offset values |
computeOffset |
packing offset and
gain values into 16-bit little-endian values |
packCoefficients |
| writing the packed coefficients into a binary file | savePackedCoefficients |
The sample application already supports a few common pixel formats:
Mono, RGB, RGBa and
Bayer.
Limitation: to limit the complexity of the sample
application, we consider (for pixel formats with several components per
pixel) that all components have the same size. Supporting pixel formats
with different component sizes is still possible by updating the
functions addImage and addComponents.
To support a new pixel format (under the condition of the previous limitation), we need to modify two functions:
Image::getComponentsPerPixel, to return the number of
components per pixel for the new format identified by its PFNC nameImage::getComponentFilters, to return a
std::vector of ComponentFilter objects
describing how the pixel components of the new format (identified by its
PFNC name) are positioned in
the imageThe ComponentFilter objects are used to separate the
processing of the different pixel components while evaluating the
Gain and Offset values. For example, in
RGB format (as described in Color Pixel
Formats), the FFC coefficients related to the
Red components are computed using the Red
components from the dark and flat images.
Please see the source code of Image::getComponentFilters
for details about pixel component layout configuration.