You are here: Start » Appendices » Quick Start Guide for the C/C++ Programmers
Quick Start Guide for the C/C++ Programmers
FabImage Studio has been created by developers, who were previously creating machine vision applications in C++. We created this product to make this work much more efficient, whereas another our goal was to retain as much of the capabilities and flexibility as possible. We did not, however, simply create a graphical interface for a low level C++ library. We applied a completely different programming paradigm – the Data Flow model – to find the optimum balance between capabilities and development efficiency. Programming in FabImage Studio is more like designing an electrical circuit – there are no statements and no variables in the same way as they are not present on a PCB board. The most important thing to keep in mind is thus that there is no direct transition from C++ to FabImage Studio. You need to stop thinking in C++ and start thinking in data flow to work effectively. Automatic C++ code generation is still possible from the data flow side, but this should be considered a one-way transformation. At the level of a data flow program there are no statements, no ifs, not fors.
So, how should you approach constructing a program, when you are accustomed to such programming constructs as loops, conditions and variables? First of all, you need to look at the task at hand from a higher level perspective. There is usually only a single, simple loop in machine vision applications – from image acquisition to setting digital outputs with the inspection results. It is highly recommended to avoid nested loops and use Array Connections instead, which are data-flow counterparts of for-each loops from the low level programming languages. For conditions, there is no if-then-else construct anymore. There are Conditional Connections instead (data may flow or not), or – for more complex tasks – Variant Macrofilters. The former can be used to skip a part of a program when some data is not available, the latter allow you to create subprograms that have several alternative paths of execution. Finally, there are no variables, but data is transmitted through (usually unnamed) connections. Moreover, Global Parameters can be used to create named values that need to be used in many different places of a program, and Macrofilter Registers can be applied to program complex behaviors and store information between consecutive iterations of the program loop.
Please note, that even if you are an experienced C++ programmer, your work on machine vision projects will get a huge boost when you switch to FabImage Studio. This is because C++ is designed to be the best general purpose language for crafting complex programs with complicated control flow logic. FabImage Studio on the other hand is designed for one specific field and focuses on what is mostly important for machine vision engineers – the ability to experiment quickly with various combinations of tools and parameters, and to visualize the results instantly, alone or in combination with other data.
Here is a summary:
|Conditions (the if statement)||Conditional Connections, Variant Macrofilters||FabImage Studio is NOT based on the control flow paradigm. Instead, data flow constructs can be used to obtain very similar behavior. Conditional connections can be used to skip some part of a program when no data is available. Variant Macrofilters are subprograms that can have several alternative paths of execution. See also: Sorting, Classifying and Choosing Objects|
|Loops (the for and while statements)||Array Connections, Task Macrofilters||FabImage Studio is NOT based on the control flow paradigm. Instead, data flow constructs can be used to obtain very similar behavior. Array connections correspond to for-each style loops, whereas Task Macrofilters can be used to create complex programs with arbitrary nested loops.|
|Variables||Connections, Global Parameters, Macrofilter Registers||Data flow programming assumes no side effects. Computed data is stored on the filter outputs and transmitted between filters through connections. Global Parameters can be used to define a named value that can be used in many different places of a program, whereas Macrofilter Registers allow to store information between consecutive iterations.|
|Collections (arrays, std::vector etc.)||Arrays||The Array type is very similar to the std::vector<T> type from C++. This is the only collection type in FabImage Studio.|
|Templates||Generic Filters||As there can be arrays of many different types (e.g. RegionArray, IntegerArrayArray), we also need to have filters that transform arrays of different types. In C++ we have template metaprogramming and the STL library that is based on it. In FabImage Studio we have generic filters, which are very similar to simplified templates from C++ – the type parameter has to be defined when adding such filter to the program.|
|Functions, methods||Macrofilters||Macrofilters are subprograms, very similar to functions from C++. One notable difference is that macrofilters can not be recursive. We believe that this makes programs easier to understand and analyze.|
|GUI Libraries (MFC, Qt, WxWidgets etc.)||HMI Designer||If more complex GUI is needed, the algorithms created in FabImage Studio can be integrated with a GUI written in C++ through C++ Code Generator. See also: Handling HMI Events.|
|Static, dynamic libraries||Modules||Bigger projects require better organization. As you can create libraries in C++ which can be used in many different programs, you can also create modules (a.k.a. libraries of macrofilters) in FabImage Studio.|
|Breakpoints||The "Iterate Current Macrofilter" command (Ctrl+F10).||As there are no side effects within macrofilters, there is no need to set breakpoints in arbitrary places. You can, however, run the program to the end of a selected macrofilter – just open this macrofilter in the Program Editor and use the "Iterate Current Macrofilter" command. The program will pause when it reaches the end of the selected macrofilter instance.|
|Threads||There are no threads in FabImage Studio. Instead, the filters utilize as many processors as possible internally and the HMI (end user interface) is automatically run in parallel and synchronized with the program loop.|
|Exceptions||Domain Errors, Conditional Outputs||Domain Errors signal unexpected conditions encountered during program execution. They cause the program to stop, so it is crucial to make sure they are not possible. Nevertheless, during development they provide important information about what has to be fixed. If an unexpected condition cannot be easily predicted with careful program construction, then conditional outputs are used and the Nil value is returned to signal failure of execution.|
Interoperability with C++
Having said, that you can solve even the most challenging machine vision tasks with the data-flow programming model, in real life you most often need to integrate the machine vision solution with a bigger system. This integration most often requires C++ or .NET programming. FabImage Studio comes with several features that make it possible:
- User Filters allow to add your own C++ code in the form of filters of FabImage Studio.
- C++ Code Generator allows to switch from the graphical environment of FabImage Studio to a C++ program based on the FIL.DLL library.
- .NET Macrofilter Interface Generator produces a .NET assembly (a .dll file) with methods corresponding to macrofilters of a program, thus providing a bridge between FabImage Studio and .NET technology
- The program files of FabImage Studio are based on textual formats. You can use your version control system to store them and monitor their history.
How to mark the end of a loop started with filters such as EnumerateIntegers or Loop?
This is by design different than in C++. The loop goes through the entire Task macrofilter, which is a logical part of a program. If you really need a nested loop (which is rare in typical machine vision projects), then create a Task macrofilter for the entire body of the loop. First of all, however, consider array connections. They allow for example to inspect many objects detected on a single image without creating an explicit loop.
Could you add a simple "if" filter, that takes a boolean value and performs the next filter only if the condition is met?
This would be a typical construct in the control-flow based programming languages. We do not what to mix different paradigms, because we must keep our software not too complicated. You can achieve the same thing by using the MakeConditional filter and passing data to the next filter conditionally then. If there is no appropriate data that could be used in that way, then a variant macrofilter might be an another solution.
How to create a variable?
There are no variables in data-flow. This is for the same reason you do not see variables on PCB boards or when you look at a production line in a factory. There is a flow instead and connections transmit data (or objects) from one processing element to another. If you need to store information between consecutive iterations, however, then also stateful filters (e.g. AddIntegers_OfLoop, macrofilter registers or appropriate functions in formula blocks can be used.
|Previous: Quick Start Guide for the Users of LabVIEW||Next: Deep Learning Service Configuration|