Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

# Modules/ImageProcessor/ImageProcessorTools/FastSUSANNoiseReduction.h

Go to the documentation of this file.

    00001
    00002 /**
    00003 * @file FastSUSANNoiseReduction.h
    00004 * Declaration of file FastSUSANNoiseReduction.
    00005 *
    00006 * @author <A href=mailto:walter.nistico@uni-dortmund.de>Walter Nistico</A>
    00007 */
    00008
    00009 #ifndef _FastSUSANNoiseReduction_h_
    00010 #define _FastSUSANNoiseReduction_h_
    00011
    00012 #include "Representations/Perception/Image.h"
    00013
    00014 /**
    00015 * @class FastSUSANNoiseReduction
    00016 *
    00017 * This class represents a non-linear image noise-reduction filter.
    00018 * The main feature of S.U.S.A.N. filters is their capability to smooth out the noise while preserving image structures
    00019 * like lines, edges, borders, and so on, hence if the smoothing threshold is set correctly, the resulting image tipically exhibits no blur.
    00020 * This implementation has been significantly modified from the original SUSAN algorithm, in order to reach a vastly reduced
    00021 * computational cost making it suitable for real-time processing, so strictly speaking, this is NOT a SUSAN filter, yet it shares the same basic idea.
    00022 *
    00023 * @author <A href=mailto:walter.nistico@uni-dortmund.de>Walter Nistico</A>
    00024 */
    00025
    00026 class FastSUSANNoiseReduction
    00027 {
    00028
    00029 public:
    00030
    00031   //~ enum ColorSpectra {componentA=0, componentB, componentC};
    00032
    00033   /** Constructor */
    00034   FastSUSANNoiseReduction(int smoothingThreshold);
    00035
    00036   /** Destructor */
    00037   ~FastSUSANNoiseReduction();
    00038
    00039   /**
    00040   * Filters a chosen pixel of an image.
    00041   * IMPORTANT NOTE: since it's a filter which makes use of a convolution kernel of size 3x3,
    00042   * always make sure that you don't access the 1 pixel wide beavel of the image,
    00043   * (so it should always be x>0, x<width-1, y>0, y<width-1)
    00044   * otherwise you'll be accessing memory out of the allocated space, with obvious consequences.
    00045   * @param source the source image to be filtered
    00046   * @param posX the x coordinate of the chosen pixel
    00047   * @param posY the y coordinate of the chosen pixel
    00048   * @param valA the first spectrum (ex. Y (luminance)) of the filtered pixel, returned
    00049   * @param valB the second spectrum (ex. U (crominance)) of the filtered pixel, returned
    00050   * @param valC the third spectrum (ex. V (crominance)) of the filtered pixel, returned
    00051   */
    00052   inline void getFilteredPixel(const Image& source, int posX, int posY, unsigned char& valA, unsigned char& valB, unsigned char& valC) const
    00053   {
    00054     valA = getFilteredPixelSpectrum(source, posX, posY, 0);
    00055     valB = getFilteredPixelSpectrum(source, posX, posY, 1);
    00056     valC = getFilteredPixelSpectrum(source, posX, posY, 2);
    00057   }
    00058
    00059   /**
    00060   * Filters a chosen pixel of an image, directly modifying it.
    00061   * IMPORTANT NOTE: since it's a filter which makes use of a convolution kernel of size 3x3,
    00062   * always make sure that you don't access the 1 pixel wide beavel of the image,
    00063   * (so it should always be x>0, x<width-1, y>0, y<width-1)
    00064   * otherwise you'll be accessing memory out of the allocated space, with obvious consequences.
    00065   * @param source the source image to be filtered
    00066   * @param posX the x coordinate of the chosen pixel
    00067   * @param posY the y coordinate of the chosen pixel
    00068   */
    00069   inline void filterPixel(Image& source, int posX, int posY) const
    00070   {
    00071     source.image[posY][0][posX] = getFilteredPixelSpectrum(source, posX, posY, 0);
    00072     source.image[posY][1][posX] = getFilteredPixelSpectrum(source, posX, posY, 1);
    00073     source.image[posY][2][posX] = getFilteredPixelSpectrum(source, posX, posY, 2);
    00074   }
    00075
    00076   /**
    00077   * Filters a whole image.
    00078   * IMPORTANT NOTE: since it's a filter which makes use of a convolution kernel of size 3x3,
    00079   * always make sure that you don't access the 1 pixel wide beavel of the image,
    00080   * (so it should always be x>0, x<width-1, y>0, y<width-1)
    00081   * otherwise you'll be accessing memory out of the allocated space, with obvious consequences.
    00082   * @param source the source image to be filtered
    00083   * @param destination the resulting image
    00084   */
    00085   void getFilteredImage(const Image& source, Image& destination) const;
    00086
    00087 private:
    00088
    00089   /**
    00090   * A LookUpTable containing a correlation function, in this implementation it's a "rect" for efficiency reasons
    00091   */
    00092   char Susan_LUT[127];
    00093
    00094   /**
    00095   * Initializes the LookUpTable
    00096   */
    00097   void setupSusanLUT(int threshold);
    00098
    00099   /**
    00100   * The correlation function, precomputed
    00101   */
    00102   inline char correlation(int delta) const
    00103   {
    00104     return Susan_LUT[(delta>>2)+63];
    00105   }
    00106
    00107   /**
    00108   * Filters a single spectrum (ex. Y or U or V) of a chosen pixel of an image.
    00109   * IMPORTANT NOTE: since it's a filter which makes use of a convolution kernel of size 3x3,
    00110   * always make sure that you don't access the 1 pixel wide beavel of the image,
    00111   * (so it should always be x>0, x<width-1, y>0, y<width-1)
    00112   * otherwise you'll be accessing memory out of the allocated space, with obvious consequences.
    00113   * @param image the source image to be filtered
    00114   * @param posx the x coordinate of the chosen pixel
    00115   * @param posy the y coordinate of the chosen pixel
    00116   * @param spectrum the chosen image spectrum
    00117   * @return the filtered value
    00118   */
    00119   inline unsigned char getFilteredPixelSpectrum(const Image& image, int posx, int posy, int spectrum) const
    00120   {
    00121     register unsigned int USAN;
    00122     register int counter;
    00123     register unsigned char center;
    00124     register int tempCorrelation;
    00125     register unsigned char neighbours0;
    00126     register unsigned char neighbours1;
    00127     register unsigned char neighbours2;
    00128     register unsigned char neighbours3;
    00129
    00130     unsigned char resp;
    00131     int sp = static_cast<int> (spectrum);
    00132
    00133     center = image.image[posy][sp][posx];
    00134     neighbours0 = image.image[posy-1][sp][posx];
    00135     neighbours1 = image.image[posy+1][sp][posx];
    00136     neighbours2 = image.image[posy][sp][posx-1];
    00137     neighbours3 = image.image[posy][sp][posx+1];
    00138
    00139     tempCorrelation = correlation(neighbours0-center);
    00140     USAN = neighbours0 & tempCorrelation;
    00141     counter = tempCorrelation;
    00142     tempCorrelation = correlation(neighbours1-center);
    00143     USAN += neighbours1 & tempCorrelation;
    00144     counter += tempCorrelation;
    00145     tempCorrelation = correlation(neighbours2-center);
    00146     USAN += neighbours2 & tempCorrelation;
    00147     counter += tempCorrelation;
    00148     tempCorrelation = correlation(neighbours3-center);
    00149     USAN += neighbours3 & tempCorrelation;
    00150     counter += tempCorrelation;
    00151
    00152     if (counter == -4) { // most likely situation, typically above 85% for smoothin threshold >= 8 (which usually is the case)
    00153       resp = (unsigned char) (USAN>>2);
    00154     }
    00155     else
    00156     if (counter == -3) {// second most likely situation
    00157       USAN += center;
    00158       resp = (unsigned char) (USAN>>2);
    00159     }
    00160     else
    00161     if (counter == -2) {
    00162       resp = (unsigned char) (USAN>>1);
    00163     }
    00164     else
    00165     if (counter == -1) {
    00166       USAN += center;
    00167       resp = (unsigned char) (USAN>>1);
    00168     }
    00169     else
    00170     { // counter == 0
    00171       unsigned char swap;
    00172       if (neighbours0>neighbours1){
    00173         swap = neighbours1;
    00174         neighbours1 = neighbours0;
    00175         neighbours0 = swap;
    00176       }
    00177       if (neighbours2>neighbours3){
    00178         swap = neighbours3;
    00179         neighbours3 = neighbours2;
    00180         neighbours2 = swap;
    00181       }
    00182       if (neighbours2>neighbours0){
    00183         neighbours0 = neighbours2;
    00184       }
    00185       if (neighbours3<neighbours1){
    00186         neighbours1 = neighbours3;
    00187       }
    00188       USAN = neighbours0 + neighbours1;
    00189       resp = (unsigned char) (USAN>>1);
    00190     }
    00191     return resp;
    00192   }
    00193
    00194 };
    00195
    00196 #endif   //  _FastSUSANNoiseReduction_h_