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

ltiSusan.h

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 

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