This example shows how to record images using different camera interfaces.
The program allows acquiring and saving images from cameras of different interfaces. The chosen camera can be changed while the program is running. The user can trigger acquisition manually or set it to recording mode where an image is acquired after every given period.
The program takes care of naming new image files to be saved on the disk. It has built-in mechanism to avoid overwriting previous files. While using the program the user can see a live image preview.
The interface consists of five panes. The pane Image Source Settings lists all possible image sources and allows the user to choose one of them. Only one source can be active at a time. Choosing a source which requires specifying a device address enables the "..." button next to it (as seen next to GigE Vision and GenICam GenTL). Clicking it opens a dialog where the user can choose the device.
The next pane, Saving image Settings, the user can specify where the images will be saved, the file format of them, and the name prefix. There are four available formats to choose: BMP, JPEG, PNG, TIFF. Additionally, the user can set the period between consecutive images to be saved in recording mode.
The third pane allows the user to start and stop recording or save only a single frame. It additionally shows the number of images saved during the current session.
The fourth pane is an image preview. The user can see a live feed of the camera.
The last pane has instructions how to use the program. Below that some of the error messages are displayed.
View of the HMI
Points of Interest
Due to its complexity the program requires more than basic knowledge of the software to comprehend. Among other things the program utilizes:
- multiple task macrofilters,
- error handlers ,
- registers ,
- loop generators,
- conditional execution and using conditional variables of filters.
Those will be explained in more detail in the following part.
The main part of the program is inside a task macrofilter MainLoop. The root of the program contains one MainLoop macrofilter and a Loop filter. This enables error handling and prevents the program from closing after encountering an error.
After entering MainLoop the program starts with checking the state of the radio buttons (GetImageSource macrofilter). In case of interfaces which require specifying the address (GigE and GeniCam) an additional check is performed. Not only the radio button should be selected but the address has to be not Nil. The checks are done using formulas - if the check fails the formula outputs a Nil string. At the end of the macrofilter the results of all the formulas are merged into an array, with Nil values being ignored. This results in an array which is either empty or has one value. The macrofilter outputs that string (or Nil) which will later be used to switch to the correct grabbing filter.
The next step is to check whether the image source has changed since the previous iteration. If it did, the program exits MainLoop back to Main, effectively starting again. The formula for this check takes into account that by default the image source is set to Nil. This part of the program is not critical for the operation of the program - it makes switching the cameras faster and avoids redundant image acquisition.
If the loop is continued the state of the HMI controls in Recording control section is read (SavingImageControl filter). Using registers the filter has information whether the program is in the recording mode. First the filter checks if the "Save single frame" button has been pressed. Next, in the formula, the filter checks whether the program is in recording mode.
To be in this mode either the "Start recording" button must have been pressed or the program was in this mode in the previous iteration. Additionally, the "Stop recording" must have not been pressed and the camera address must not be Nil.
If the program is in recording mode or the "Save single frame" button has been pressed the filter sets its output outSaveSingleFrame to true - otherwise it's set to false. The filter also enables and disables the aforementioned control button. Finally, in the filter there is an instance of the Loop filter. It keeps the program running while not connected to the camera.
The next filter in MainLoop is GrabAndSaveImage. As the previous filter it uses registers to store data from the previous iterations. First, the filter checks the current time and compares it with the time of the previous acquisition (which was stored in the register "LastSaveImageTime") calculating the difference between them. Then the program grabs image from the connected camera. The variant macrofilter GrabImage has separate variants for every possible image source. If no image could be grabbed the I/O error handler is run. In there an error message is displayed and the image source is set to Nil. If the image was acquired it is sent to MakeConditional filter.
The image is set to Nil if it is not going to be saved. The condition depends on several variables. The image is saved if the difference is greater than the specified period and the program is in recording mode or if the user pressed the "Save single frame" button. The conditional image is connected to the SaveGrabbedImage filter.
If image is not set to Nil the "SaveGrabbedImage" is executed. There the program gets current time and date and reads the value of the controls in "Saving Image Settings". Next, it creates a file path from those elements and checks if it is unique. Before exiting GrabAndSaveImage the program puts the time the last image was grabbed into the register "LastSaveImageTime". If the image is Nil, then "SaveGrabbedImage" is not run.
At the end of the iteration the program checks if the image source is Nil. Normally, that would happen when no source was selected in which case the iteration would have ended at the Exit filter. If the iteration lasted past that filter it means the selected camera could not connect or was disconnected. If the source is Nil the program displays an error message in the lower-right corner.
As previously mentioned, one of the reasons to put most of the program into a task macrofilter MainLoop was to allow error handling. This prevents the application from crashing after encountering an error. Information about error handlers and creating them is available in the Error Handling tutorial.
In this program there are 2 error handlers - one for input/output errors and one for system errors. System errors can happen when the computers does not have the appropriate third-party driver installed. IO errors happen when the user tries to connect to a disconnected camera.
Both error handling filters have identical contents. First an error message is shown in the HMI. The program then waits for one second and resets the state off all the radio buttons.
|TestFileExists||Checks if a given file is present.|
|JoinArrays||Concatenates the input arrays one after another.|
|GigEVision_GrabImage_WithTimeout||Use this filter if the trigger may be not coming for some time, while the application should be performing other operations continuously (e.g. processing HMI events), or when timeout condition on missing frame must be detected|
|Roseek_GrabImage||Captures images from a Roseek device.|
|Delay||Suspends the program workflow for inTime milliseconds.|
|Exit||If the specified condition is true, exits the macrofilter loop.|
|Smart_GrabImage||Captures an image from a smart camera using AvSMART interface. Allows for remote access to the runtime system.|
|Pylon_GrabImage_WithTimeout||Captures an image stream from a camera using Pylon library; returns Nil if no frame comes in the specified time.|
|CopyObject||Use this filter to create a source of data, e.g. that needs to be send to HMI or used in several places of a macrofilter.|
|CurrentDateTime||Returns a string containing the date time information in selected format and all of the date time data separately.|
|GetClockTime||Stops clock to measure performance.|
|WebCamera_GrabImage||Not recommended for industrial operation.|
|FlyCapture_GrabImage||Captures images from a Flir camera.|
|SynView_GrabImage_WithTimeout||Use this filter if the trigger may be not coming for some time, while the application should be performing other operations continuously (e.g. processing HMI events).|
|ConcatenateStrings||Joins two or more strings into a single one.|
|ChooseByPredicate||E.g. to choose GREEN color to visualize correct objects or RED to visualize defective ones.|
|ICImagingControl_GrabImage||Captures a frame from The Imaging Source cameras using ICImagingControl.|
|MakeConditional||Introduces conditional data flow on a condition defined by the user. This filter can be used to skip some parts of the program - e.g. when a detected object does not fulfill some quality criteria.|
|GetArrayElement_OrNil||Extracts a single element from an array at the specified index; returns NIL if the index is out of range.|
|Vimba_GrabImage||Captures an image from an Allied Vision camera.|
|Loop||Put this filter into a task that should have a loop, but does not have any other loop generators (e.g. GrabImage).|
|SaveImage||Saves an image to a file.|
|EnumerateIntegers||In each consecutive iteration produces a consecutive number from an arithmetic sequence.|
|GenICam_GrabImage_WithTimeout||Use this filter if the trigger may be not coming for some time, while the application should be performing other operations continuously (e.g. processing HMI events), or when timeout condition on missing frame must be detected.|
|XiApi_GrabImage||Captures an image from a XIMEA camera.|
|MergeIntoArray||Creates an array from all the non-Nil input elements.|
|Spinnaker_GrabImage||Captures images from a Flir camera using Spinnaker interface.|
|ICube_GrabImage||Captures an image from an ICube camera.|
|Thorlabs_GrabImage||Captures an image from a Thorlabs device.|