Concepts and Ideas
Directory- and Library-Hierarchy
The bias library is currently divided into a number of sublibraries. Each is compiled from the files in separate subdirectories. These sublibraries can be clustered into two main categories, the
- base libraries, which should have no dependencies to other BIAS libraries and minimal dependencies to other third party libraries, and the
- remaining libraries, where a little more relaxed approach regarding dependencies is chosen.
Building one big "libbias.so" is deprecated. Please add dependencies to the individual libraries you really need, instead. You can emulate the behavior of LIBBIAS adding dependencies to all BIAS libraries. They are stored in BIAS_LIBRARIES if you use CMake and BIAS' find script.
All base libraries reside in the common subdirectory Base. Currently 5 diferent base libraries exist, namely
- libBIASImageBase: It provides basic operations on images for e.g. storing and the most simple operations (i.e. operations that do only need to access one pixel at a time, f.e. thresholding). The more complex operations on images can be found in the libBIASFilter library, which does not belong to the base libraries. Very few external dependencies exists, which can all be excluded using appropriate build options.
- libBIASMathBase: It provides basic matrix, vector and tensor operations as well as a class for generating random numbers with different distribution functions. Most important is, that no semantic is implemented in the libBIASMathBase library. Furthert on there is no dependency to external libraries although some of our classes are derived from the matrix and vector classes from the TNT library. The code from the TNT library is however included in BIAS. There are no dependencies to this libary.
- libBIASGeometryBase: In this library the matrices, vectors and tensors from the libBIASMathBase are filled with semantic, providing classes for fundamental matrices, trifocal tensors, homgenous points, etc. These classes do not know much mathematic algorithm (f.e. SVD), since libBIASGeometryBase does not depend on any other library but libBIASMathBase.so.
- libBIASDebug: This is a a library for basic debugging functions. It contains header files with helper classes, macros and functions for debugging and profiling/timing. Most of this functionality vanishes, if the BIAS_DEBUG preprocessor flag is undefined (normaly, it is defined in bias_config.h).
- libBIASImageUtilsBase: Library which contains utility classes for images such as drawing in images and pixelwise operations.
- libBIASCommon.so: Contains XML I/O handling, Win32 compatibility fucntions, some Utility functins including Filename string handling and the getopt command line parser.
All libaries not belonging to the base libraries are located in directory directly in the toplevel directory. Currently
- libBIASFeatureDetector: Detectors for intensity features such as Harris, and KLT. But also detektors for connected regions, checkerboards and contours.
- libBIASFilter: Contains image filters for gradient image computation, morphological operations, smoothing, etc...
- libBIASGeometry: Most of the classes in this libraries are derived from base classes in the libBIASGeometryBase library and provide some enhanced functionality (e.g. decomposition using SVD).
- libBIASGui: Consists of two parts: The first provides a simple mechanism to display an image without building a real gui application using callback functions (Gui* classes). The second provides some helper classes for building propper gui applications using wxWidgets (ImageCanvas and ParamGUI).
- libBIASGLviewer: Contains OpenGL rendering functions. Connected to libBIASOpenGLFramework
- libBIASOpenGLFramework: Contains a GLSL shader computation framework, abstracting from the hardware issues.
- libBIASImage: Contains convenient functions for working with images, e.g. 2 pyramid image classes, histogram classes, and a convenient class for the usage of meta data with images.
- libBIASMatcher2D: Contains classes for solving the image correspondence problem (e.g. SSD, NCC, KLT).
- libBIASMathAlgo: Contains wrapper classes for more complex mathematical algorithms like SVD, Levenberg-Marquardt, ... Most of theses algorithms are only provided when BIAS is used together with third party libraries like LAPACK or GSL.
- libBIASNetworkComm: Network communication library for TCP and UDP connections
- libBIASStateEstimator: Contains classes for the state estimation problem, like Kalman filter, particle filter, and condensation.
- libBIASUtils: Contains useful helper classes for handling parameters, for generation of ground truth image matches with additional noise, ...
- Tools: Contains nice little stand-alone tools like an image viewer biasview(wx), a conversion tool, and so on
The separation into math and geometry seems somewhat strange at first glance, but has some important advantages:
- The semantics are first introduced in the geometry libraries. This allows for extremly lean matrix and vector classes.
- Constraints to certain entities (i.e. orthogonality in RMatrix) do not inhibit the general use of the more generic entity (i.e. matrix).
Templates are used to minimize the implementation overhead while at the same time providing a wider range of available specializations.
- We decided to use explicit template instantiation (also called Cfront model). See info gcc for detailed description of the different instantiation models. The main advantage is the reduced compile time for applications.
- When using explicit template instantiation, the programmer of the library decides for what classes the template is instantiated. At the moment the explicit instantiation takes place either in the *.cpp files of each class or in a special file called Instantiation.cpp.
- Because we tried to optimize our library with respect to speed, we only accept basic data types as specialization for the image and math related classes. Performance measurements revealed that the constructor of Image<class RGB> is approximate 100 times slower than Image<unsigned char>, when the class RGB consists of three unsigned char members and has an empty inline constructor. This is mainly a result of the fact, that the constructor is called for every pixel in the first case, while a single call to malloc/new is sufficient in the latter case.
- In order to reduce compile time of the BIAS libraries, the instantiation of image classes exists through options for each basic type.
- At the moment an instance of Image<std::complex<double> > exists. This is contradictory to the above stated basic ideas. It most probably will be removed in the future. A good way confirming to our instantiation policy to allow images with complex content would be to take an Image<double> with channel count 2 and introduce a new color model CM_Complex.
C-Style Functions / Static Functions
- Generally BIAS is an C++ library and hence no (or at least very little) C-style functions exist. Some functionality does not necessarily need to be implemented as a C++ class, e.g. when no class memeber variables are needed. In such cases we use wrapper classes to group this functions (e.g. BIAS::ImageConvert). There is a single exception from this rule: The wrappers implemented for old Fortran code in Lapack.hh and Minpack.hh (lapack/minpack). This may also change in the future.
- Static functions are only used, when absolutly necessary, i.e. when a function pointer is needed. Again there are some exceptions to this rule: All members of the classes BIAS::ImageIO, BIAS::ImageDraw and BIAS::ImageConvert are static since in this case the classes are only used to group C-style functionality.
- Debug levels in short (for more details see Conventions):
- All classes that should be debugged are inherited from Debug.
- Debug operations (output, assertions) disappear when CMake flag BIAS_DEBUG is not set.
- Error messages relevant for the developers can be produced with macro BIASERROR.
- Status messages, warnings and debug information can be printed according to different debug levels if BIAS_DEBUG is set.
- Hierarchical debug levels are set locally/globally
Efficiency is the first priority on which the design of the BIAS libraries is based:
- Virtual functions are somewhat slow, because it is decided at runtime which function gets called. Hence the use of virtual functions is avoided whenever possible. This applies mainly to functions which are called very frequently.
- Some computations are cached within certain classes. Since we often compute some object (e.g. a PMatrix) once and use it several times afterwards without modification, it is efficient to cache computations needed in that object, such as a decomposition or pseudo-inverse of a matrix. However, an explicit notification becomes necessary, when the data fields have changed and the cache becomes invalid. The concept here is that validity is only checked in BIAS_DEBUG mode (if data is corrupt program aborts) and assumed otherwise.
- Only basic data types are allowed as template instantiations for images and matrices. See Templates for details.
- Generally our matrix classes have no Invert() function. This results from two facts.
- The matrix classes reside in the Base/Math directory and hence have no dependency to mathematical algorithms, like e.g. SVD.
- The presents of an (most probably inefficient) function invert in every matrix class tempts the programmer to write inefficient code.
Operators do not belong to classes, because
- it is not allways clear to which class an operator should belong (e.g. Matrix Vector multiplication).
- it causes problems when using inheritance and overwriting operators. It can happen, that some operators from the father class are no longer available if a single operator is overwritten.
Tools and Utils
What is the difference between tools and utils?
- Tools are small standalone applications like image viewers, converters, filters, and so on.
- Utils are helper classes dealing with a variety of problems, f.e. a class dealing with the management of parameters to complex applications.
The aim for the future is that all basic data containing classes are able to write and read their data from and to a file. The data file format is set to XML.
- All classes with xml i/o support should be derived from the class "Base/Common/XMLBase". Override XMLGetTopLevelName that it returns a tag identifying the class, e.g. "FeaturePoint". XMLAdd and XMLWrite use this function to generate the toplevel node of you object. Override XMLFill, to fill the data of (*this) into a XML-tree, where the top level node is already created. Then call XMLWrite to write the object to an XML file or XMLAdd(n) to attach the object to a node n of an existing xml structure. Given a valid xml file, you can call XMLRead to read the xml file into the current object, this calls your specialization of XMLReadObject.
- The class XMLIO is a wrapper of the libXML2 which is needed at least in version 2.5.10. It supports building and accessing an XML-tree in an easy way and should be used when overwriting XMLFill.