<a id="easycolor-general"></a>

# EasyColor - Pre-Processing Color Images

**EasyColor** provides efficient color image processing through color system conversions, lookup table-based transforms, Bayer decoding, and component operations. Several conversion functions mean that any supported color system can be processed.

<a id="easycolor-color-definition"></a>

## Color Definition and Supported Systems

<a id="easycolor-what-is-color"></a>

### What is Color?

* The human eye is sensitive to light:
  * **Intensity**, or **achromatic** sensation, captured by **grayscale** images.
  * **Wavelength**, or **chromatic** sensation, described in red, green, and blue primary **colors**.

![image](assets/images/easycolor/color_gamut.svg)
* There are three color systems:
  * **Mixture** systems (RGB / XYZ) give the proportions of the three primaries to be combined.
  * **YUV Luma/chroma** systems (YUV / L\*a\*b\* / L\*u\*v\* / YCbCr) separate the achromatic (Y) and chromatic sensations (U & V). Used when a black and white image is required as well (television).
  * **Intensity/saturation/hue** systems (ISH / LSH / VSH / LCH / YSH) separate achromatic (black and white Intensity) from enhanced chromatic (color Saturation and Hue) sensations. Used to eliminate lighting effects, or to convert RGB images to another color system. More saturated colors are more vivid, less saturated ones are grayer.
* In general:
  * RGB is used by monitors, cameras and other display devices.
  * YUV / YCbCr is used for efficient transmission of color images by compressing the chrominance information.
  * XYZ is used for device-independent color representation.
* All image processing operations can use **quantized** coordinates: discrete values in the [0..255] interval, which use a byte representation to store images in a frame buffer.
* Color system conversion operations can also use simpler **unquantized** coordinates: continuous values, often normalized to the [0..1] interval.

<a id="easycolor-color-image-processing"></a>

### Color Image Processing

* A color image is a vector field with three components per pixel. All three RGB components reflected by an object have amplitude proportional to the intensity of the light source. By considering the ratio of two color components, one obtains an illumination-independent image. With a clever combination of three pieces of information per pixel, one can extract better features.
* There are 3 ways to process a color image:
  * **Component extraction**: you can extract the most relevant feature from the triple color information, to reduce the amount of data. For instance, objects may be distinguished by their hue, a pre-processing step could transform the image to a gray-level image containing only hue values.
  * **De-coupled transformation**: you can perform operations separately on each color component. For instance, adding two images together adds the red, green and blue components and stores the result, component by component, in a resulting color image.
  * **Coupled transformation**: you can combine all three color components to produce three derived components. For example, converting YIQ to RGB.

<a id="easycolor-supported-color-systems"></a>

### Supported Color Systems

* **EasyColor** supports color systems RGB, XYZ, L\*a\*b\*, L\*u\*v\*, YUV, YCbCr, YIQ, LCH, ISH / LSH, VSH and YSH.
* RGB is the preferred internal representation as it is compatible with 24-bit Windows Bitmaps.

