Conditional execution consists in executing a part of a program, or not, depending on whether some condition is met. There are two possible ways to achieve this in Adaptive Vision Studio:
- Variant Macrofilters – preferred when there are two or more alternative paths of execution.
- Conditional Connections – preferred when the program structure is linear and only some steps may be skipped in some circumstances.
This section is devoted to the second way, conditional connections.
Before conditional connections can be discussed, we need to explain, what conditional data is. There are some filters, for which it may be impossible to compute the output data. For example, the SegmentSegmentIntersection filter computes the intersection point of two line segments, but for many input segments the intersection may not exist. In such cases, the filter returns a special Nil value which indicates lack of data.
Other examples of filters producing conditional data include:
- ScanSingleEdge – will not find any edge on a plain image.
- DecodeBarcode – will not return any decoded string, if the checksum is incorrect.
- GigEVision_GrabImage_WithTimeout – will not return any image, if communication with the camera times out.
Filter outputs that produce conditional data can be recognized by their types which have a question mark suffix. For example, the output type in SegmentSegmentIntersection is "Point2D?".
The Nil value corresponds to the NULL pointer or a special value, such as -1. Conditional types, however, provide more type safety and clearly define, in which parts of the program special cases are anticipated.
Conditional connections () appear when a conditional output is connected to a non-conditional input. The second filter is then said to be executed conditionally and has its output types changed to conditional as well. It is actually executed only if the incoming data is not Nil. Otherwise, i.e. when a Nil comes, the filter also returns Nil on all its outputs and it becomes subdued in the Program Editor.
As output types of conditionally executed filters change into conditional, an entire sequence of conditionally executed filters can easily be created. This sequence ends at a filter that accepts conditional data on its input.
Resolving Nil Values
In general, if we have a conditional execution, the Nil has to be anticipated, and it has to be resolved at some point. Here is a list of the most typical solutions:
- First of all, the Nil case can be ignored. Some part of the program will be not executed and it will not be signaled. This is however usually unacceptable in industrial machine vision systems, where some sort of output signal must be produced for each inspected object.
- The most simple way to resolve Nil is by using the MergeDefault filter, which replaces Nil with another value, specified in the program. Most typically for industrial quality inspection systems, we can replace Nil with "NOT OK" inspection result.
- A conditional value can also be transformed into a logical value with TestObjectNotNil or TestObjectNil filter.
- If conditional values appear in an array, e.g. because a filter with a conditional output is executed in array mode, then the RemoveNils filter can create a copy of this array with all Nils removed. Please note, however, that this operation potentially destroys a correspondence of elements between this and other arrays.
- Sometimes we have a Task with conditional values at some point, where Nil appears only in some iterations. If we are interested in returning the latest value that existed, the LastNotNil filter can be helpful.
- Another possibility is to use a variant macrofilter with a conditional forking input and exactly two variants: "Nil" and "Default". The former will be executed for Nil, the latter for any other value.
Conditional execution can be illustrated with a simplified version of the "Capsules" example:
Other Alternatives to Conditional Execution
If the objects that have to be processed conditionally belong to an array, then it is advisable to use neither variant macrofilters nor conditional connections, but the classification filters from the Classify group. Each of these filters receives an array on its input and then splits it into several arrays with elements grouped accordingly to one of the three criterions.
Especially the ClassifyByRange filter is very useful when classifying objects on a basis of values of some extracted numeric features.
In the simplest cases it is also possible to compute a value conditionally with the filters from the Choose group (ChooseByPredicate, ChooseByRange, ChooseByCase) or with the ternary <if> ? <then> : <else> operator in the formula blocks.
|Previous: Connections||Next: Types of Filters|