CVR-Lib last update 20 Sep 2009

cvrArchitecture.h

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

Generated on Sun Sep 20 22:07:58 2009 for CVR-Lib by Doxygen 1.5.8