LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiEdgeSaliency.h

00001 /*
00002  * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006
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 
00024 /*----------------------------------------------------------------
00025  * Project ....: LTI Digital Image/Signal Processing Library
00026  * file .......: ltiEdgeSaliency.h
00027  * authors ....: Stefan Syberichs
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 17.3.2000
00030  * revisions ..: $Id: ltiEdgeSaliency.h,v 1.8 2006/02/08 11:03:05 ltilib Exp $
00031  */
00032 
00033 
00034 #ifndef _LTI_EDGE_SALIENCY_H_
00035 #define _LTI_EDGE_SALIENCY_H_
00036 
00037 #include "ltiObject.h"
00038 #include "ltiMatrix.h"
00039 #include "ltiVector.h"
00040 #include "ltiSaliency.h"
00041 
00042 namespace lti {
00043 
00044   /**
00045    * A class for edge based strcutural saliency calculations.
00046    *
00047    * Structural Saliency as proposed by A. Shashua and S. Ullman
00048    * extracts salient information out of edge images. A salient
00049    * structure in our terms is a long line of pixels with low
00050    * curvation.  This modifier can be used to produce input data for a
00051    * feature map as well as a preprocessing stage for further
00052    * segmentation.  The methods work on binary (!) edge maps
00053    * (lti::channel or lti::channel8), where a white pixel should mark
00054    * an edge point and a black pixel is part of the background. Edge
00055    * data like that can be generated by the edge detectors lti::susanEdges
00056    * or lti::cannyEdges.
00057    * The behaviour of the edgeSaliency methods can be controled by 8
00058    * parameters in a very wide range, where the optimal values have to
00059    * be adapted to the actual problem.
00060    *
00061    * For more information see <em> A. Shashua, S.Ullman 1988: Structural
00062    * Saliency, Proceedings of the international conference on Computer
00063    * Vision, 482-488 (ISBN 0-8186-0883-8)</em>
00064    *
00065    * Usage:
00066    *
00067    * \code
00068    *  // ---- preparations to obtain binary edges --- //
00069    *
00070    *  lti::splitImageToRGB rgb;
00071    *  lti::channel8 R, G, B, edges;
00072    *  lti::image theimage;
00073    *
00074    *  // load an image
00075    *  ...
00076    *
00077    *  // rgb or any other channel split
00078    *  rgb.apply(theimage, R, G, B);
00079    *
00080    *
00081    *  lti::susanEdges susanedge;
00082    *  lti::susanEdges::parameters edgeparams;
00083    *
00084    *  edgeparams.gamma = 10;
00085    *  susanedge.setParameters(edgeparams);
00086    *
00087    *  // extract binary edges from red channel
00088    *  susanedge.apply(R, edges);
00089    *
00090    *  // --- actual saliency part --- //
00091    *
00092    *  lti::edgeSaliency sal;
00093    *  lti::channel salmap;
00094    *  lti::edgeSaliency::parameters salparam;
00095    *
00096    *  salparam.iterations = 20;
00097    *  salparam.couplingCenter = 0.2;
00098    *  salparam.couplingNeighbour = 0.0;
00099    *  salparam.rho = 0.6;
00100    *  salparam.initialSigma = 1.0;
00101    *  salparam.gamma = 0.5;
00102    *  salparam.curvationTable=lti::edgeSaliency::parameters::biased;
00103    *
00104    *  sal.setParameters(salparam);
00105    *
00106    *  sal.apply(edges, salmap);
00107    *
00108    *  // ready. the saliency map is in salmap now.
00109    *
00110    * \endcode
00111    */
00112   class edgeSaliency : public saliency {
00113   public:
00114 
00115     typedef vector<float> eVector;
00116 
00117     /**
00118      * the parameters for the class edgeSaliency
00119      */
00120     class parameters : public saliency::parameters {
00121     public:
00122 
00123       enum curvationType {standard, biased};
00124 
00125       /**
00126        * default constructor
00127        */
00128       parameters();
00129 
00130       /**
00131        * copy constructor
00132        */
00133       parameters(const parameters& other);
00134 
00135       /**
00136        * destructor
00137        */
00138       ~parameters();
00139 
00140       /**
00141        * returns name of this type
00142        */
00143       const char* getTypeName() const;
00144 
00145       /**
00146        * copy member
00147        */
00148       parameters& copy(const parameters& other);
00149 
00150       /**
00151        * returns a pointer to a clone of the parameters
00152        */
00153       virtual functor::parameters* clone() const;
00154 
00155       /**
00156        * write the parameters in the given ioHandler
00157        * @param handler the ioHandler to be used
00158        * @param complete if true (the default) the enclosing begin/end will
00159        *        be also written, otherwise only the data block will be written.
00160        * @return true if write was successful
00161        */
00162       virtual bool write(ioHandler& handler,const bool complete=true) const;
00163 
00164       /**
00165        * write the parameters in the given ioHandler
00166        * @param handler the ioHandler to be used
00167        * @param complete if true (the default) the enclosing begin/end will
00168        *        be also written, otherwise only the data block will be written.
00169        * @return true if write was successful
00170        */
00171       virtual bool read(ioHandler& handler,const bool complete=true);
00172 
00173 #     ifdef _LTI_MSC_6
00174       /**
00175        * this function is required by MSVC only, as a workaround for a
00176        * very awful bug, which exists since MSVC V.4.0, and still by
00177        * V.6.0 with all bugfixes (so called "service packs") remains
00178        * there...  This method is public due to another bug, so please
00179        * NEVER EVER call this method directly: use read() instead!
00180        */
00181       bool readMS(ioHandler& handler,const bool complete=true);
00182 
00183       /**
00184        * this function is required by MSVC only, as a workaround for a
00185        * very awful bug, which exists since MSVC V.4.0, and still by
00186        * V.6.0 with all bugfixes (so called "service packs") remains
00187        * there...  This method is public due to another bug, so please
00188        * NEVER EVER call this method directly: use write() instead!
00189        */
00190       bool writeMS(ioHandler& handler,const bool complete=true) const;
00191 #     endif
00192 
00193       // --------------------------------------------
00194       // the parameters
00195       // --------------------------------------------
00196 
00197       /**  A coupling constant for the parameter sigma. couplingCenter is
00198        *   the coupling value
00199        *   in case that the regarded pixel is an edge and the regarded
00200        *   neighbour is a background pixel. A non-zero value for
00201        *   <code> couplingCenter </code> provides the ability for
00202        *   the saliency algorithmn to close gaps in a line segment.
00203        *   reasonable values are
00204        *   <pre>
00205        *   0 <=  couplingCenter <= 0.7
00206        *   </pre>
00207        *   A high couplingCenter value will blur the resulting saliency map.
00208        *   The default is 0.0;
00209        */
00210       float couplingCenter;
00211 
00212       /** A coupling constant for the parameter sigma. CouplingNeighbour
00213        *  is the coupling value
00214        *  in case that the regarded pixel is a part of the background and
00215        *  the regarded neighbour is an edge pixel. A non-zero value for
00216        *  <code> couplingCenter </code> provides the ability for
00217        *  the saliency algorithmn to close gaps in a line segment.
00218        *  reasonable values are
00219        *  <pre>
00220        *  0 <=  couplingNeighbour <= 0.5
00221        *  </pre>
00222        *  Any non-zero will significantly blur the resulting saliency map.
00223        *  The default is 0.0
00224        */
00225       float couplingNeighbour;
00226 
00227       /**
00228        * the intial coupling constant for active orientation elements.
00229        *
00230        * in the initial computation step, all orientation elements
00231        * that are made up by two edge pixels are marked as <em>
00232        * active </em> by initialising them with <code> initialSigma
00233        * </code>.  <code> initialSigma </code> is normaly 1.0. Such
00234        * orientation elements, that are made up by one edge and one
00235        * background pixel are initialised with either
00236        * <code>couplingCenter</code> or <code>couplingNeighbour</code>.
00237        * The default is 1.0
00238        */
00239       float initialSigma;
00240 
00241       /** Number of updating iterations.
00242        *
00243        * Since the the updating procedure of the saliency activities
00244        * is implemented as a locally connected network, the saliency
00245        * map is calculated in a recursive manner. The result will
00246        * converge for an infinite number of iterations, but any number
00247        * of runs between 20 and 30 should be enough.  The default is 20.
00248        */
00249       int iterations;
00250 
00251       /**
00252        * Gap attenuation factor.
00253        *
00254        * The parameter rho is used to penalize the existance of long
00255        *  gaps in the regarded structures.  the factor rho is always
00256        *  associated to an orientation element, where the constant
00257        *  value 1.0 is assigned to a fully active element, and the
00258        *  value of <code>rho</code> to any other element. A small
00259        *  <code>rho</code> leads to a suppresion of fragmented
00260        *  structures.
00261        *
00262        *  Reasonable values are:
00263        *  <pre>
00264        *  0.1 <= rho <= 0.7
00265        *  </pre>
00266        *  The default is 0.4
00267        */
00268       float rho;
00269 
00270       /**
00271        * threshold for cutting off the saliency map.
00272        *
00273        * if <code>gamma</code> is non-zero, the all final saliency
00274        * values that are lower than gamma will be cut off (i.e. set to
00275        * black) in the resulting saliency map. This can be used to get
00276        * rid of weak, unsalient structures in the image.
00277        *
00278        * Reasonable values are:
00279        * <pre>
00280        * 0 <= gamma <= 0.5
00281        * </pre>
00282        * This paramter has no effect, if the map is not normalised !
00283        * The default is 0.5.
00284        */
00285       float gamma;
00286 
00287       /**
00288        * normalize the saliency map (recommended).
00289        *
00290        * the resulting map is normalised with regard
00291        * to the maximum value.
00292        * The map is normalised, if <code>normalise</code> is <code>true</code>.
00293        * The default is <code>true</code>
00294        */
00295       bool normalise;
00296 
00297       /**
00298        * binarise the resulting saliency map.
00299        * If normalisation and a reasonable gamma are chosen,
00300        * the rest of the saliency information is set to
00301        * 1.0 (or 255 respectively). Used as a preprocessing stage
00302        * for further segmentation (use with care!).
00303        * This parameter has no effect if the map is not normalised !
00304        * The default is <code>false</code>.
00305        */
00306       bool binarise;
00307 
00308       /**
00309        * type of curvation table.
00310        * The curvation factor between to orientation elements is used to
00311        * promote line elements with low curvation, or to penalize strong
00312        * curvations. Curvation in this manner means depends on the  angle
00313        * between two sucvcessive orientation elements according to:
00314        *
00315        * \f[ c=\exp\left(-\cfrac{2\alpha\tan(\alpha/2)}{\delta}\right)\f]
00316        * 0 < c < 1
00317        *
00318        * where <code>alpha</code> is the mentioned angle and delta the length
00319        * of an orientation element. The the shape of the curvation function
00320        * c strongly depends on the denominator delta, i.e. the way in which
00321        * <em>low</em> curvations are penalized.
00322        * Therefor, two curvation lookup tables have been provided with
00323        * two characteristic shapes:
00324        *
00325        * - <b>standard</b> curvation with <code>delta = 1</code> which
00326        *   penalizes low,  non-zeo curvations stronger than the
00327        *
00328        * - <b>biased</b> curvation, where <code>delta = 2</code>.
00329        *
00330        * The default is <code>edgeSaliency::parameters::standard</code>
00331        */
00332       curvationType curvationTable;
00333     };
00334 
00335     /**
00336      * default constructor
00337      */
00338     edgeSaliency();
00339 
00340     /**
00341      * copy constructor
00342      * @param other the object to be copied
00343      */
00344     edgeSaliency(const edgeSaliency& other);
00345 
00346     /**
00347      * destructor
00348      */
00349     virtual ~edgeSaliency();
00350 
00351     /**
00352      * returns the name of this type ("edgeSaliency")
00353      */
00354     virtual const char* getTypeName() const;
00355 
00356 
00357     /**
00358      * Applies structural saliency computation on-place.
00359      * @param srcdest channel8 with the source data (binary edges,
00360      *                black bakcground!).The result will be left here too.
00361      * @return true if successful, false otherwise.
00362      */
00363     bool apply(channel8& srcdest) const;
00364 
00365     /**
00366      * Applies structural saliency computation on-place.
00367      * @param srcdest channel8 with the source data (binary edges,
00368      *                black bakcground!).The result will be left here too.
00369      * @return true if successful, false otherwise.
00370      */
00371     bool apply(channel& srcdest) const;
00372 
00373     /**
00374      * Applies strcuctural saliency computation on-copy.
00375      * @param src channel8 with the source data (binary edges, black
00376      *                     background).
00377      * @param dest channel8 where the result will be left.
00378      * @return true if successful, false otherwise.
00379      */
00380     bool apply(const channel8& src,channel8& dest) const;
00381 
00382     /**
00383      * Applies strcuctural saliency computation on-copy.
00384      * @param src channel8 with the source data (binary edges, black
00385      * background)
00386      * @param dest channel where the result will be left.
00387      * @return true if successful, false otherwise.
00388      */
00389     bool apply(const channel& src,channel& dest) const;
00390 
00391     /**
00392      * Applies strcuctural saliency computation on-copy.
00393      * This is the fastest method, since all other apply
00394      * members refer to this method using additional casts or copy operations!
00395      * @param src channel8 with the source data (binary edges, black
00396      *            background)
00397      * @param dest channel8 where the result will be left.
00398      * @return true if successful, false otherwise.
00399      */
00400     virtual bool apply(const channel8& src, channel& dest) const;
00401 
00402     /**
00403      * copy data of "other" functor.
00404      */
00405     edgeSaliency& copy(const edgeSaliency& other);
00406 
00407     /**
00408      * returns a pointer to a clone of the functor.
00409      */
00410     virtual functor* clone() const;
00411 
00412     /**
00413      * returns used parameters
00414      */
00415     const parameters& getParameters() const;
00416 
00417 
00418   private:
00419 
00420     /**
00421      * the one and only saliency computation.
00422      * the local saliency values of each orientation element E_i
00423      * of each pixel of the image is update according to the
00424      * following equations:
00425      *
00426      * \code
00427      *
00428      * E_i(0) = sigma_i
00429      * E_i(n+1) = sigma_i + rho_i * max E_j(n) * curvation(i,j)
00430      *
00431      * \endcode
00432      *
00433      * where <code>sigma_i</code> is the appropriate sigma of an
00434      * orientation element, given by one of the parameters
00435      * <em>initialSigma</em>, <em>couplingCenter</em>, or
00436      * <em>couplingNeighbour</em> (for explanantion see parameter
00437      * class).  <code>rho_i</code> is the gap factor and E the
00438      * saliency activity.  The number of loops <code>n</code> is given
00439      * by the parameter <code>iterations</code>, where n=20 is a good
00440      * choice (The saliency will converge for an infinite number of
00441      * updates).
00442      */
00443     void updateSaliency(const channel8& src, channel& map) const;
00444 
00445     /**
00446      * Same thing as the update method above.
00447      * The <code>src</code> is casted to lti::channel8
00448      * to invoke the original update method.
00449      */
00450     void updateSaliency(const channel& src, channel& map) const;
00451 
00452     /**
00453      * returns a rho depending on sigma.
00454      *
00455      * If an edge element is <em>active</em>, i.e. if its sigma value
00456      * is non-zero, the function returns the value 1.0.  Otherwise,
00457      * the value specified by the parameter <code>rho<code> is
00458      * returned to penalize a <em>virtual</em>edge element.  <b> The
00459      * behaviour of this function is subject to change!<b> @param
00460      * sigma the sigma value to determine whether an element is
00461      * <em>active</em> or <em>virtual</em>.  @result 1.0 if the edge
00462      * is <em>active</em> or the parameter rho otherwise.
00463      */
00464     float rho(const float sigma) const;
00465 
00466     /**
00467      * returns a local curvation value.
00468      *
00469      * The curvation of two successive orientation elements i and j
00470      * is calculated according to:
00471      *
00472      * \f[ c=\exp\left(-\cfrac{2\alpha\tan(\alpha/2)}{\delta}\right)\f]
00473      * 0 < c < 1
00474      *
00475      * where <code>alpha</code> is the angle between the
00476      * elements i and j. <code>delta</code> is 1.0 (standard)
00477      * or 2.0 (biased).
00478      */
00479     float curvation(const int pi, const int pj) const;
00480 
00481     /**
00482      * biased curvation table
00483      */
00484     static float curvationLookupTable2[8][8];
00485 
00486     /**
00487      * standard curvation table
00488      */
00489     static float curvationLookupTable1[8][8];
00490 
00491     /**
00492      * radian angles
00493      */
00494     static float radAngles16[16][16];
00495 
00496     /**
00497      * geometric length
00498      */
00499     static float geometricLength[16];
00500 
00501     /**
00502      * get orientation
00503      */
00504     int getOrientation16(const point here, const point there) const;
00505 
00506     /**
00507      * get neighbour of a given point
00508      */
00509     point getNeighbour(const point here, const int direction) const;
00510 
00511     /**
00512      * orientation square mean
00513      */
00514     float orientationSquareMean(const int i, const int j)const;
00515   };
00516 }
00517 
00518 #endif

Generated on Sat Apr 10 15:25:24 2010 for LTI-Lib by Doxygen 1.6.1