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 can be used with the LTI-Computer Vision Library (LTI-Lib) 00006 * (please note this file is NOT part of the LTI-Lib) 00007 * This code is based on the original C code by S. Smith, which contains 00008 * following header: 00009 * 00010 ********************************************************************** 00011 * 00012 * SUSAN Version 2l by Stephen Smith 00013 * 00014 * Oxford Centre for Functional Magnetic Resonance Imaging of the 00015 * Brain, Department of Clinical Neurology, Oxford University, Oxford, 00016 * UK (Previously in Computer Vision and Image Processing Group - now 00017 * Computer Vision and Electro Optics Group - DERA Chertsey, UK) 00018 * 00019 * Email: steve@fmrib.ox.ac.uk 00020 * WWW: http://www.fmrib.ox.ac.uk/~steve 00021 * 00022 * (C) Crown Copyright (1995-1999), Defence Evaluation and Research Agency, 00023 * Farnborough, Hampshire, GU14 6TD, UK 00024 * DERA WWW site: 00025 * http://www.dera.gov.uk/ 00026 * DERA Computer Vision and Electro Optics Group WWW site: 00027 * http://www.dera.gov.uk/imageprocessing/dera/group_home.html 00028 * DERA Computer Vision and Electro Optics Group point of contact: 00029 * Dr. John Savage, jtsavage@dera.gov.uk, +44 1344 633203 00030 * 00031 * A UK patent has been granted: "Method for digitally processing 00032 * images to determine the position of edges and/or corners therein for 00033 * guidance of unmanned vehicle", UK Patent 2272285. Proprietor: 00034 * Secretary of State for Defence, UK. 15 January 1997 00035 * 00036 * This code is issued for research purposes only and remains the 00037 * property of the UK Secretary of State for Defence. This code must 00038 * not be passed on without this header information being kept 00039 * intact. This code must not be sold. 00040 ********************************************************************** 00041 * 00042 * 00043 * 00044 * The LTI-Lib is free software; you can redistribute it and/or 00045 * modify it under the terms of the GNU Lesser General Public License (LGPL) 00046 * as published by the Free Software Foundation; either version 2.1 of 00047 * the License, or (at your option) any later version. 00048 * 00049 * The LTI-Lib is distributed in the hope that it will be 00050 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00051 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00052 * GNU Lesser General Public License for more details. 00053 * 00054 * You should have received a copy of the GNU Lesser General Public 00055 * License along with the LTI-Lib; see the file LICENSE. If 00056 * not, write to the Free Software Foundation, Inc., 59 Temple Place - 00057 * Suite 330, Boston, MA 02111-1307, USA. 00058 * 00059 */ 00060 00061 /*---------------------------------------------------------------- 00062 * project ....: LTI Digital Image/Signal Processing Library 00063 * file .......: ltiSusan.h 00064 * authors ....: Stefan Syberichs (LTI-Lib port),Stephen Smith (original SUSAN) 00065 * organization: LTI, RWTH Aachen 00066 * creation ...: 29.04.2000 00067 * revisions ..: $Id: ltiSusan.h,v 1.12 2005/07/22 08:19:05 libuda Exp $ 00068 */ 00069 00070 #ifndef _LTI_SUSAN_H_ 00071 #define _LTI_SUSAN_H_ 00072 00073 #include "ltiObject.h" 00074 #include "ltiException.h" 00075 #include "ltiImage.h" 00076 00077 #ifndef HAVE_SUSAN 00078 #ifdef _LTI_MSC_VER 00079 #pragma message("Configuration Error:") 00080 #pragma message("Change in src/basics/ltiWinConfig.h HAVE_SUSAN to 1") 00081 #else 00082 #warning "Configuration Error:" 00083 #warning "Change in src/basics/config.h HAVE_SUSAN to 1" 00084 #endif 00085 #endif 00086 00087 namespace lti { 00088 00089 //////////////////////////////////////////////////////////// 00090 // Exceptions for Susan operator 00091 /////////////////////////////////////////////////////////// 00092 00093 /** 00094 * A class for SUSAN image Processing. 00095 * The SUSAN principle implements a fast-low level approach for 00096 * finding binary edges and corners and reducing noise in grey 00097 * channel images. The basic idea is to move a circular mask of 37 00098 * pixels over the image and compare the brightness of all 00099 * peripheral pixels to the brightness of the center. The sum of all 00100 * pixels who's brightness is equal (or similar) to the center point 00101 * gives the USAN value (Univalue Segment Assimilating Nucleus), 00102 * which can be used to determine the presence of edges and corners 00103 * or to reduce noise. For more details see the <em>Technical Report 00104 * TR95SMS1c: SUSAN - A New Approach to Low Level Image 00105 * Processing</em> by 00106 * <a href="http://www.fmrib.ox.ac.uk/~steve/susan/"> Stephen M. Smith</a>, 00107 * or refer to the source comments. 00108 * <b> For the use in applications use the frontends 00109 * derived from the modifier or functor classes 00110 * (e.g. lti::susanEdges)!!! </b> 00111 */ 00112 class susan: public object { 00113 public: 00114 00115 /// susan error exception 00116 class susanError : public exception { 00117 public: 00118 susanError (const std::string &msg) : exception (msg) {}; 00119 const char* getTypeName() const {return "SusanError";}; 00120 }; 00121 00122 /// default constructor 00123 susan(); 00124 /// copy constructor 00125 00126 /// destructor 00127 ~susan(); 00128 00129 /** find edges in img and visualize them in edges. 00130 * According to the SUSAN Algorithmn, the binary edges 00131 * in <em> img </em> are detected. A copy of <em> img </em> is made in 00132 * <em>edges </em> and the edgepoints are highlighted by setting the 00133 * brightness to 255. There is no need to cut <em>edges</em> to 00134 * the right size, findedges() will do 00135 * this (i.e. all data in <em> edges </em> is erased). 00136 * findEdges() is notably slower than binaryEdges, because the whole 00137 * image data is being copied (and it's just for demonstartion purpose) 00138 * @param img the channel with the input image 00139 * @param edges a channel8-buffer to store the result. 00140 */ 00141 void findEdges(const channel8 &img, channel8& edges); 00142 00143 00144 /** draw binary edge image. 00145 * According to the SUSAN Algorithmn, the binary edges in <em> 00146 * img </em> are detected and stored in the buffer 00147 * <em>binaryEdges</em>. After that, <em> binaryEdges </em> 00148 * contains a map of the image, where all edge points are white 00149 * (255), and all other pixels are black(0). 00150 * @param img the channel with the input image 00151 * @param binEdges a channel8-buffer to store the result in black 00152 * and white. 00153 */ 00154 void binaryEdges(const channel8 &img, channel8& binEdges); 00155 00156 /** draw binary edge image. 00157 * According to the SUSAN Algorithmn, the binary edges in <em> 00158 * img </em> are detected and stored in the buffer 00159 * <em>binaryEdges</em>. After that, <em> binaryEdges </em> 00160 * contains a map of the image, where all edge points are white 00161 * (255), and all other pixels are black(0). 00162 * @param img the channel with the input image 00163 * @param binEdges a channel8-buffer to store the result in black 00164 * and white. 00165 */ 00166 void binaryEdges(const channel &img, channel& binEdges); 00167 00168 00169 /** 00170 * set brightness threshold. 00171 * the brightness threshold is roughly the value to determine the 00172 * similarity of pixels (counted in grey values. i.e. threshold = 00173 * 20 declares all pixel similar to the center pixel, who's 00174 * brightness does not differ by more than roughly +/- 20 00175 * greylevels). The default is 20. In effect, a lower threshold 00176 * finds more edges, a higher threshold finds less edges, since 00177 * the algorithmn of detecting an edge from an USAN is more subtle 00178 * than comparing brightness values ! In reality, the similarity 00179 * function is expressed in gaussian curve rather than a 00180 * rectangle, where the similarity (0..100, 100 is maximum 00181 * similarity) is given by <pre> c = 100*exp(-((I-Io)/t)^6) </pre> 00182 * with <em> Io </em>being the brightness of the center pixel to 00183 * be compared, and <em>I</em> the brightness of the considered 00184 * pixel. The exponent <em> 6 </em> is an arbitrary form factor 00185 * for the gaussian curve. 00186 * 00187 * @param t brightness threshold between 1 and 255, default is 20 00188 * @exception susanError is thrown if threshold is out of range. */ 00189 void setThreshold(int t); 00190 00191 /** 00192 * set the values used to indicate a no-edge (off) and edge (on) pixels 00193 */ 00194 void setOffOnValues(const ubyte off, const ubyte on); 00195 00196 /** 00197 * returns the name of this type 00198 */ 00199 const char* getTypeName() const {return "susan";}; 00200 00201 private: 00202 00203 /** 00204 * marks the edge information from the buffer <em>edgeBuffer</em> 00205 * by highlighting all edge pixels in <em>in</em> to 255. 00206 */ 00207 void edgeDraw(ubyte* in, ubyte* edgeBuffer, int xSize,int ySize); 00208 00209 /** 00210 * binarise the raw edge information. 00211 * Binarisation is done by adjusting the raw edge data (values 00212 * between 1 and 100) to either 255 (edge point) or background 00213 * (0). 00214 */ 00215 void binaryDraw(channel8& img); 00216 00217 /** 00218 * binarise the raw edge information. 00219 * Binarisation is done by adjusting the raw edge data (values 00220 * between 1 and 100) to either 255 (edge point) or background 00221 * (0). 00222 */ 00223 void binaryDraw(const channel8& img,channel& dest); 00224 00225 00226 /** thin the raw edge information. 00227 * The thinning provides an enhancement to the raw edge image by 00228 * <ul> 00229 * <li> deleting all edge points without neigbours (i.e. noise reduction) 00230 * <li> extending broken edges 00231 * <li> moving shifted points back into line 00232 * </ul> 00233 */ 00234 void thin(int *response,ubyte* edgeBuffer,int xSize,int ySize); 00235 00236 /** Set up Brightness Look-up Table. 00237 * The actual computation that is needed to determine, whether point (x,y) 00238 * with brightness I is similar to the nucleus Io by the threshold t is: 00239 * 00240 * c = 100*exp(-((I-Io)/t)^6) 00241 * 00242 * where 0 means no similarity in brightness and 100 maximum similarity 00243 * (i.e. identity) (See Figure 5 and equation (4)) 00244 * 0 and 100 have been choosen to obtain a smooth gaussian membership 00245 * function while still using integer arithmetics for computational 00246 * efficiency 00247 * As the variety of possible brightness differences is limited, 00248 * a brightness LUT is set up in the manner, that 00249 * <ul> 00250 * <li> the lutBase pointer points to the middle of the allocated memory 00251 * <pre> 00252 * value: ........ 95 98 99 99 99 99 100 99 99 99 99 98 95 ........... 00253 * | 00254 * index: 0 lutBase 515 00255 * </pre> 00256 * <li> the similarity (= membership value) of a pixel at image position p 00257 * and brightness *p to a kernel-centerpoint cp can be obtained by 00258 * the following code: 00259 * <pre> 00260 * cp=lutBase + image[row*xSize+col]; 00261 * similarity= *(cp-*p); 00262 * </pre> 00263 * </ul> 00264 * This means: the brightness difference gives the distance from 00265 * the LUT center, the value in this LUT-position gives the 00266 * similarity 00267 */ 00268 void setupBrightnessLUT(unsigned char **lutBase, int thresh,int form); 00269 00270 /** 00271 * susanEdges - Edgefinder 00272 * 00273 * This method handles 2 things: 00274 * 00275 * -# find points that are candidates for an edge and calculate the USAN 00276 * response 00277 * -# compute the direction of the edge, i.e. horizontal, vertical or 00278 * diagonal (with sign) 00279 * 00280 * The direction is needed for the thinning procedure. 00281 * FINDING EDGE POINTS (1): 00282 * (see Dera Technical Report TR95SMS1c) 00283 * 00284 * To find possible candidate pixels for an edge, the USAN response 00285 * (Univalue Segment Assimilating Nucleus) is computed for each 00286 * image-pixel in the following manner: 00287 * 00288 * a) move a circular mask of size 37 pixels over the image: 00289 * \code 00290 * 00291 * ooo 00292 * ooooo 00293 * ooooooo 00294 * "+" indicates center ooo+ooo 00295 * ooooooo 00296 * ooooo 00297 * ooo 00298 * \endcode 00299 * 00300 * b) determine the (weighted) number of pixels that have similar 00301 * brightness as the center pixel. The similarity is expressed 00302 * within the brightness LUT described above. Every pixel in the 00303 * mask contributes a value between 100 (identical brightness) and 0 00304 * (far beyond threshold) to a sum that is stored in the variable n 00305 * in every mask loop. (see equation (2) in paper). 00306 * 00307 * c) a USAN response for every center pixel is calculated like 00308 * response = maxNo - n (or 0, if n > maxNo, equation (3)) 00309 * where maxNo is a parameter that should be chosen like 2700 (= 00310 * 0.75 * maximum USAN sum) As a high value of n means "no edge", 00311 * a high value of response means "strong edge" respectively. the 00312 * response values are stored in the one-dimensional field 00313 * response 00314 * 00315 * EDGE DIRECTIONS: There are two types of edges to be distinguished 00316 * - inter-pixel edges: pixel of an (almost) ideal step 00317 * edge. inter-pixel means: the center of gravity of the 00318 * corresponding USAN lies between two pixels. 00319 * 00320 * - intra-pixel edges: pixel of a band of brightness half the way 00321 * between the brightness of the two regions generating the 00322 * edge. The resulting center of gravity coincides with the mask 00323 * nucleus. (see Figure 6) intra-pixel edges are assumed, if the 00324 * USAN area is smaller than the mask diameter (= 6 pixels = value 00325 * 600 for the USAN sum n) 00326 * 00327 * the field edgeBuffer contains a "1" if the edge is of inter-pixel 00328 * type, and a "2" if the edge is of intra-pixel type, otherwise 00329 * "100" (i.e. the edgeBuffer must be initialized outside the 00330 * susanEdges() function, see public method findEdges()). 00331 */ 00332 void susanEdges(const ubyte* in, 00333 int* response, 00334 ubyte* edgeBuffer, //mid 00335 ubyte* lutBase, //bp 00336 int maxNo, 00337 int xSize, 00338 int ySize); 00339 00340 /** 00341 * Threshold for brightness comparison 00342 */ 00343 int threshold; 00344 00345 /** 00346 * value used for no-edges 00347 */ 00348 ubyte off; 00349 00350 /** 00351 * value used for edges 00352 */ 00353 ubyte on; 00354 }; 00355 00356 } // namespace lti 00357 00358 #endif 00359