# EChecker - Validating Golden Templates

[`EChecker`](../../../doxygen_cpp/classeVision_1_1EChecker.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EChecker.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EChecker.html) is a tool that allows you to inspect an image using a Golden Template validation. It works in 2 steps:

1. The *Model Creation* involves preprocessing one of several reference images to compute a model. You can create the model once and save the results in a Golden Template model for later use.
2. The *Inspection* involves processing an image and checking its quality using the previously computed model. These 2 operations are totally independent and can be programmed in separate applications.

The following sections present the relevant API functions for use in the training and inspection steps.

<a id="echecker-vs-legacy"></a>

## EChecker vs. Legacy::EChecker2

[`EChecker`](../../../doxygen_cpp/classeVision_1_1EChecker.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EChecker.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EChecker.html) supersedes the original [`eVision::Legacy::EChecker2`](../../../doxygen_cpp/classeVision_1_1Legacy_1_1EChecker2.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Legacy_1_1EChecker2.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Legacy_1_1EChecker2.html) (which itself superseded [`eVision::Legacy::EChecker`](../../../doxygen_cpp/classeVision_1_1Legacy_1_1EChecker.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Legacy_1_1EChecker.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Legacy_1_1EChecker.html)):

- It expands [`eVision::Legacy::EChecker2`](../../../doxygen_cpp/classeVision_1_1Legacy_1_1EChecker2.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Legacy_1_1EChecker2.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Legacy_1_1EChecker2.html) with an up-to-date API using [`EFrame`](../../../doxygen_cpp/classeVision_1_1EFrame.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EFrame.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EFrame.html) and easy to integrate to the **eVision Studio** workflows.
- It delegates the alignment part to the calling application, allowing for greater flexibility when aligning.

For all these reasons, the original [`eVision::Legacy::EChecker2`](../../../doxygen_cpp/classeVision_1_1Legacy_1_1EChecker2.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Legacy_1_1EChecker2.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Legacy_1_1EChecker2.html) is now considered legacy and deprecated.

<a id="echecker-creating-a-model"></a>

## Creating a Model

During the model creation phase, the good images are processed to build the model that is used in the inspection phase. The model includes the pixel acceptance ranges, in the form of 2 threshold images, as well as the information needed to normalize the images and the region to inspect.

