Main Page | Class Hierarchy | Class List | File List | Class Members

MedianFilter.h

00001 #ifndef __MEDIAN_FILTER_H__
00002 #define __MEDIAN_FILTER_H__
00003 
00004 #include <vuVector.h>
00005 #include <Utilities.h>
00006 #include <vuML.h>
00007 #include <Dataset.h>
00008 
00009 #include <VVector.h>
00010 #include <VVectorFun.h>
00011 using namespace math;
00012 
00013 #include <assert.h>
00014 #include <cmath>
00015 
00016 #include <string>
00017 #include <algorithm>
00018 using namespace std;
00019 
00021 class Neighborhood {
00022 
00023  public: 
00024 
00026   Neighborhood(): m_size(0) {}
00027 
00029   void print() const {
00030 /*     int i; */
00031 /*     for ( i = 0; i < m_size; i++ ) { */
00032 /*       cout << "Neighbor " << i << " is " << m_locations[i] << endl; */
00033 /*     } */
00034     cout << "Neighborhood size is " << m_size << endl;
00035   }
00036 
00038   int getSize() const { return m_size; }
00039 
00041   Vector3i& operator[](int i) { 
00042     assert ( i >= 0 && i < MAX_NUM );
00043     return m_locations[i]; 
00044   }
00045 
00047   const Vector3i& operator[](int i) const { 
00048     assert ( i >= 0 && i < MAX_NUM );
00049     return m_locations[i]; 
00050   }
00051 
00053 
00056   void setSize(int s) { m_size = s; }
00057 
00059   void addNeighbor(const Vector3i& l) {
00060     m_locations[m_size] = l;
00061     m_size++;
00062   }
00063 
00064  private:
00065   //cannot have more neighbors than the number of samples.
00066   Vector3i m_locations[MAX_NUM];
00067   int m_size;
00068 };
00069 
00071 class SphericalFilter {
00072 
00073  public:
00074 
00076   SphericalFilter(): m_radius(0.0) {}
00077 
00079   void filter(const Dataset& in, Dataset& out) {
00080     int numSamples = in.getNumSamples();
00081 
00082     out.copyAttribs(in);
00083 
00084     int i;
00085     for ( i = 0; i < numSamples; i++ ) {
00086       out[i] = filter(in, i);
00087     }
00088   }
00089 
00091   int getNeighborhoodSize() const { return m_neighborhood.getSize(); }
00092 
00094   void print() const {
00095     cout << "Filter radius = " << m_radius << endl;
00096     int numNeighbors = m_neighborhood.getSize();
00097     cout << "Neighorhood size = " << numNeighbors << endl;
00098     int i;
00099     for ( i = 0; i < numNeighbors; i++ ) {
00100       cout << "Neighbor " << i << " = " << m_neighborhood[i]
00101            << " has weight " << m_weights[i] << endl;
00102     }
00103   }
00104 
00106   static double gaussianFunc(const double& sigma,
00107                              const double& x,
00108                              const double& y,
00109                              const double& z) {
00110     return exp( -(x*x + y*y + z*z) / (2.0 * sigma*sigma));
00111   }
00112 
00114   static double gaussianFunc(const double& sigma, const Vector3i& p) {
00115     double x = double(p[0]);
00116     double y = double(p[1]);
00117     double z = double(p[2]);
00118 
00119     return gaussianFunc(sigma, x, y, z);
00120   }
00121 
00123   double getRadius() const { return m_radius; }
00124 
00126   virtual void setRadius(const double& r) = 0;
00127 
00128  protected:
00129 
00131   virtual double filter(const Dataset& in, int i) = 0;
00132 
00134   Neighborhood m_neighborhood; 
00135 
00137 
00140   double m_weights[MAX_NUM]; //normalized
00141 
00143 
00147   double m_radius;
00148 };
00149 
00151 class SphericalFilterCC : public SphericalFilter {
00152  public:
00153 
00155   /*virtual*/ void setRadius(const double& r) {
00156     m_neighborhood.setSize(0); //clear existing neighborhood
00157 
00158     m_radius = 0;
00159 
00160     //construct integral bounding box of neighborhood candidates
00161     int radius_int = int(r); 
00162     Vector3i min(-radius_int);
00163     Vector3i max(radius_int);
00164 
00165     int x, y, z;
00166     for ( x = min[0]; x <= max[0]; x++ ) {
00167       for ( y = min[1]; y <= max[1]; y++ ) {
00168         for ( z = min[2]; z <= max[2]; z++ ) {
00169           int p_arr[] = {x,y,z};
00170           Vector3i p(p_arr);
00171           double norm_p = norm(p);
00172           if ( norm_p <= r ) {
00173             m_neighborhood.addNeighbor(p);
00174 
00175             //track actual radius of discrete neighborhood
00176             if ( norm_p > m_radius ) {
00177               m_radius = norm_p;
00178             }
00179           }
00180         }
00181       }
00182     }
00183 
00184     printf("Radius is %lf, ", m_radius); 
00185     m_neighborhood.print();
00186   } 
00187 
00188 };
00189 
00191 class MedianSphericalFilterCC : public SphericalFilterCC { 
00192  private:
00193 
00195   /*virtual*/ double filter(const Dataset& in, int index) {
00196     int numNeighbors = m_neighborhood.getSize();
00197     Vector3i p = in.mindex_cc(index);
00198 
00199     assert(numNeighbors > 0);
00200 
00201     int i;
00202     for ( i = 0; i < numNeighbors; i++ ) {
00203       Vector3i neighbor = p + m_neighborhood[i];
00204       int neighbor_index = in.lindex_cc(neighbor);
00205       m_weights[i] = in[neighbor_index];
00206     }
00207 
00208     sort(m_weights, m_weights+numNeighbors);
00209 
00210     if ( ODD(numNeighbors) ) { //median is unique
00211       int median = (numNeighbors - 1) / 2;
00212       //i.e. numNeighbors = 5, median = 2, where indices = {0,1,2,3,4}
00213       return m_weights[median];
00214     }
00215  
00216     //else, take average of the two medians
00217     int m1 = numNeighbors / 2;
00218     int m2 = m1 - 1;
00219     //i.e. numNeighbors = 6, median = 2,3, where indices = {0,1,2,3,4,5}
00220     return 0.5*(m_weights[m1] + m_weights[m2]);
00221   }
00222 };
00223 
00225 class GaussianSphericalFilterCC : public SphericalFilterCC { 
00226  public:
00227 
00229   /*virtual*/ void setRadius(const double& r) {
00230     //need to fill Gaussian filter weights in addition to
00231     //setRadius function of parent
00232 
00233     SphericalFilterCC::setRadius(r);
00234 
00235     //sigma below cannot be 0, else div by 0 in exponent of gaussian
00236     if ( EQUALS(m_radius, 0.0) ) {
00237       m_weights[0] = 1.0; 
00238       return;
00239     }
00240 
00241     //now that we know the radius, use it to compute sigma
00242     double N = 3.0;
00243     double sigma = m_radius / N; 
00244 
00245     //compute weights
00246     int i;
00247     int numNeighbors = m_neighborhood.getSize();
00248     double sum = 0;
00249     for ( i = 0; i < numNeighbors; i++ ) {
00250       Vector3i neighbor = m_neighborhood[i];
00251       m_weights[i] = gaussianFunc(sigma, neighbor);
00252       sum += m_weights[i];
00253     }
00254     
00255     //normalize weights so they add up to 1
00256     for ( i = 0; i < numNeighbors; i++ ) {
00257       m_weights[i] /= sum;
00258     }
00259   }
00260 
00261  private:
00262 
00264   /*virtual*/ double filter(const Dataset& in, int index) {
00265     int numNeighbors = m_neighborhood.getSize();
00266     Vector3i p = in.mindex_cc(index);
00267 
00268     assert(numNeighbors > 0);
00269 
00270     double filtered_val = 0.0;
00271     int i;
00272     for ( i = 0; i < numNeighbors; i++ ) {
00273       Vector3i neighbor = p + m_neighborhood[i];
00274       int neighbor_index = in.lindex_cc(neighbor);
00275       filtered_val += in[neighbor_index] * m_weights[i];
00276     }
00277 
00278     return filtered_val;
00279   }
00280 };
00281 
00283 class SphericalFilterBCC : public SphericalFilter {
00284  public:
00286   /*virtual*/ void setRadius(const double& r) { 
00287     m_neighborhood.setSize(0); //clear existing neighborhood
00288 
00289     m_radius = 0;
00290 
00291     //construct integral bounding box of neighborhood candidates
00292     int radius_int = int(r); 
00293     Vector3i min(-radius_int);
00294     Vector3i max(radius_int);
00295 
00296     int x, y, z;
00297     for ( x = min[0]; x <= max[0]; x++ ) {
00298       for ( y = min[1]; y <= max[1]; y++ ) {
00299         for ( z = min[2]; z <= max[2]; z++ ) {
00300           int p_arr[] = {x,y,z};
00301           Vector3i p(p_arr);
00302           double norm_p = norm(p);
00303           if ( norm_p <= r ) {
00304             //test parity for BCC grid
00305             if ( ( ODD(x) && ODD(y) && ODD(z) ) ||
00306                  ( EVEN(x) && EVEN(y) && EVEN(z) ) ) {
00307               m_neighborhood.addNeighbor(p);
00308 
00309               //track actual radius of discrete neighborhood
00310               if ( norm_p > m_radius ) {
00311                 m_radius = norm_p;
00312               }
00313             }
00314           }
00315         }
00316       }
00317     }
00318 
00319     printf("Radius is %lf, ", m_radius); 
00320     m_neighborhood.print();
00321   }   
00322 };
00323 
00325 class MedianSphericalFilterBCC : public SphericalFilterBCC {
00326  private:
00327 
00329   /*virtual*/ double filter(const Dataset& in, int index) {
00330     int numNeighbors = m_neighborhood.getSize();
00331     Vector3i p = in.mindex_bcc(index);
00332 
00333     assert(numNeighbors > 0);
00334 
00335     int i;
00336     for ( i = 0; i < numNeighbors; i++ ) {
00337       Vector3i neighbor = p + m_neighborhood[i];
00338       int neighbor_index = in.lindex_bcc(neighbor);
00339       m_weights[i] = in[neighbor_index];
00340     }
00341 
00342     sort(m_weights, m_weights+numNeighbors);
00343 
00344     if ( ODD(numNeighbors) ) { //median is unique
00345       int median = (numNeighbors - 1) / 2;
00346       //i.e. numNeighbors = 5, median = 2, where indices = {0,1,2,3,4}
00347       return m_weights[median];
00348     }
00349  
00350     //else, take average of the two medians
00351     int m1 = numNeighbors / 2;
00352     int m2 = m1 - 1;
00353     //i.e. numNeighbors = 6, median = 2,3, where indices = {0,1,2,3,4,5}
00354     return 0.5*(m_weights[m1] + m_weights[m2]);
00355   }
00356 };
00357 
00359 class GaussianSphericalFilterBCC : public SphericalFilterBCC { 
00360  public:
00361 
00363   /*virtual*/ void setRadius(const double& r) {
00364     //need to fill Gaussian filter weights in addition to
00365     //setRadius function of parent
00366 
00367     SphericalFilterBCC::setRadius(r);
00368 
00369     //sigma below cannot be 0, else div by 0 in exponent of gaussian
00370     if ( EQUALS(m_radius, 0.0) ) {
00371       m_weights[0] = 1.0; 
00372       return;
00373     }
00374 
00375     //now that we know the radius, use it to compute sigma
00376     double N = 3.0;
00377     double sigma = m_radius / N; 
00378 
00379     //compute weights
00380     int i;
00381     int numNeighbors = m_neighborhood.getSize();
00382     double sum = 0;
00383     for ( i = 0; i < numNeighbors; i++ ) {
00384       Vector3i neighbor = m_neighborhood[i];
00385       m_weights[i] = gaussianFunc(sigma, neighbor);
00386       sum += m_weights[i];
00387     }
00388     
00389     //normalize weights so they add up to 1
00390     for ( i = 0; i < numNeighbors; i++ ) {
00391       m_weights[i] /= sum;
00392     }
00393   }
00394 
00395  private:
00396 
00398   /*virtual*/ double filter(const Dataset& in, int index) {
00399     int numNeighbors = m_neighborhood.getSize();
00400     Vector3i p = in.mindex_bcc(index);
00401 
00402     assert(numNeighbors > 0);
00403 
00404     double filtered_val = 0.0;
00405     int i;
00406     for ( i = 0; i < numNeighbors; i++ ) {
00407       Vector3i neighbor = p + m_neighborhood[i];
00408       int neighbor_index = in.lindex_bcc(neighbor);
00409       filtered_val += in[neighbor_index] * m_weights[i];
00410     }
00411 
00412     return filtered_val;
00413   }
00414 };
00415 
00416 #endif

Generated on Thu Apr 13 04:55:56 2006 by  doxygen 1.4.4