<a id="easymatch-learn-patterns"></a>

# Learn a Pattern

* Select an image containing the pattern/ROI to be searched for and call [`EMatcher::LearnPattern`](../../../doxygen_cpp/classeVision_1_1EMatcher.html#acefe7822d00bd66e29361fe6d9781421) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EMatcher.html#a75bc52a9ce8490d5606986abe5b118dc) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EMatcher.html#abb5a92bb163e68d8fb98c1525a5ea632).
* Pass an arbitrary shaped region of interest ([`ERegion`](../../../doxygen_cpp/classeVision_1_1ERegion.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ERegion.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ERegion.html)) to ignore the pixels outside of this region.

#### WARNING
For historical reasons, masking part of the pattern with `ERegion` does not work properly when some pixels in the pattern have a grayscale value of `0` (these pixels are handled as if they were outside of the `ERegion`).

* The resulting [`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) object can be saved through [`EMatcher::Save`](../../../doxygen_cpp/classeVision_1_1EMatcher.html#a2690f5e9aa8e5ebb95c79b9a4b283eda) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EMatcher.html#a149489dadfed73e36f4deff7c72849d7) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EMatcher.html#aed3d59f45a4b39784e4e91d788b7ab43) for later use.

<a id="easymatch-learning-workflow"></a>

## Learning Workflow

<a id="easymatch-best-pattern"></a>

## Ideal Patterns to Learn

**EasyMatch** works best when the patterns:

- **Represent the object to be located.** They should:
  - Keep the same appearance whatever the lighting conditions.
  - Remain at a fixed location with respect to the part.
  - Be rigid and not change shape.
- **Exhibit good contrast in small and large scale.** They should be distinctly visible from a distance, and on a reduced image.
- **Not be invariant under the degrees of freedom to be measured.** For instance, a pattern of black and white horizontal stripes cannot detect horizontal translation; a cog wheel cannot help measure large rotations.
- **Have a neutral background.** If objects around the pattern in the ROI may change, this area should be neutralized by means of an [`ERegion`](../../../doxygen_cpp/classeVision_1_1ERegion.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ERegion.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ERegion.html).
- **Have contrasted margin around the objects** so that foreground and background intensities are seen.

#### WARNING
[`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) does not work with uniform patterns. In this case, it always returns a score of -1 and Advanced Learning fails.

<a id="easymatch-multiple-models"></a>

## Learn Multiple Models from Different Images

With **EasyMatch**, you can also learn multiple models at once.

#### NOTE
This is useful when different instances of the model look very different, for example because of perspective, illumination or mechanical deformations.

![image](assets/images/easyfind/studio2/learn_multiple_models_1.webp)![image](assets/images/easyfind/studio2/learn_multiple_models_2.webp)

To learn multiple patterns:

1. Call the function [`EMatcher::LearnPatterns`](../../../doxygen_cpp/classeVision_1_1EMatcher.html#a903bb33cfd15deb6f8c74e7163708de1) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EMatcher.html#a392ed536eb4591b509fc63f3c7d2b730) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EMatcher.html#a6e2592aa0850c6665af52a84ffc1b109) with several images instead of the function [`EMatcher::LearnPattern`](../../../doxygen_cpp/classeVision_1_1EMatcher.html#acefe7822d00bd66e29361fe6d9781421) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EMatcher.html#a75bc52a9ce8490d5606986abe5b118dc) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EMatcher.html#abb5a92bb163e68d8fb98c1525a5ea632) with a single image.
2. Call the function [`EMatcher::Match`](../../../doxygen_cpp/classeVision_1_1EMatcher.html#ac4c97be7341241ee12a14b705fb1d150) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EMatcher.html#a753e5bd7a5a267f3119986f1b5c6235b) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EMatcher.html#aa146cdcdcfdb2d330ca60014db506cc1) to search the patterns in the image.

#### NOTE
Using multiple threads with [`Easy::SetMaxNumberOfProcessingThreads`](../../../doxygen_cpp/classeVision_1_1Easy.html#a07daba7dfbeff40db5e1d9e4404d4722) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy.html#ae729364026373ca376e818d4b82cd978) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy.html#ae819b646aea6778997c6155442a0ccee) results in large speed gains as the process is parallelized over the learned patterns.

<a id="easymatch-pyramid-creation"></a>

## Pyramid Creation

EasyMatch is faster than simple pattern matching because it uses image pyramids. This concept is important to understand the parameters below.

* The learned pattern and inspected image are downscaled a certain number of times
* The coarsest reduction (Level 4 on the image below) is used to find intial match candidates
* Moving from coarsest to finest reduction (Level 0 on the image below), the position of the candidates is iteratively refined
* Parameters can be tuned to minimize processing time, but **EasyMatch** still takes longer than **EasyFind** as the entire selected area is searched.

![image](assets/images/easymatch/Image_pyramid.svg)

<a id="easymatch-learning-parameters"></a>

## Learning Parameters

<a id="easymatch-filtering-mode"></a>

### Filtering Mode

* When creating the [pyramid](), filtering is used before each downsizing of the image.
* By default, a uniform kernel is used.
* [`EMatcher::SetFilteringMode`](../../../doxygen_cpp/classeVision_1_1EMatcher.html#aaaa310d70cdc26f547d0788ea34b959f) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EMatcher.html#ad28c0384ee60d809cfb28721ea0ba845) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EMatcher.html#a1de0b71ee84bc52f2353f2eaed35fbdd) allows to use a low-pass kernel instead. The low-pass kernel works better if the image has sharp gray-level transitions.

<a id="easymatch-min-reduced-area"></a>

### Min Reduced Area

The pattern is downsized in the pyramid as long as the coarsest reduction gets a size (i.e. an area in pixels) greater than or equal to [`EMatcher::SetMinReducedArea`](../../../doxygen_cpp/classeVision_1_1EMatcher.html#a8e20a55230616181572c2c91638f77e3) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EMatcher.html#a0d97cd3eab8d063699bf4d6fccdbdf9f) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EMatcher.html#a7bf90e8e299a386b2a6b7c51d1e45d6d):

* The bigger the value, the faster the matching process. However, if set too high, it decreases the matching process reliability.
* The value of `MinReducedArea` is computed automatically if [`AdvancedLearning`](../../../doxygen_cpp/classeVision_1_1EMatcher.html#a82f1a8b91ef6704954fbb65935bfc9a9) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EMatcher.html#a296db165a9fa5f498542bf8ea88c5715) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EMatcher.html#ab60a21a668b30cb23aa41948deec0b23) is enabled (default behavior).
* Explicitly setting `MinReducedArea` disables `AdvancedLearning`. A `MinReducedArea` of 64 is usually a good compromise.

<a id="easymatch-advanced-learning"></a>

### Advanced Learning

If the pattern is defined as an ROI, [`EMatcher::SetAdvancedLearning`](../../../doxygen_cpp/classeVision_1_1EMatcher.html#a82f1a8b91ef6704954fbb65935bfc9a9) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EMatcher.html#a296db165a9fa5f498542bf8ea88c5715) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EMatcher.html#ab60a21a668b30cb23aa41948deec0b23) uses the entire image to optimize learning parameters such as `MinReducedArea`:

* `AdvancedLearning` is enabled by default, as it leads to better results in case of tiled or periodic images.
* If [`EMatcher::SetMinReducedArea`](../../../doxygen_cpp/classeVision_1_1EMatcher.html#a8e20a55230616181572c2c91638f77e3) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EMatcher.html#a0d97cd3eab8d063699bf4d6fccdbdf9f) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EMatcher.html#a7bf90e8e299a386b2a6b7c51d1e45d6d) is used explicitly, `AdvancedLearning` is disabled.
* Please note that as [`EMatcher::SetAdvancedLearning`](../../../doxygen_cpp/classeVision_1_1EMatcher.html#a82f1a8b91ef6704954fbb65935bfc9a9) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EMatcher.html#a296db165a9fa5f498542bf8ea88c5715) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EMatcher.html#ab60a21a668b30cb23aa41948deec0b23) changes the size of the pyramid, it can have a significant impact on matching duration.

<a id="easymatch-learn-timeout"></a>

### Learn Timeout

[`EMatcher::LearnPattern`](../../../doxygen_cpp/classeVision_1_1EMatcher.html#acefe7822d00bd66e29361fe6d9781421) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EMatcher.html#a75bc52a9ce8490d5606986abe5b118dc) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EMatcher.html#abb5a92bb163e68d8fb98c1525a5ea632) possesses a timeout:

- Use [`EMatcher::SetLearnTimeOut`](../../../doxygen_cpp/classeVision_1_1EMatcher.html#a113284bb50709d3a9a2f57b9ff179db0) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EMatcher.html#a6b9568f476406d9f6dd2c204c3e921d0) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EMatcher.html#abb063df2a799be078cef038785cfa6d0) to add a time limit to the methods [`EMatcher::LearnPattern`](../../../doxygen_cpp/classeVision_1_1EMatcher.html#acefe7822d00bd66e29361fe6d9781421) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EMatcher.html#a75bc52a9ce8490d5606986abe5b118dc) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EMatcher.html#abb5a92bb163e68d8fb98c1525a5ea632) and [`EMatcher::LearnPatterns`](../../../doxygen_cpp/classeVision_1_1EMatcher.html#a903bb33cfd15deb6f8c74e7163708de1) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EMatcher.html#a392ed536eb4591b509fc63f3c7d2b730) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EMatcher.html#a6e2592aa0850c6665af52a84ffc1b109).
- If the timeout is reached, an exception is thrown and the processing stops.

#### NOTE
This timeout mechanism is used to prevent the application from freezing while tuning parameters. This is especially useful in **eVision Studio**. Note that this does not correspond to the behavior of code reader timeouts, which aim to prevent long processing times in production settings.