The [`EChecker::Train`](../../../doxygen_cpp/classeVision_1_1EChecker.html#ab7eb8ea952edc325af476c1ee707750d) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EChecker.html#ae27ca6499a012f08ee79884eabc9a9e8) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EChecker.html#a94e314953c0b82a10e5e375e0d1d75be) method creates the model. This method takes the frames to align all the images on a common reference as input, so the alignment part must be handled first.

<a id="echecker-external-alignment"></a>

### External Alignment

#### HINT
If your images are sufficiently aligned, you can skip this step.

**EChecker** needs to know where the object to inspect lies in the image.

* Use an [`EFrame`](../../../doxygen_cpp/classeVision_1_1EFrame.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EFrame.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EFrame.html) that indicates a referential for each training or inspection image.
* Define the inspection region in that frame.
* You can use an [`EPatternFinder`](../../../doxygen_cpp/classeVision_1_1EPatternFinder.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EPatternFinder.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EPatternFinder.html) or an [`EMatcher`](../../../doxygen_cpp/classeVision_1_1EMatcher.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EMatcher.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EMatcher.html) to directly detect the frame or you can use a combination of several [`EFoundPattern`](../../../doxygen_cpp/classeVision_1_1EFoundPattern.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EFoundPattern.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EFoundPattern.html).

There are 2 **EChecker** samples in **eVision Studio**:

* In the first sample, an [`EPatternFinder`](../../../doxygen_cpp/classeVision_1_1EPatternFinder.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EPatternFinder.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EPatternFinder.html) retrieves the frame by finding the text to inspect (the text is not at a fixed position on the chip, so the chip itself cannot be used as a frame).
  ![](assets/images/echecker/creating_a_model_1a.webp)![](assets/images/echecker/creating_a_model_1b.webp)
* In the second sample, the frame is obtained by finding 2 fiducials, drawing a line between them and applying a fixed rotation so that the reference frame is horizontal.
  ![](assets/images/echecker/creating_a_model_1c.webp)![](assets/images/echecker/creating_a_model_1d.webp)

<a id="echecker-training-on-multiple-images"></a>

### Training on Multiple Images

After the alignment setup, the main training phase begins.

* All the training images are processed and are averaged using statistical training (see below).
* The training uses realignment to deal with displacement of the inspected part in the field of view.
* The training uses gray-level normalization to deal with global illumination changes.

Ideally, use 16 images or more in training to create the low and high threshold images that serve as the basis of the inspection process.

<a id="echecker-statistical-training"></a>

### Statistical Training

Use several training images to build a statistical model of normal gray-level variations and establish acceptance ranges. All submitted images must be correctly aligned so that variations in gray levels come only from noise and normal part-to-part differences, not from geometric transformations.

- **Consecutive images of the same part** capture the noise distribution, the inherent camera and lighting fluctuations.
- **Consecutive images of different defect-free parts** capture normal part-to-part variations due to manufacturing tolerances and material properties.
- **Training images should cover the expected range of real-world conditions** (lighting variations, part geometry spread, etc.) so that detected defects represent genuine anomalies rather than normal variation.

![](assets/images/echecker/creating_a_model_2a.webp)![](assets/images/echecker/creating_a_model_2b.webp)![](assets/images/echecker/creating_a_model_2c.webp)![](assets/images/echecker/creating_a_model_2d.webp)

<a id="echecker-model-creation-parameters"></a>

### Model Creation Parameters

Choose the [`training mode`](../../../doxygen_cpp/classeVision_1_1EChecker.html#ac6f1738a9fac397a21f85c1ff9e15073) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EChecker.html#add14cc3f202e892197f6be4a559e4513) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EChecker.html#a8d6e81030dc168420dfcd09f687cc9d8) to fit your needs:

- [`Quick`](../../../doxygen_cpp/namespaceeVision.html#abc8159ce5dc3001f0b77fcc9e84f96aaa272a0d109b46198d0cd76cd1ef7e985e) [<sub>.NET</sub>](../../../doxygen_cs/namespaceeVision.html#a4d2e495adc9f5217438bcf497a0a36a9) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ETrainingMode.html#ad995d96735a0fc966c74ba4a8ec0034f) for a quick training process and simpler cases (well defined defects and stable illumination).
- [`Precise`](../../../doxygen_cpp/namespaceeVision.html#abc8159ce5dc3001f0b77fcc9e84f96aaae3f16d84fc959268426297973d7dfbed) [<sub>.NET</sub>](../../../doxygen_cs/namespaceeVision.html#a4d2e495adc9f5217438bcf497a0a36a9) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ETrainingMode.html#a421c4e3c53bfcd121bae03a98a9d9aae) for more difficult cases.
- Default: [`Precise`](../../../doxygen_cpp/namespaceeVision.html#abc8159ce5dc3001f0b77fcc9e84f96aaae3f16d84fc959268426297973d7dfbed) [<sub>.NET</sub>](../../../doxygen_cs/namespaceeVision.html#a4d2e495adc9f5217438bcf497a0a36a9) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ETrainingMode.html#a421c4e3c53bfcd121bae03a98a9d9aae) mode.

Set the  [`normalisation mode`](../../../doxygen_cpp/classeVision_1_1EChecker.html#a86cfdf685969d499417dc567eeae6fc6) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EChecker.html#a041efccdf45b66f9e314ddc6890ff9f2) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EChecker.html#ab34dcde52d6984b1f714de115b32d73b) to select the type of normalization used by **EChecker**:

- [`Moments`](../../../doxygen_cpp/namespaceeVision.html#a60a85a273c5ce69b059ebea9a103fb37a66842fe716426fae5f0bcd909fead43c) [<sub>.NET</sub>](../../../doxygen_cs/namespaceeVision.html#ab0fcb6aa130fe4d4008950e89e536dd0) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ENormalizationMode.html#ae32684dce900f950cd0e9e74db1b6d60): linear.
- [`Threshold`](../../../doxygen_cpp/namespaceeVision.html#a60a85a273c5ce69b059ebea9a103fb37acc35bd2bbaca27f015becc572fc6f81d) [<sub>.NET</sub>](../../../doxygen_cs/namespaceeVision.html#ab0fcb6aa130fe4d4008950e89e536dd0) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ENormalizationMode.html#a9ccf27e6e2371ea30726dcd053fe8c10): non-linear.
- [`NoNormalization`](../../../doxygen_cpp/namespaceeVision.html#a60a85a273c5ce69b059ebea9a103fb37a2a3b5da9a5f649fd192243ee18e697a8) [<sub>.NET</sub>](../../../doxygen_cs/namespaceeVision.html#ab0fcb6aa130fe4d4008950e89e536dd0) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ENormalizationMode.html#a352c8016c9b332d00476a494e7608103): if your acquisition process already produces consistently lit images.
- By default, the [`Moments`](../../../doxygen_cpp/namespaceeVision.html#a60a85a273c5ce69b059ebea9a103fb37a66842fe716426fae5f0bcd909fead43c) [<sub>.NET</sub>](../../../doxygen_cs/namespaceeVision.html#ab0fcb6aa130fe4d4008950e89e536dd0) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ENormalizationMode.html#ae32684dce900f950cd0e9e74db1b6d60) normalization mode is used.

Set the [`inspection tolerance`](../../../doxygen_cpp/classeVision_1_1EChecker.html#afab01d838f70099b86eebe24eec9418f) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EChecker.html#ad70d316cdd38e6afbf37281bebbe695a) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EChecker.html#a2ee7e376865adbe816b9fd24093e16a5) to adjust the acceptance ranges during the inspection.

- Use higher values to make the inspection process more tolerant to noise and/or texture.

#### NOTE
All these parameters have an influence on how the model is built, and, as such, if any of these parameters is changed, you must restart the model creation.

<a id="echecker-training-on-a-single-image"></a>

### Training on a Single Image

Although **EChecker** often needs several training images, in simple cases, you can use only one with specific tolerance thresholds with the method [`EChecker::TrainOnSingleImage`](../../../doxygen_cpp/classeVision_1_1EChecker.html#a0a595abfc1cf0c2af3465d4ae07a9943) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EChecker.html#a2b15f3bf0cf93a513fafbb97219c5d36) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EChecker.html#ab97aff753b2df537f7a4be4ec71ab66d). This method accepts a pixel if it is between $p - G$ and $P + G$, with $p$ the smallest pixel in a `geometricMargin` vicinity, $P$ the biggest pixel in a `geometricMargin` vicinity and $G$ the value of the parameter `grayLevelTolerance`.

In this mode [`EChecker::SetInspectionTolerance`](../../../doxygen_cpp/classeVision_1_1EChecker.html#afab01d838f70099b86eebe24eec9418f) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EChecker.html#ad70d316cdd38e6afbf37281bebbe695a) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EChecker.html#a2ee7e376865adbe816b9fd24093e16a5) and [`EChecker::SetTrainingMode`](../../../doxygen_cpp/classeVision_1_1EChecker.html#ac6f1738a9fac397a21f85c1ff9e15073) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EChecker.html#add14cc3f202e892197f6be4a559e4513) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EChecker.html#a8d6e81030dc168420dfcd09f687cc9d8) are ignored but [`EChecker::SetNormalizationMode`](../../../doxygen_cpp/classeVision_1_1EChecker.html#a86cfdf685969d499417dc567eeae6fc6) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EChecker.html#a041efccdf45b66f9e314ddc6890ff9f2) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EChecker.html#ab34dcde52d6984b1f714de115b32d73b) still applies.

![image](assets/images/echecker/creating_a_model_3.webp)

<a id="echecker-model-serialization"></a>

### Model Serialization

After the training, use the methods [`Save`](../../../doxygen_cpp/classeVision_1_1EChecker.html#abc34e25ace354eb5631250d44d0a61cf) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EChecker.html#af94ae4d9abb91f14aa7156c56208cc06) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EChecker.html#a9997142c160448398f280be431f52503) to save the created model in a single file including all the relevant information and [`Load`](../../../doxygen_cpp/classeVision_1_1EChecker.html#a471551c5273934db33cbd8c53d457841) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EChecker.html#ae49247322516162524ff363408a4e3a7) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EChecker.html#ad1cf585750421468d3a4bd27bd0e4c3a) to retrieve it.

#### NOTE
If you performed an alignment, (de)serialize the [`EPatternFinder`](../../../doxygen_cpp/classeVision_1_1EPatternFinder.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EPatternFinder.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EPatternFinder.html) or the [`EMatcher`](../../../doxygen_cpp/classeVision_1_1EMatcher.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EMatcher.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EMatcher.html) as well.

<a id="echecker-inspecting-an-image"></a>

## Inspecting an Image

Use the inspection on an image to assess it against the trained model. The process is straightforward:

1. The sample image is realigned with the model.
2. The gray-level is normalized.
3. This gray-level is combined with the high and low threshold images to populate an [`ECodedImage2`](../../../doxygen_cpp/classeVision_1_1ECodedImage2.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ECodedImage2.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ECodedImage2.html).
4. The computed blobs are made of pixels that fall out of the range defined by the threshold images and thus represent potential defects.

![image](assets/images/echecker/inspection_1.webp)![](assets/images/echecker/inspection_2a.webp)![](assets/images/echecker/inspection_2b.webp)![image](assets/images/echecker/inspection_3.webp)
* When the inspection is done, you can discard the smaller defects (usually noise), as well as measure the geometric characteristics (location, size, orientation…) using the standard **EasyObject** processes.
* To perform the inspection, use the method [`EChecker::Inspect`](../../../doxygen_cpp/classeVision_1_1EChecker.html#a1bb8d1328338873720ccd6a6a274e025) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EChecker.html#a9699123d21acaf4a835803c94084c33e) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EChecker.html#a47d9bb0f08d4456dcc6563bbf1a9eb80).
* As for [`EChecker::Train`](../../../doxygen_cpp/classeVision_1_1EChecker.html#ab7eb8ea952edc325af476c1ee707750d) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EChecker.html#ae27ca6499a012f08ee79884eabc9a9e8) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EChecker.html#a94e314953c0b82a10e5e375e0d1d75be), if an alignment is needed, first extract the frame of the fiducial (s) from the image.

<a id="easyobject-checker-quick-links"></a>

## Quick Links

Easy to understand, ready to copy code snippets.

Using EasyFind to correctly align images before detection and inspection.

Using EasyMatch to correctly align images before detection and inspection.

#### SEE ALSO
Some **eVision Studio** samples illustrate several aspects of the **EChecker** tool:

* **Checker without Alignment**: Checks defects on printed characters that are already aligned. The training is based on `TrainOnSingleImage`, a single image and tolerance thresholds are used instead of several representative images. This sample relies on the EasyObject library.
* **Checker with Basic Alignment**: Checks defects on chips after alignment with a pattern finder. This sample relies on the EasyObject and EasyFind libraries.
* **Checker with Advanced Alignment**: Checks defects on pcbs after alignment of 2 fiducials with 2 pattern finders. The 2 fiducials are then combined to form a frame. This sample relies on the EasyObject and EasyFind libraries.
