GUI-Applications
One of ICL’s main features is it’s tight integration with the GUI
creation framework, which allows for intuitive and simple creation of
GUI-applications. In this section we will develop a simple viewer
application that grabs images from arbitrary image sources and
displays the image.
For a more general overview about the GUI framework, we recommend to
also study GUI Creation and Visualization Framework.
Simple Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | #include <ICLQt/Common.h>
GUI gui;
GenericGrabber grabber;
void init(){
grabber.init(pa("-i"));
gui << Image().handle("image") << Show();
}
void run(){
gui["image"] = grabber.grab();
}
int main(int n, char **args){
return ICLApp(n,args,"-input|-i(2)",init,run).exec();
}
|
Note
a documented version of this source code can be found below
A basic ICL GUI-application can be structured into three major
functions: main, init and run
main
This function simply creates an instance of type
ICLApplication (or short ICLApp). The ICLApp instance always
gets the following arguments:
- the program argument count the program
- argument list the program
- argument definition string (which can be set to “”, if program
argument support shall not be supported)
- an initialization function
- further functions, that are automatically distributed to extra threads
In fact, The ICLApp instances does a lot of work for you.
- it creates a QApplication
- it calls your initialization function before the QApplications
event-loop is entered
- it parses all program arguments (and notifies errors)
- it creates working threads for each given run-function
- it joins all threads before the internal Qt-event loop is shut
down.
init
This function is automatically invoked by the ICLApp
instance that was created in main. Here, the application and in
particular the GUI can be initialized. Program arguments can
also be used here.
run
This function is called in a loop in the applications working
thread. Normally run has the steps
- image acquisition
- image processing
- restult visualization
In the examples the images are visualized without any processing
Documented Example
First, we include the ‘care-free’-header
ICLQt/Common.h which includes all most common
ICL-headers. Please note, this header also includes all icl
sub-namespaces icl::utils, icl::math, etc. as well as
the std-namespace
#include <ICLQt/Common.h>
GUI gui;
GenericGrabber grabber;
We need a global GUI instance that is visible from your init- and
from your run-function. As you application normally has only one
global GUI instance, the use of a global variable is justifiable and
natural here.
#include <ICLQt/Common.h>
GUI gui;
GenericGrabber grabber;
The same is true for the image source of your application.
Here, we use an instance of type GenericGrabber,
which can be configured simply using program arguments
#include <ICLQt/Common.h>
GUI gui;
GenericGrabber grabber;
We use the init function for initialization of the
grabber and the GUI instance
void init(){
grabber.init(pa("-i"));
gui << Image().handle("image") << Show();
}
The grabber can be initialized directly with the given
program argument, which can be accessed by the utils::pa
function. pa gets one of the program argument’s
name aliases and optionally also the sub-argument index.
void init(){
grabber.init(pa("-i"));
gui << Image().handle("image") << Show();
}
now we have to create a GUI component for image
visualization. To this ends, we use ICL’s powerful
Qt-based GUI creation framework. Here, GUI components
can conveniently streamed into each other to create
complex GUIs, but also for simple GUI as necessary
in this example, it is convenient to use.
void init(){
grabber.init(pa("-i"));
gui << Image().handle("image") << Show();
}
The run function contains our processing loop which is
acutually very simple in this case. It just grabs a new
image and visualizes it with our image visualization GUI
component.
void run(){
gui["image"] = grabber.grab();
}
Here, we pass the next grabbed image from the grabber instance
directly to the visualization component
void run(){
gui["image"] = grabber.grab();
}
Finally, the main function creates an ICLApp instance and
returns the result of its ICLApplication::exec()-function. It
also specifies the list of allowed program arguments. In this case,
only a single argument is allowed, that gets two sub-arguments. The
“[m]”-prefix makes the argument mandatory
int main(int n, char **args){
return ICLApp(n,args,"-input|-i(2)",init,run).exec();
}
Compiling and Running
Again, you can set up you build-environment as described before. If your used ICL build does at least support Qt and
libjepg, you can run your application with
./application-name -input create lena
The program argument -input device-type device-info is used for
most ICL-applications. In combination with an instance of type
GenericGrabber, this enables you to create applications that are
able to work with arbitrary image sources. Here are some further
examples:
- -input create parrot
- uses a static hard-coded test image showing
a parrot as input. Each time, the GenericGrabber‘s grab-function is
called, the same image is returned.
- -input file image.pnm
- uses a constant image file as input
- -input file ‘images/*.jpg’
- uses all images as input that match the given pattern. Note: the
pattern is expanded internally, so you have to set it into tics (‘)
to avoid that the pattern is already expanded by your bash
- -input v4l 0
- This will use the first Video4Linux2-based camera (usually used
for webcams and builtin cameras) that is available
- -input dc 0
- This will use the first firewire-camera that is connected to your PC
as input
- -input video myvideo.avi
- This will grab images frame by frame from the given video file
Note
A complete list of supported device-types and their device
selection parameters is given in the GenericGrabber reference
(TODO: a link would be better here!).
Footnotes