latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 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-Lib: Image Processing and Computer Vision Library 00026 * file .......: ltiCannyEdges.h 00027 * authors ....: Christian Harte 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 19.7.2002 00030 * revisions ..: $Id: ltiCannyEdges.h,v 1.12 2006/02/07 18:34:34 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_CANNY_EDGES_H_ 00034 #define _LTI_CANNY_EDGES_H_ 00035 00036 #include "ltiEdgeDetector.h" 00037 #include "ltiNonMaximaSuppression.h" 00038 #include "ltiColorContrastGradient.h" 00039 #include "ltiArctanLUT.h" 00040 00041 namespace lti { 00042 /** 00043 * The Canny Edge Detector is a standard algorithm, designed to detect 00044 * "optimal" edges. Almost every image processing book (e.g. Sonka et.al 00045 * Image Processing, Analysis and Machine Vision) explains the details for 00046 * the algorithm. 00047 * 00048 * As all other edge detectors in this Library, the colors for the edges and 00049 * background are specified in the parameters (see 00050 * lti::edgeDetector::parameters) 00051 * 00052 * The construction of the first cannyEdges functor in your 00053 * application will take some time to initialize a Look-Up-Table 00054 * that allows a much faster edge detection later (about 0.13 seconds 00055 * on a Pentium III, 450MHz). The LUT will require about 1MB. 00056 * Please see lti::arctanLUT for more information. 00057 * 00058 * You can also choose between the "classic" simple gradient operator, 00059 * which considers only two neighbors at each axis \c x and \c y or the more 00060 * accurate gradient kernels (see lti::gradientKernelX). In the latter 00061 * mode, the edge detection is about a factor 2 slower. 00062 * 00063 * For color images the color contrast gradient is used. 00064 * 00065 * @see lti::nonMaximumSuppression 00066 * @see lti::colorContrastGradient 00067 * @see lti::edgeDetector 00068 */ 00069 class cannyEdges : public edgeDetector { 00070 public: 00071 /** 00072 * the parameters for the class cannyEdges 00073 */ 00074 class parameters : public edgeDetector::parameters { 00075 public: 00076 /** 00077 * default constructor 00078 */ 00079 parameters(); 00080 00081 /** 00082 * copy constructor 00083 * @param other the parameters object to be copied 00084 */ 00085 parameters(const parameters& other); 00086 00087 /** 00088 * destructor 00089 */ 00090 ~parameters(); 00091 00092 /** 00093 * returns name of this type 00094 */ 00095 const char* getTypeName() const; 00096 00097 /** 00098 * copy the contents of a parameters object 00099 * @param other the parameters object to be copied 00100 * @return a reference to this parameters object 00101 */ 00102 parameters& copy(const parameters& other); 00103 00104 /** 00105 * copy the contents of a parameters object 00106 * @param other the parameters object to be copied 00107 * @return a reference to this parameters object 00108 */ 00109 parameters& operator=(const parameters& other); 00110 00111 00112 /** 00113 * returns a pointer to a clone of the parameters 00114 */ 00115 virtual functor::parameters* clone() const; 00116 00117 /** 00118 * write the parameters in the given ioHandler 00119 * @param handler the ioHandler to be used 00120 * @param complete if true (the default) the enclosing begin/end will 00121 * be also written, otherwise only the data block will be written. 00122 * @return true if write was successful 00123 */ 00124 virtual bool write(ioHandler& handler,const bool complete=true) const; 00125 00126 /** 00127 * read the parameters from the given ioHandler 00128 * @param handler the ioHandler to be used 00129 * @param complete if true (the default) the enclosing begin/end will 00130 * be also written, otherwise only the data block will be written. 00131 * @return true if write was successful 00132 */ 00133 virtual bool read(ioHandler& handler,const bool complete=true); 00134 00135 # ifdef _LTI_MSC_6 00136 /** 00137 * this function is required by MSVC only, as a workaround for a 00138 * very awful bug, which exists since MSVC V.4.0, and still by 00139 * V.6.0 with all bugfixes (so called "service packs") remains 00140 * there... This method is also public due to another bug, so please 00141 * NEVER EVER call this method directly: use read() instead 00142 */ 00143 bool readMS(ioHandler& handler,const bool complete=true); 00144 00145 /** 00146 * this function is required by MSVC only, as a workaround for a 00147 * very awful bug, which exists since MSVC V.4.0, and still by 00148 * V.6.0 with all bugfixes (so called "service packs") remains 00149 * there... This method is also public due to another bug, so please 00150 * NEVER EVER call this method directly: use write() instead 00151 */ 00152 bool writeMS(ioHandler& handler,const bool complete=true) const; 00153 # endif 00154 00155 // ------------------------------------------------ 00156 // the parameters 00157 // ------------------------------------------------ 00158 00159 /** 00160 * Variance for the Gaussian to smooth the image. 00161 * (see also gaussKernel1D<ubyte>::gaussKernel1D()) 00162 * 00163 * Default value: 1.0 00164 */ 00165 float variance; 00166 00167 /** 00168 * Size of the Gaussian kernel used to smooth the image 00169 *(see also variance). 00170 * 00171 * Set to zero if you don't want any smoothing. 00172 * 00173 * Default value: 7 00174 */ 00175 int kernelSize; 00176 00177 /** 00178 * If a pixel is detected as part of an edge (a response higher 00179 * than thresholdMax), its neighbors are consider also edges if their 00180 * values are higher than the given percentage of thresholdMax 00181 * (i.e. higher than thresholdMax*thresholdMin) 00182 * 00183 * This value must be between 0.0 and 1.0 00184 * 00185 * Default Value: 0.5 00186 */ 00187 float thresholdMin; 00188 00189 /** 00190 * If an edge response is higher than this value, those pixels will be 00191 * definite an edge. This value MUST be between 0 and 1.0. 00192 * 00193 * Please note that the older value range between 0 and 255 is 00194 * deprecated. 00195 * 00196 * Default Value: 0.04f; 00197 */ 00198 float thresholdMax; 00199 00200 /** 00201 * Parameters for gradient computation. 00202 * 00203 * To provide more alternatives to the gradient computation, the 00204 * lti::gradientFunctor is used. Here you can select all options 00205 * available for that functor. 00206 * 00207 * The default behaviour is to use the 00208 * lti::gradientFunctor::parameters::Difference kernel, which is the 00209 * fastest but also the less precise. You can use the optimal 00210 * kernels if you require a more stable orientation detection. 00211 * 00212 * Default value: Difference mode (fast gradient computation) 00213 * 00214 * @see lti::gradientFunctor 00215 */ 00216 colorContrastGradient::parameters gradientParameters; 00217 }; 00218 00219 /** 00220 * default constructor 00221 */ 00222 cannyEdges(); 00223 00224 /** 00225 * constructor with parameters 00226 */ 00227 cannyEdges(const parameters& thePars); 00228 00229 /** 00230 * copy constructor 00231 * @param other the object to be copied 00232 */ 00233 cannyEdges(const cannyEdges& other); 00234 00235 /** 00236 * destructor 00237 */ 00238 virtual ~cannyEdges(); 00239 00240 /** 00241 * returns the name of this type ("cannyEdges") 00242 */ 00243 virtual const char* getTypeName() const; 00244 00245 /** 00246 * operates on the given %parameter. 00247 * @param srcdest channel8 with the source data. The result 00248 * will be left here too. 00249 * @return true if apply successful or false otherwise. 00250 */ 00251 virtual bool apply(channel8& srcdest) const; 00252 00253 /** 00254 * operates on the given %parameter. 00255 * @param srcdest channel with the source data. The result 00256 * will be left here too. 00257 * @return true if apply successful or false otherwise. 00258 */ 00259 virtual bool apply(channel& srcdest) const; 00260 00261 /** 00262 * operates on a copy of the given %parameters. This one is the fastest, 00263 * because it won't require casting the channel to any other type. 00264 * 00265 * @param src channel8 with the source data. 00266 * @param dest channel8 where the result will be left. 00267 * @return true if apply successful or false otherwise. 00268 */ 00269 virtual bool apply(const channel8& src,channel8& dest) const; 00270 00271 /** 00272 * compute the canny edges for the given source channel. 00273 * The found edges will be left on the edges channel, and the 00274 * orientation angle of the edges (that can be used in other functors, like 00275 * the hough transform) is left on the orientation channel. 00276 * 00277 * @param src channel8 with the source data. 00278 * @param edges channel8 where the result will be left. 00279 * @param orientation channel where the orientation for the channel will 00280 * be left. 00281 * @return true if apply successful or false otherwise. 00282 */ 00283 virtual bool apply(const channel8& src, 00284 channel8& edges, 00285 channel& orientation) const; 00286 00287 00288 /** 00289 * operates on a copy of the given %parameters. 00290 * @param src channel with the source data. 00291 * @param dest channel where the result will be left. 00292 * @return true if apply successful or false otherwise. 00293 */ 00294 virtual bool apply(const channel& src,channel& dest) const; 00295 00296 00297 /** 00298 * operates on a copy of the given %parameters. 00299 * @param src channel with the source data. 00300 * @param dest channel where the result will be left. 00301 * @return true if apply successful or false otherwise. 00302 */ 00303 virtual bool apply(const channel& src,channel8& dest) const; 00304 00305 /** 00306 * compute the canny edges for the given source channel. 00307 * The found edges will be left on the edges channel, and the 00308 * orientation angle of the edges (that can be used in other functors, like 00309 * the hough transform) is left on the orientation channel. 00310 * 00311 * @param src channel with the source data. 00312 * @param edges channel8 where the result will be left. 00313 * @param orientation channel where the orientation for the channel will 00314 * be left. 00315 * @return true if apply successful or false otherwise. 00316 */ 00317 virtual bool apply(const channel& src, 00318 channel8& edges, 00319 channel& orientation) const; 00320 00321 /** 00322 * Strictly speaking, this method does not do a Canny Edge 00323 * Detection any more, but, because of the strong similarity with 00324 * the Canny later stages, it is provided here. 00325 * 00326 * The problem lies in the definition of the "gradient" for a 00327 * color channel. Here, the approach introduced in A. Cumani, 00328 * "Edge Detection in Multispectral Images", Technical Report, 00329 * Istituto Elettrotecnico Nazionale "Galileo Ferraris", 1989 is 00330 * followed. 00331 * 00332 * With this approach, instead of the usual gradient, the maxima of the 00333 * contrast function are searched. The contrast function defines 00334 * the direction in the (x,y) plane at which the contrast change is 00335 * maximal. See lti::colorContrastGradient for more information. 00336 * 00337 * The Canny-typical non-maxima suppression procedure is applied on the 00338 * contrast result. 00339 * 00340 * @param src image with the source data. 00341 * @param dest channel where the result will be left. 00342 * @return true if apply successful or false otherwise. 00343 */ 00344 virtual bool apply(const image& src,channel8& dest) const; 00345 00346 /** 00347 * operates on a copy of the given %parameters. 00348 * @param src image with the source data. 00349 * @param dest channel where the result will be left. 00350 * @param orientation channel where the orientation for the channel will 00351 * be left. 00352 * @return true if apply successful or false otherwise. 00353 */ 00354 virtual bool apply(const image& src, 00355 channel8& dest, 00356 channel& orientation) const; 00357 00358 /** 00359 * Compute the edges for the red, green and blue components of the image 00360 * and leave the result in each channel of image. 00361 * @param srcdest image with the source data. The result 00362 * will be left here too. 00363 * @return true if apply successful or false otherwise. 00364 */ 00365 virtual bool apply(image& srcdest) const; 00366 00367 /** 00368 * Compute the edges for the red, green and blue components of the image 00369 * and leave the result in each channel of the destination image. 00370 * @param src image with the source data. 00371 * @param dest image where the result will be left. 00372 * @return true if apply successful or false otherwise. 00373 */ 00374 virtual bool apply(const image& src,image& dest) const; 00375 00376 /** 00377 * Strictly speaking, this method does not do a Canny Edge 00378 * Detection any more, but, because of the strong similarity with 00379 * the Canny later stages, it is provided here. 00380 * 00381 * The problem lies in the definition of the "gradient" for a 00382 * color channel. Here, the approach introduced in A. Cumani, 00383 * "Edge Detection in Multispectral Images", Technical Report, 00384 * Istituto Elettrotecnico Nazionale "Galileo Ferraris", 1989 is 00385 * followed. 00386 * 00387 * With this approach, instead of the usual gradient, the maxima of the 00388 * contrast function are searched. The contrast function defines 00389 * the direction in the (x,y) plane at which the contrast change is 00390 * maximal. See lti::colorContrastGradient for more information. 00391 * 00392 * The Canny-typical non-maxima suppression procedure is applied on the 00393 * contrast result. 00394 * 00395 * @param c1 first channel 00396 * @param c2 second channel 00397 * @param c3 third channel 00398 * @param edges the found edges 00399 * @param orientation orientation of the found angles. 00400 * @return true if apply successful or false otherwise. 00401 */ 00402 virtual bool apply(const channel& c1, 00403 const channel& c2, 00404 const channel& c3, 00405 channel8& edges, 00406 channel& orientation) const; 00407 00408 /** 00409 * copy data of "other" functor. 00410 * @param other the functor to be copied 00411 * @return a reference to this functor object 00412 */ 00413 cannyEdges& copy(const cannyEdges& other); 00414 00415 /** 00416 * alias for copy member 00417 * @param other the functor to be copied 00418 * @return a reference to this functor object 00419 */ 00420 cannyEdges& operator=(const cannyEdges& other); 00421 00422 /** 00423 * returns a pointer to a clone of this functor. 00424 */ 00425 virtual functor* clone() const; 00426 00427 /** 00428 * set functor's parameters. 00429 * This member makes a copy of <em>theParam</em>: the functor 00430 * will keep its own copy of the parameters! 00431 * @return true if successful, false otherwise 00432 */ 00433 virtual bool updateParameters(); 00434 00435 /** 00436 * returns used parameters 00437 */ 00438 const parameters& getParameters() const; 00439 00440 private: 00441 00442 /** 00443 * non maxima suppression functor 00444 */ 00445 nonMaximaSuppression suppressor; 00446 00447 /** 00448 * Look-Up Table for the computations of atan2 00449 */ 00450 arctanLUT atan2; 00451 00452 /** 00453 * convert a pair of values in cartesic system into a pair in 00454 * polar system 00455 * 00456 * The LUT takes care that the returned value lies between 0 and 2*Pi 00457 */ 00458 inline void cartToPolar(const int dx,const int dy, 00459 float& mag,float& angle) const; 00460 00461 /** 00462 * The gradient functor used 00463 */ 00464 colorContrastGradient grad; 00465 00466 }; 00467 } 00468 00469 #endif