This page refers to version 3 of SwisTrack. Unless you are still using this old version, you may want to read the documentation of the most recent version of SwisTrack.
Introduction
editSwisTrack is programmed in C++ and should compile on Windows, Linux, and MacOS platforms.
SwisTrack's is divided in three parts
- The tracking core that takes care of image acquisition and analysis
- A graphical user interface that provides tools for visualizing different steps in the tracking process
- A command line interface
The three parts are linked by an XML description that can be found in the file swistrack.exp in the SwisTrack directory. Here, the different processes in the tracking process are organized in components with different modes (see Using SwisTrack). For the component input suitable modes are for instance image acquisition from a camera or from a file.
Based on this description (which also specifies the parameter type, e.g. list or integer), the GUI provides appropriate controls for modifying each parameter and storing it to a configuration file, which is a subset of swistrack.exp (see for instance example.cfg in the example directory). Also, the GUI provides panels that allow changing parameters during tracking and observing their influence on the tracking result at the same time (see Using SwisTrack).
On the other hand, the structure defined in swistrack.exp should reflect the class hierarchy of the tracking core. As a rule of thumb, each component in swistrack.exp is encapsulated in its own class, whereas modes are implemented using switch statements in the class' member functions. Here, it is the duty of the programmer to verify in the constructor of each class, whether the current operational mode and its parameters are provided in the actual configuration file and throw an exception otherwise.
See Installing Swistrack for information about setting up a developer's environment.
Example
editThe <COMPONENTS> section in swistrack.exp describes the distinct tracking steps that are implemented in the tracking core and require parameter input from the user.
<COMPONENTS> <INPUT desc="Input"/> <SEGMENTER desc="Segmenter"/> <SEGMENTERPP desc="Segmenter Post-Processing"/> <PARTICLEFILTER desc="Particle Filter"/> <MASK desc="Mask"/> <TRACKER desc="Tracker"/> <CALIBRATION desc="Calibration"/> <OUTPUT desc="Output"/> </COMPONENTS>
The <SEGMENTER> section for instance might have 2 modes (in this example)
<SEGMENTER mode="0" desc="Static Background, fixed threshold" long="The image is segmented by subtracting a static background image from every frame in the video. The 'Threshold' determines the minimal difference for the gray value of an object to be recognized, and 'Max. Number' is the maximal number of contours processed (sorted by size)."> <THRESHOLD desc="Threshold" type="integer" min="1" max="150" variable="1">20</THRESHOLD> <FIXED desc="Fixed" type="boolean" variable="1">0</FIXED> <BGIMAGE desc="Background Image" type="open" param="*.bmp">example/bg.bmp</BGIMAGE> </SEGMENTER> <SEGMENTER mode="1" desc="Running Average" long="The image is segmented by subtracting a static background image from every frame in the video. The 'Threshold' determines the minimal difference for the gray value of an object to be recognized, and 'Max. Number' is the maximal number of contours processed (sorted by size). 'Alpha' is the speed of the exponential averager."> <THRESHOLD desc="Threshold" type="integer" min="1" max="150" variable="1">20</THRESHOLD> <ALPHA desc="Averaging Speed" type="double" min="0" max="1" variable="1">0.02</ALPHA> </SEGMENTER>
Here mode 0 has three parameters (<THRESHOLD>, <FIXED>, and <BGIMAGE>), whereas mode 1 has two parameters (<THRESHOLD>,<ALPHA>), that are of different type. For instance the type "open" of <BGIMAGE> with attribute param="*.bmp" tells the GUI to use an Open File control (the developer should reserve a string variable in its application).
In the source code, the segmenter component can be found in the class Segmenter (segmenter.cpp, segmenter.h). The constructor then needs to look like
if(!IsAttrByXPath(cfgRoot,"/CFG/COMPONENTS/SEGMENTER","mode")) throw "[Segmenter::Segmenter] Segmenter mode undefined (/CFG/COMPONENTS/SEGMENTER)"; mode=GetIntAttrByXPath(cfgRoot,"/CFG/COMPONENTS/SEGMENTER","mode"); switch(mode) { case 0 : { CreateExceptionIfEmpty(cfgRoot,"/CFG/SEGMENTER[@mode='0']"); CreateExceptionIfEmpty(cfgRoot,"/CFG/SEGMENTER[@mode='0']/BGIMAGE"); CreateExceptionIfEmpty(cfgRoot,"/CFG/SEGMENTER[@mode='0']/THRESHOLD"); CreateExceptionIfEmpty(cfgRoot,"/CFG/SEGMENTER[@mode='0']/FIXED"); } case 1 : { CreateExceptionIfEmpty(cfgRoot,"/CFG/SEGMENTER[@mode='1']"); CreateExceptionIfEmpty(cfgRoot,"/CFG/SEGMENTER[@mode='1']/THRESHOLD"); CreateExceptionIfEmpty(cfgRoot,"/CFG/SEGMENTER[@mode='1']/ALPHA"); } default : throw "[Segmenter::Segmenter] Segmenter mode not implemented"; } SetParameters();
The parameters themselves are queried in the member function SetParameters(), which will be called whenever the user changes parameters during run-time.
Setting up your Developer Environment
editAfter downloading all necessary library packages (don't forget to compile them using your development environment), create a project for the SwisTrack core. Then create a project for the SwisTrack GUI, which links the core together with the other libraries. Make sure that you compile both projects as Multithreaded DLL.
Libraries
editYou will need to link the following libraries
- libxml++.lib
- libxml2.lib
- wxbase26_net.lib
- wxmsw26_adv.lib
- wxmsw26_core.lib
- wxbase26.lib
- wxtiff.lib
- wxjpeg.lib
- wxpng.lib
- wxzlib.lib
- wxregex.lib
- wxexpat.lib
- winmm.lib
- comctl32.lib
- rpcrt4.lib
- wsock32.lib
- oleacc.lib
- odbc32.lib
- objecttracker.lib
- 1394camera.lib
- cv.lib
- highgui.lib
- cxcore.lib
- vispolygon_dll.lib
- libgeom_dll.lib
Contributing components and modes
editThis section addresses how to extend SwisTrack's core functionality by extending a component by a new mode or by adding a new component.
Extending a component by a new mode
edit- Add a new section into swistrack.cfg and set the mode attribute to a number not yet used. Also specify the mode's description and its parameters
- Add your mode into the switch(mode) statement in the constructor of the class that represents the component you want to extend, and throw exceptions for each missing parameter
- Define appropriate variables in the private section in the class's interface (to be found in .h file)
- Add your mode into the switch(mode) statement in the SetParameters() member function to fetch the parameters from the XML description
- Go through each member function of the class that you are extending and add code into the switch statement so to implement the functionality that you have in mind. If some of the functionality is redundand, you might want to put your 'case' statement under a case that represents your functionality and remove its 'break;' statement (don't forget to add a break; in your case though)
Adding a new component
edit- Have a look at other components to see how they are implemented
- Inherit your class from the 'Component' class, including component.h also includes some handy macros that you need for accessing the XML structure
- Your class should be instantiated in the class that is above your component; in turn, your class needs to instantiate the class that is below your component in the functional hierarchy