|                          | RGB-based                                                                                                                                                                                                                 | XYZ-based                                                                                                                                                   | YUV-based                                                                                                                                                                                                                     |
|--------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Mixture                  | [RGB](../../../glossary.html.md#term-RGB)                                                                                                                                                               | [XYZ](../../../glossary.html.md#term-XYZ)                                                                                                 |                                                                                                                                                                                                                               |
| Luma/Chroma              |                                                                                                                                                                                                                           | [L\*a\*b\*](../../../glossary.html.md#term-L-a-b) <br /><br/>\\\\<br/>[L\*u\*v\*](../../../glossary.html.md#term-L-u-v) | [YUV](../../../glossary.html.md#term-YUV)<br /><br/>\\\\<br/>[YCbCr](../../../glossary.html.md#term-YCbCr)<br /><br/>\\\\<br/>[YIQ](../../../glossary.html.md#term-YIQ) |
| Intensity/Saturation/Hue | [ISH](../../../glossary.html.md#term-ISH)<br /><br/>\\\\<br/>[LSH](../../../glossary.html.md#term-LSH)<br /><br/>\\\\<br/>[VSH](../../../glossary.html.md#term-VSH) | [LCH](../../../glossary.html.md#term-LCH)                                                                                                 | [YSH](../../../glossary.html.md#term-YSH)                                                                                                                                                                   |

<a id="easycolor-transform-using-luts"></a>

## Transform Using LUTs (Lookup Tables)

* **EasyColor** Lookup Tables provide an array of values that define what output corresponds to a given input, so an image can be changed by a user-defined transformation.
* A color pixel can take 16,777,216 ($2^{24}$) values, a full color LUT with these entries would occupy 50 MB of memory and transforms would be prohibitively time-consuming. Pre-computed LUTs make color transforms feasible.
* To transform a color image, you initialize a color LUT using one of the following functions:
  * [LUT for Gain / Offset (Color)](lookup_table.html.md#easycolor-lut-gain-offset): [`EasyImage::GainOffset`](../../../doxygen_cpp/classeVision_1_1EasyImage.html#a198f67f6fe8e5e91bbda471ab5d439ca) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyImage.html#a21914a5d707531e6a1897f1f8534216e) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyImage.html#a29abc49676a17381b1c40dbbd01ac463),
  * [LUT for Color Calibration](lookup_table.html.md#easycolor-lut-colorcalibration): [`EColorLookup::Calibrate`](../../../doxygen_cpp/classeVision_1_1EColorLookup.html#a81116162a8162258bd7e5488be1de89f) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EColorLookup.html#a6148162dc74007751250ef478c01535c)
    [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EColorLookup.html#aaea8a3dae3223cb28e19909dee94d55b),
  * [LUT for Color Balance](lookup_table.html.md#easycolor-lut-colorbalance): [`EColorLookup::WhiteBalance`](../../../doxygen_cpp/classeVision_1_1EColorLookup.html#a9213e20183c85ed5ca424bba010633f2) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EColorLookup.html#ac83a475139511222037d72a9d8ff7698) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EColorLookup.html#ad0b8f8201504f69c18de48d45f698a16),
  * [`EColorLookup::ConvertFromRgb`](../../../doxygen_cpp/classeVision_1_1EColorLookup.html#af6425cbf8223bb3a41a135e7aa720354) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EColorLookup.html#aa4e2562ef3b934192425bac0e45e3fd6) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EColorLookup.html#a4196a414a7762edd87ba36685e9becb0), [`EColorLookup::ConvertToRgb`](../../../doxygen_cpp/classeVision_1_1EColorLookup.html#a33872ea95ca49c45b019a59b91802d01) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EColorLookup.html#a5f2bfdb184c5e75f4e90b332bff2b66b) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EColorLookup.html#a6e6960c59ce4f32a558348f945e9aebc).
* This color LUT is then used in a transform operation such as [`EasyColor::Transform`](../../../doxygen_cpp/classeVision_1_1EasyColor.html#ae7443c9c1f809cd28bcee9423da51322) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyColor.html#a17cfcd3aa57367e9640eb306f6e86359) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyColor.html#ac679fc53e665bbe666e804f11eaf7207) or you can create a custom transform using [`EColorLookup`](../../../doxygen_cpp/classeVision_1_1EColorLookup.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EColorLookup.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EColorLookup.html) which takes unquantized values (continuous, normalized to [0..1] intervals), and specifies the source and destination color systems. Some operations use the LUT on-the-fly thus avoid storing the transformed image, for example to alter the U (of YUV) component while the image is in RGB format.
* The optimum combination of **accuracy and speed** is determined by the choice of [`EColorLookup::GetIndexBits`](../../../doxygen_cpp/classeVision_1_1EColorLookup.html#a58dc076cbbbf49a12688efdb01090b2b) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EColorLookup.html#a2e3981e469bc5e933e5e62ed32ce8ce6) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EColorLookup.html#a1205b6f3353bffbe610d5acc8dd73923) and [`EColorLookup::GetInterpolation`](../../../doxygen_cpp/classeVision_1_1EColorLookup.html#a72d25ac946352dad9a8299ca4b82e697) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EColorLookup.html#a51c6e49fb935c5df18171a5483904e7d) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EColorLookup.html#a77d18f960eb1c676681355af92ab2089) - the accuracy of the transformed values roughly corresponds to the number of index bits.
  * Fewer table entries mean smaller storage requirements, but less accuracy.
  * No interpolation gives quicker running time, but less accuracy. Interpolation can recover 8 bits of accuracy per component. When the involved transform is linear (such as YUV to RGB), interpolation always gives exact results, regardless of the number of table entries.

|   Index Bits | Number of entries            |    |   Table size (bytes) |
|--------------|------------------------------|----|----------------------|
|            4 | $2^{(3 \times 4)} = 4,096$   |    |               14,739 |
|            5 | $2^{(3 \times 5)} = 32,768$  |    |              107,811 |
|            6 | $2^{(3 \times 6)} = 262,144$ |    |              823,875 |

<a id="easycolor-discrete-vs-continuous"></a>

## Discrete Quantized vs. Continuous Unquantized

Color coordinates in the classical systems are normally **continuous** values, often normalized to the [0..1] interval. Computations on such values, termed **unquantized**, are simpler.

However, storage of images in a frame buffer imposes a byte representation, corresponding to **discrete** values, in the [0..255] interval. Such values are termed **quantized**.

All image processing operations apply to quantized values, but conversion operations can also be specified using unquantized coordinates.

<a id="easycolor-transform-yuv"></a>

## Transform YUV444 / YUV422

* YUV images can be minimized without degrading visual quality using function [`EasyColor::Format444To422`](../../../doxygen_cpp/classeVision_1_1EasyColor.html#afedca3be0c726d5557549e11d0611e38) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyColor.html#ad971d5b3b1b593223677fa1f5f7f4901) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyColor.html#ac43064250e57dfbad8ddba88e6e8c5e9) to convert from 4:4:4 to 4:2:2 format (or you can convert `Format 422 to 444` ([`EasyColor::Format422To444`](../../../doxygen_cpp/classeVision_1_1EasyColor.html#ac9645c4cef77981637f31c836ffe24fa) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyColor.html#ade758c29fc207b1f1cb36a39f4b8b6e7) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyColor.html#a06addeb52689c24063c05e1ec23c812e))).
  * 4:4:4 uses 3 bytes of information per pixel.
  * 4:2:2 uses 2 bytes of information per pixel. It stores the **even** pixels of U and V chroma with the **even and odd** pixels of Y luma as follows:

$ Y_{[even]} U_{[even]} Y_{[odd]} V_{[even]} $

<a id="easycolor-merge-extract-color"></a>

## Merge, Extract, and Color

* A color image contains three color planes of continuous tone images.
* A gray-level image can be a component of a color system.

<a id="easycolor-merge-extract-components"></a>

### Merge and Extract Components

* **EasyColor** can change or extract one plane at a time, or all three together. See [`EasyColor::Compose`](../../../doxygen_cpp/classeVision_1_1EasyColor.html#ad88889bbfda9f5708574d56cdcfacb8c) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyColor.html#aa37b5ac39005b53c52782d64519aedd2) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyColor.html#a18c48b17a5e95158590366148a5e2290), [`EasyColor::Decompose`](../../../doxygen_cpp/classeVision_1_1EasyColor.html#a0938070540e56484c3531d2308971a55) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyColor.html#ac54dde83b960d2ee165da43f4d2e49b0) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyColor.html#aeeeaa4a46e7b7219b5ebbe83700bdd68), [`EasyColor::GetComponent`](../../../doxygen_cpp/classeVision_1_1EasyColor.html#a6ddf04e79c0fdca48c37c9a673e36cf6) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyColor.html#ae320096f815060127da0e26cbaa519e8) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyColor.html#ab871aa1eb9fefbef197a64fd847db2c4), [`EasyColor::SetComponent`](../../../doxygen_cpp/classeVision_1_1EasyColor.html#ad5fe17c0ff9a3510673ead58d743e0a9) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyColor.html#a0280d36ae72ca71a5b65f897f0d446f6) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyColor.html#a3143b8585161d81ec204077f5abcc9dd).
* These operations can use a color LUT to transform on the fly, for example, to build an RGB image from lightness, saturation and hue planes.

#### NOTE
**EasyColor** functions perform the necessary interleaving / un-interleaving operations to support Windows bitmap format of interleaved color planes (blue, green and red pixels follow each other).

<a id="easycolor-pseudo-color"></a>

### Pseudo-Color to Transform Gray-Level Images to Color

* The trick is to define a regular gamut of 256 colors and each color will be assigned to pixels with a corresponding gray-level value.
* To define pseudo-color shades, you specify a trajectory in the color space of an arbitrary system. You can then pseudo-color using the drawing functions color palette (see Image and Vector Drawing) then save and/or transform it like any other color image.

![](assets/images/easycolor/colorization_input.webp)![](assets/images/easycolor/colorization_output.webp)

<a id="easycolor-separate-color-objects"></a>

## Separate Color Objects

* This **EasyColor** process takes a set of distinct colors and associates each pixel with the closest color, using a layer index that can then be used in [EasyObject](../../matching_and_measurement/easyobject/index.html.md) with the labeled image segmenter to improve blob creation.

![ColorSegmentationNone](assets/images/easycolor/colorsegmentationnone.webp)![ColorSegmentationThree](assets/images/easycolor/colorsegmentationthree.webp)

<a id="easycolor-rgb-bgr-conversion"></a>

## `RGB` and `BGR` Conversion

**EasyColor** allows you to convert an image brom RGB to BGR. This can be applied to [`EImageC24`](../../../doxygen_cpp/classeVision_1_1EImageC24.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EImageC24.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EImageC24.html) and [`EImageC24A`](../../../doxygen_cpp/classeVision_1_1EImageC24A.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EImageC24A.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EImageC24A.html).

Please note that **eVision** uses BGR (A) images internally. Therefore, a color image loaded using [`EImageC24::Load`](../../../doxygen_cpp/classeVision_1_1EBaseROI.html#a993f2416a63b523d6b1a89b1b4f9310d) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EBaseROI.html#ab468012a82769c1902eaefde4a1a74b1) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EBaseROI.html#a6203404de61357bdbae378e32144fe91) is in the `BGR` format. When getting a [`EC24`](../../../doxygen_cpp/structeVision_1_1EC24.html) [<sub>.NET</sub>](../../../doxygen_cs/structeVision_1_1EC24.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EC24.html) pixel from an image:

* [`EC24::C0`](../../../doxygen_cpp/structeVision_1_1EC24.html#a27a0269a1109496cd75e3e0d63360ca4) [<sub>.NET</sub>](../../../doxygen_cs/structeVision_1_1EC24.html#ae33868cd37f6a142a43e8ad459d6fd7c) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EC24.html#a35d1b246e7dd46752be1a5c3aaac57d3) is the red channel.
* [`EC24::C1`](../../../doxygen_cpp/structeVision_1_1EC24.html#a1cdf5d4a934b6a9cdb54462dd0cb3e36) [<sub>.NET</sub>](../../../doxygen_cs/structeVision_1_1EC24.html#a74844da2f23eae26ecd909905f096284) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EC24.html#a209b493f1e6a3a5b68e8ae148df56844) is the green channel.
* [`EC24::C2`](../../../doxygen_cpp/structeVision_1_1EC24.html#a6ec9bff4382e0a2ac077dc3d67e0fb82) [<sub>.NET</sub>](../../../doxygen_cs/structeVision_1_1EC24.html#a43da734070c5c52285ef21277d55997e) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EC24.html#ae7667a2566e172a1aa750f167be13ac6) is the blue channel.

## See Also

Converting Bayer-encoded images to true color.

Color transforms using precomputed lookup tables.

Easy to understand, ready to copy code snippets.
