latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 1998, 1999, 2000, 2001 00003 * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany 00004 * 00005 * This file is part of the LTI-Computer Vision Library (LTI-Lib) 00006 * 00007 * The LTI-Lib is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public License (LGPL) 00009 * as published by the Free Software Foundation; either version 2.1 of 00010 * the License, or (at your option) any later version. 00011 * 00012 * The LTI-Lib is distributed in the hope that it will be 00013 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00014 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with the LTI-Lib; see the file LICENSE. If 00019 * not, write to the Free Software Foundation, Inc., 59 Temple Place - 00020 * Suite 330, Boston, MA 02111-1307, USA. 00021 */ 00022 00023 #ifndef _LTI_ARCHITECTURE 00024 #define _LTI_ARCHITECTURE 00025 00026 /** 00027 00028 \page architecture Architecture 00029 00030 00031 The LTI-Lib is easy to use due to the specification of a well-defined 00032 programming interface for all classes. The preservation of its 00033 consistency is partially achieved through the use of the 00034 PERL-script \c ltiGenerator. Based on a few rudimentary 00035 data provided by the programmer (like class name and parent class) 00036 this script builds some template files, containing all standard 00037 definitions (see \ref howtonew). After that, only the functionality 00038 needs to be implemented. This chapter explains all basic concepts 00039 required to understand the meaning of these classes. 00040 00041 \section arcFunctor Functors, parameters and states 00042 00043 Most algorithms require \e parameters, i.e. user defined values that 00044 modify its behavior. For example, the file name is a parameter of an 00045 image loader class, or the size of a filter kernel is a parameter of a 00046 convolution algorithm. 00047 00048 All algorithms in the LTI-Lib are encapsulated in so-called \e functor classes. 00049 They always enclose a class called \c parameters, that 00050 can be explicitely declared or just inherited from the parent class. 00051 00052 This means, when you use the LTI-Lib you do not call some functions or 00053 class methods with lots of confusing arguments, some meaning input 00054 data, others the output data, and additionally a (maybe too long) list 00055 of parameters for the algorithm. A default \c parameters object is 00056 usually set in the functor class, and the methods to call the 00057 functionality expect only the input data and the output objects where 00058 the results are going to be written. You can of course change the 00059 used parameters as you wish, in order to fit the functor's 00060 functionality to your own needs. 00061 00062 Example: 00063 00064 \code 00065 lti::cannyEdges canny; // an ltilib object to extract the edges 00066 // of a channel 00067 canny.apply(myChannel,myEdges); // extract the edges from myChannel, 00068 // and leave them in myEdges using a 00069 // canny functor. (default parameters used). 00070 00071 // now we want to do a similar task, but changing Canny's default parameters 00072 00073 lti::cannyEdges::parameters cannyParams; // our parameters object 00074 cannyParams.variance = 5; // change the variance used 00075 canny.setParameters(cannyParams);// and set the new parameters 00076 canny.apply(myChannel,myEdges); // now extract the new edges from myChannel, 00077 // and leave them in myEdges again. 00078 \endcode 00079 00080 The parameters of a functor have to be distinguished from its state, which 00081 consists of all those attributes of the class that are computed 00082 during the execution the algorithm, but are not directly required by the user. 00083 For the Motion History Images (lti::temporalTemplate) for 00084 example, the last presented image must be kept in order to compute the next 00085 iteration. This image is not a parameter, but a part of the functor's state. 00086 These concepts are shown following image: 00087 00088 \image html functor.png 00089 00090 \n 00091 00092 The user can change the behavior of the functor through the 00093 parameters. The functor can also have a state, that eventually (like 00094 the parameters) can also be saved. 00095 00096 There are several reasons for an independent lti::functor::parameters 00097 class. You can create several instances with different value sets and 00098 change at once the functionality of your functor with a simple \c 00099 setParameters(). You can load and save your parameters object in a 00100 file, or can give it to a graphical user interface where the user can 00101 choose between several values. The parameters-classes can also provide 00102 methods to find special configurations of parameters, or to check if the 00103 given values fulfill several conditions imposed by the algorithms. 00104 The parameters contain values directly specified by the user and they 00105 are never modified by the algorithms themselves. 00106 00107 An usual question is: why do I need to call the method \c getParameters() 00108 to get the parameters instance? would it not be faster if each functor-class 00109 had its own parameters instance that could be used directly?. 00110 00111 \image html paramhier.png 00112 00113 \n 00114 00115 The answer relies partially on memory management issues. It would be very 00116 expensive if all classes in the functor hierarchy would have an own instance 00117 of parameters, because all inherited parameter attributes would be present 00118 several times. With the functor hierarchy shown on the left side of 00119 the previous figure an instance of the functor 00120 lti::optimalThresholding would have two parameter objects: the one of 00121 its own with five attributes (\c precision and the four attributes of the 00122 parent class) and the parameters-instance of lti::thresholdSegmentation 00123 with its four attributes. In other words, the four attributes of the parent 00124 class are present twice! 00125 00126 To avoid this problem, there is only one instance of the parameters in 00127 the lti::functor class. Each class casts this instance to the proper 00128 parameters type using the overloaded method \c getParameters(). 00129 00130 Another important reason for the use of just one parameters-instance 00131 in the functor class appears when the inherited class calls methods 00132 of the parent classes, the later ones could not see the proper 00133 parameters-instance but only the own one, which could contain other values 00134 than those specified by the user. 00135 00136 The functionality of a functor is always accessed by the methods 00137 \c apply(). They expect input data, (usually \c const references to 00138 objects like matrices of images), and references to output objects 00139 (references to containers where the result is written). Other 00140 functor methods (the shortcuts) provide comfortable ways to access specific 00141 functionality. To load an image file, for example, image loaders 00142 provide the shortcut \c load that expects a file name and the image 00143 where the read image result should be written. Otherwise, you would require to 00144 create a parameters object, set there the file name, give this 00145 parameters-instance to the functor, and at last call the apply 00146 method: 00147 00148 \code 00149 // an image 00150 lti::image img; 00151 00152 // functor to load images in Windows BMP format: 00153 lti::loadBMP loader; 00154 00155 // parameters for the loader 00156 lti::loadBMP::parameters loaderParam; 00157 00158 // the file to load 00159 loaderParam.filename = "testimage.bmp"; 00160 00161 // load the image into img 00162 loader.setParameters(loaderParam); 00163 loader.apply(img); // load the image! 00164 \endcode 00165 00166 It is much easier and comfortable to employ following shortcut: 00167 00168 \code 00169 // an image 00170 lti::image img; 00171 00172 // functor to load images with Windows BMP format: 00173 lti::loadBMP loader; 00174 00175 // load an image 00176 loader.load("testimage.bmp",img); 00177 \endcode 00178 00179 All functors nevertheless provide an interface based on a 00180 \c parameters -object and \c apply -methods, in order to warrant more complex 00181 applications a uniform way to access the functionality of the functor. 00182 00183 There exist just one \c getParameters() -method per functor and it returns a 00184 \e constant reference to the parameters-instance, this due to the fact 00185 that the attributes of the parameters instance should not be changed by the 00186 functor itself. 00187 00188 Besides the parameters, a functor may have a state, where it stores 00189 information irrelevant for the user but necessary for later computations. 00190 An example for a functor with separated state and parameters is the 00191 lti::principalComponents (PCA) object. Here you find a parameter 00192 \c autoDim which indicates that another parameter 00193 \c resultDim should be detected automatically. In the \c apply method 00194 the value of \c resultDim stored in the internal parameters-instance remains 00195 unchanged, to respect the wishes of the users. 00196 The PCA computes a transformation matrix that is part of 00197 the functor's state. It is used later to linearly transform other vectors. 00198 This matrix is not something that the user usually gives directly, but after 00199 being computed, it can be saved and loaded together with other parts of the 00200 functor's state (this is done when you load or save the whole functor). 00201 In general, all functors with a state 00202 relevant for later computations can be saved and loaded, i.e. they overload 00203 the methods \c read and \c write. 00204 00205 \section arcIo Input and Output in the LTI-lib 00206 00207 Serializable objects in the LTI-Lib (i.e. objects that can be written 00208 or read from disk) never directly use \c std::fstream objects. The 00209 main reason is that we need to provide a way to support different file 00210 formats at the same time. The desired file format is determined 00211 through a so called lti::ioHandler. At this time there are two 00212 file formats. A Lisp-like one (lti::lispStreamHandler) writes or reads ASCII 00213 strings in or from a given stream, where different scopes are delimited with 00214 parenthesis. A binary format (lti::binaryHandler) produces shorter files 00215 and is faster to be read or written, but can not be edited by hand. 00216 00217 A uniform way to load or save LTI-Lib-objects and internal types (\c int , 00218 \c float , \c double , \c std::string, etc.) is provided through 00219 four global functions that passes them properly to a given lti::ioHandler. 00220 These are: 00221 00222 \code 00223 bool lti::write(ioHandler& handler, 00224 const T& data); 00225 00226 bool lti::read(ioHandler& handler, 00227 T& data); 00228 00229 00230 bool lti::write(ioHandler& handler, 00231 const std::string& name, 00232 const T& data, 00233 const bool complete=true); 00234 00235 bool lti::read(ioHandler& handler, 00236 const std::string& name, 00237 T& data, 00238 const bool complete=true); 00239 \endcode 00240 00241 The first two functions write or read the contents of an object of type 00242 \c T in or from the given \c ioHandler . The third and fourth methods 00243 write the data together with a name that identifies this object. To read 00244 the data, the given name must match the one used when the data was saved. 00245 00246 With a handler of type lti::lispStreamHandler following lines 00247 \code 00248 lti::write(handler,"a",5); 00249 lti::write(handler,"b",9); 00250 \endcode 00251 00252 produce the following output in the output stream associated with the handler: 00253 \code 00254 (a 5) 00255 (b 9) 00256 \endcode 00257 00258 The parenthesis around each line can be left out if the fourth parameter of 00259 the functions (\c complete ) is set to \c false . Note that the default 00260 value for this parameter is \c true. 00261 00262 The lti::lispStreamHandler can find an object using its name: 00263 \code 00264 int x,y; 00265 lti::read(handler,"a",x); 00266 lti::read(handler,"b",y); 00267 \endcode 00268 00269 After these lines it applies \c x==5 and \c y==9. Some 00270 \c ioHandler (for example lti::binaryStreamHandler ) require that the 00271 read order for different data matches the one used when writing. If this is 00272 not true, the read methods will return \c false . Other \c ioHandler 00273 (like lti::lispStreamHandler ) search for the data using the given name as 00274 key, so that you can use a different reading order. Following lines would 00275 also result in \c x==5 and \c y==9: 00276 00277 \code 00278 int x,y; 00279 lti::read(handler,"b",y); 00280 lti::read(handler,"a",x); 00281 \endcode 00282 00283 The \c ioHandler concept makes it possible to define new file formats 00284 \e without requiring to reimplement all read and write methods of the 00285 LTI-Lib classes. Due to the fact that the read and write methods use a 00286 relative rigorous syntax, it is also relative simple to parse the files. 00287 00288 Please note that the variables used in the previous examples could also have 00289 any other type defined in the LTI-Lib. All numerical standard types 00290 (\c int , \c double, etc.), the Standard Template Library (STL) types 00291 \c std::vector, \c std::list and \c std::map (if you include the 00292 file "\c ltiSTLIoInterface.h") and the most LTI-Lib functors, 00293 parameters and data structures can be serialized. 00294 00295 \subsection ioExample Example 00296 00297 How can I save and load some parameters in my program? 00298 00299 \code 00300 // ltilib functors and their parameters 00301 lti::csPresegmentation segmentor; 00302 lti::csPresegmentation::parameters segParam; 00303 00304 lti::orientationFeature orientor; 00305 lti::orientationFeature::parameters orientParam; 00306 00307 // ... initialize the parameters ... 00308 00309 // how can we write the parameters in a file named "param.txt"? 00310 lti::lispStreamHandler handler; // the stream handler 00311 std::ofstream out("param.txt"); // the std::fstream used 00312 00313 // if the output stream is ok, write the data 00314 if (out) { 00315 // the handler have to write the data using the stream "out": 00316 handler.use(out); 00317 00318 // write the parameters: 00319 lti::write(handler,"orientParam",orientParam); 00320 lti::write(handler,"segmentParam",segParam); 00321 lti::write(handler,"anInteger",5); 00322 } 00323 \endcode 00324 00325 And how can we read the data from "param.txt"? 00326 00327 \code 00328 std::ifstream in("param.txt"); 00329 00330 if (in) { 00331 int x; 00332 00333 handler.use(in); 00334 00335 // read the data 00336 lti::read(handler,"orientParam",orientParam); 00337 lti::read(handler,"segmentParam",segParam); 00338 lti::read(handler,"anInteger",x); 00339 } 00340 \endcode 00341 00342 You can find a hierarchical list of many functors in the LTI-Lib in the 00343 section \ref functors. 00344 00345 \section arcViewdraw Visualization Classes 00346 00347 Not everything in an image processing or computer vision library can be 00348 considered as functor. Examples for this are the so called drawing and 00349 visualization objects. 00350 00351 Drawing objects does not execute one algorithm. They provide different tools 00352 to draw simple geometric constructs on images or other output media. To use a 00353 drawing object you need to provide it with your \e canvas, i.e. you need to 00354 specify the image where you want to draw. This is done with the method 00355 \c use(). After that, you can choose the color you want to use with the 00356 method \c setColor(). All lines, circles or points you draw after this, 00357 will be painted using the given color. 00358 00359 Following example draws a circle and a line on a color image: 00360 00361 \code 00362 lti::image img(256,256); // our canvas 00363 00364 lti::draw<rgbPixel> drawing; // drawing tool 00365 00366 drawing.use(img); // where should "drawing" paint on? 00367 drawing.setColor(lti::Blue); // Blue color 00368 drawing.circle(lti::point(128,128),20,true)); // filled circle, radius 20 00369 drawing.setColor(lti::Red); // Red color 00370 drawing.line(10,10,128,128); // A red line 00371 \endcode 00372 00373 Viewer objects do not modify any data, but provide simple ways to visualize 00374 them. The presentation of the data persists as long as the viewer object 00375 exists. 00376 00377 You can show the previously drawn image with following code: 00378 00379 \code 00380 lti::viewer viewer("This is art"); // our viewer object 00381 viewer.show(canvas); // show our master piece 00382 getchar(); // just wait 00383 \endcode 00384 00385 Available viewers, drawing objects and other visualization tools in the LTI-Lib 00386 are summarized in the section \ref viewers 00387 00388 \section arcClassifiers Classifiers 00389 00390 Other important objects that do not fit into the functor paradigm 00391 are the classifiers. They provide methods to learn from data, and to use the 00392 learned information to analyze new data. There are different interfaces 00393 for the supervised and unsupervised classifiers. Both types can be categorized 00394 into instance classifiers that learn from single vectors (like traditional 00395 neural networks) and sequence classifiers that also considered time aspects 00396 (like Hidden Markov Models). 00397 00398 In the LTI-Lib all classifiers deliver the results using the same data 00399 structures lti::classifier::outputVector, so that the processing of 00400 their results does not depend on the specific classifier used. 00401 00402 More information about the classifier classes can be found in the sections 00403 \ref docuClassifiers and \ref classifiers. 00404 00405 */ 00406 00407 #endif 00408