latest version v1.9 - last update 10 Apr 2010 |
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