contrib/gel/gevd/gevd_float_operators.h
Go to the documentation of this file.
00001 #ifndef gevd_float_operators_h_
00002 #define gevd_float_operators_h_
00003 //:
00004 // \file
00005 // \brief Operators on float pixels in 2D images
00006 //
00007 // Operators on pixels in 2D image are divided into following groups:
00008 // - convolution:
00009 //   * gaussian smoothing, high pass filtering.
00010 //   * 2D/1D separable convolution in x and y, even/odd.
00011 // - detection:
00012 //   * gradient to find step edges
00013 //   * laplacian to find fold edges
00014 //   * local orientation
00015 // - pyramid:
00016 //   * shrink/expand by factor of 2 using Burt filters.
00017 //   * wavelet transform
00018 // - other:
00019 //   * correlation
00020 //   * apply function
00021 //   * projection onto axes
00022 // - utilities:
00023 //
00024 // float is used throughout to avoid overflow/underflow and conversion
00025 // on math operations like sqrt, sin, etc...
00026 // All convolution operators have a running cache of the input, and so
00027 // the from/to buffers can be the same.
00028 //
00029 // \verbatim
00030 //  Modifications
00031 //   Van-Duc Nguyen (1990) convolution to support image segmentation
00032 //   Van-Duc Nguyen (1992) add pyramid and wavelet
00033 //   Van-Duc Nguyen (1996) add circular/reflection at border
00034 //   Van-Duc Nguyen (1997) add running sum
00035 //   Chuck Stewart  (1997) added SurfaceNormalD, SurfaceCurvatureD, ShrinkBy2_D
00036 //   Peter Vanroose July 1999 -made all methods static (class has no data)
00037 //   Peter Vanroose Sept 2004 -all methods now support "from" & "to" being equal
00038 // \endverbatim
00039 
00040 class gevd_bufferxy;       // buffer of floats
00041 
00042 class gevd_float_operators
00043 {
00044 // Do not instantiate this class; access methods by name scoping
00045   gevd_float_operators();
00046 
00047  public:
00048   // convolution
00049   static float Convolve(const gevd_bufferxy& from, const gevd_bufferxy& kernel,
00050                         gevd_bufferxy*& to);
00051   static gevd_bufferxy* Read2dKernel(const char* filename);
00052   static float Convolve(const gevd_bufferxy& from, gevd_bufferxy*& to,// can mutate in place
00053                         const float* xkernel, // when from==to
00054                         const int xradius, const bool xevenp,
00055                         const float* ykernel,
00056                         const int yradius, const bool yevenp,
00057                         const bool xwrap=false, const bool ywrap=false);
00058   static float Convolve(const gevd_bufferxy& from, gevd_bufferxy*& to,// can mutate in place
00059                         const float* xkernel, // when from==to
00060                         const int xradius, const bool xevenp,
00061                         const int yradius,    // running sum along y-axis
00062                         const bool xwrap=false, const bool ywrap=false);
00063   static float Convolve(const float* from, float*& to, const int len,
00064                         const float* kernel, const int radius,
00065                         const bool evenp, const bool wrap=false);
00066   static float RunningSum(float* from, float*& to, const int len,
00067                           const int radius, const bool wrap=false);
00068   static bool Read1dKernel(const char* filename,
00069                            float*& kernel, int& radius, bool& evenp);
00070 
00071   static float Gaussian(gevd_bufferxy& img, gevd_bufferxy*& smooth, const float sigma=1.0f,
00072                         const bool xwrap=false, const bool ywrap=false);
00073   static bool Find1dGaussianKernel(const float sigma,
00074                                    float*& kernel, int& radius,
00075                                    const float fuzz=0.02f);
00076 
00077   // detection
00078   static float Gradient(const gevd_bufferxy& smooth, // 1st-derivative
00079                         gevd_bufferxy*& mag,
00080                         gevd_bufferxy*& dirx, gevd_bufferxy*& diry,
00081                         const bool xwrap=false, const bool ywrap=false);
00082   static float Slope(float* from, float*& to, const int len,
00083                      const bool wrap=false);
00084   static float Hessian(const gevd_bufferxy& smooth, // 2nd-derivative
00085                        gevd_bufferxy*& mag, // max eigenvalue
00086                        gevd_bufferxy*& dirx, gevd_bufferxy*& diry,
00087                        const bool xwrap=false, const bool ywrap=false);
00088   static float Laplacian(const gevd_bufferxy& smooth,
00089                          gevd_bufferxy*& mag, // sum of 2 eigenvalue/curvature
00090                          gevd_bufferxy*& dirx, gevd_bufferxy*& diry,
00091                          const bool xwrap=false, const bool ywrap=false);
00092   static float Curvature(float* from, float*& to, const int len,
00093                          const bool wrap=false);
00094   static float Orientation(const gevd_bufferxy& smooth,
00095                            gevd_bufferxy*& theta,  gevd_bufferxy*& coherence,
00096                            const int frame=1);
00097 
00098   static void NonMaximumSuppression(const gevd_bufferxy& magnitude,
00099                                     const gevd_bufferxy& directionx,
00100                                     const gevd_bufferxy& directiony,
00101                                     const float threshold,
00102                                     gevd_bufferxy*& contour, gevd_bufferxy*& direction,
00103                                     gevd_bufferxy*& locationx, gevd_bufferxy*& locationy,
00104                                     const bool xwrap=false,
00105                                     const bool ywrap=false);
00106   static int NonMaximumSuppression(const float* from, const int len,
00107                                    const float threshold,
00108                                    int*& index, float*& mag, float*& locs,
00109                                    const bool wrap=false);
00110   static float InterpolateParabola(float y1, float y0, float y2, // return offset
00111                                    float&y); // real max/min
00112   static float BilinearInterpolate(const gevd_bufferxy& img, float x, float y);
00113   static void SupportAngle(const gevd_bufferxy& dirx, const gevd_bufferxy& diry,
00114                            const gevd_bufferxy& magnitude,
00115                            gevd_bufferxy*& angle);
00116 
00117   // specific to range images
00118   static void SurfaceNormal(const gevd_bufferxy& range, gevd_bufferxy*& normal);
00119   static void SurfaceCurvature(const gevd_bufferxy& normal, gevd_bufferxy*& curvature);
00120 
00121   static void SurfaceNormalD(const gevd_bufferxy& range, gevd_bufferxy*& normal,
00122                              float no_value, float pixel_distance=1.0f);
00123 #if 0 // -rgc- : does SurfaceCurvature need to calculate the actual distances instead of deducing them from the grid?
00124   static void SurfaceCurvatureD(const gevd_bufferxy& normal, gevd_bufferxy*& curvature,
00125                                 float dflt, float pixel_distance=1.0f);
00126 #endif // 0
00127   static void SurfaceCurvatureD(const gevd_bufferxy& normal, const gevd_bufferxy& surface,
00128                                 gevd_bufferxy*& curvature, float dflt, float pixel_distance=1.0f);
00129 
00130   // shrink/expand
00131   static float ShrinkBy2(const gevd_bufferxy& cfrom, gevd_bufferxy*& to,
00132                          const float burt_ka=0.359375f); // Burt filter coeft
00133   static float ExpandBy2(const gevd_bufferxy& cfrom, gevd_bufferxy*& to,
00134                          const float burt_ka=0.359375f); // Burt filter coeft
00135   static void ShrinkBy2_D (const gevd_bufferxy& from, gevd_bufferxy*& to,
00136                            float no_value, float burt_ka=0.359375f );
00137   static int Pyramid(const float* from, const int length,
00138                      float*& to, int& nlevels, int trim=0,
00139                      const float burt_ka=0.359375f); // Burt filter coeft
00140   static int ShrinkBy2(const float* from, const int length,
00141                        float*& to, const float burt_ka=0.359375f);
00142 
00143   // wavelet transform
00144   static bool WaveletTransform(float* array, const int n, // 1d array
00145                                const bool forwardp,
00146                                int nlevels,
00147                                const int waveletno=4);
00148   static bool WaveletTransformByBlock(float* array, // nd imge.
00149                                       const int* dims, const int ndim,
00150                                       const bool forwardp,
00151                                       int nlevels,
00152                                       const int waveletno=4);
00153   static bool WaveletTransformByIndex(float* array,
00154                                       const int* dims, const int ndim,
00155                                       const bool forwardp, int nlevels,
00156                                       const int waveletno=4);
00157   static bool FindWavelet(const int waveletno,
00158                           float*& cc, float*& cr, int& ncof);
00159   static void LowHighPyramid(float* highPass, float* lowPass,
00160                              int n, int nlevels,
00161                              const float* lo_filter,
00162                              const float* hi_filter,
00163                              int ncof,
00164                              float* wksp);
00165 
00166 #if 0 // commented out
00167   static int DeleteMixedComponents(float* wave, // delete wavelet coefts
00168                                    const int* dims, const int ndim,
00169                                    const int nlevels)
00170   static int TruncateHighFrequencies(float* wave,
00171                                      const int* dims, const int ndim,
00172                                      const int nlevels, // throw all small
00173                                      const float threshold=0.1f); // components
00174   static int TruncateLowestFrequency(float* wave,
00175                                      const int* dims, const int ndim,
00176                                      const int nlevels,
00177                                      float& average); // uniform average
00178 #endif
00179 
00180   static bool WaveletTransformByBlock(const gevd_bufferxy& cfrom, gevd_bufferxy*& to,
00181                                       const bool forwardp,
00182                                       int nlevels,
00183                                       const int waveletno=4);
00184   static bool WaveletTransformByIndex(const gevd_bufferxy& cfrom, gevd_bufferxy*& to,
00185                                       const bool forwardp,
00186                                       int nlevels,
00187                                       const int waveletno=4);
00188   static int DeleteMixedComponents(gevd_bufferxy& wave,
00189                                    const int nlevels);
00190   static int TruncateHighFrequencies(gevd_bufferxy& wave,
00191                                      const int nlevels,
00192                                      const float threshold=0.1f);
00193   static int TruncateLowestFrequency(gevd_bufferxy& wave, const int nlevels);
00194   static int DeleteBoundaryArtifacts(float* wave, const int n, const int nlevels);
00195   static int DeleteBoundaryArtifacts(gevd_bufferxy& wave, const int nlevels);
00196 
00197   static void ProjectWaveOntoX(const gevd_bufferxy& buf, float*& proj,
00198                                const int nlevels=0);
00199   static void ProjectWaveOntoY(const gevd_bufferxy& buf, float*& proj,
00200                                const int nlevels=0);
00201 
00202   // projections on the axes.
00203   static void ProjectOntoX(const gevd_bufferxy& buf, float*& proj,
00204                            int sizeX=0, int sizeY=0,
00205                            int origX=0, int origY=0);
00206   static void ProjectOntoY(const gevd_bufferxy& buf, float*& proj,
00207                            int sizeX=0, int sizeY=0,
00208                            int origX=0, int origY=0);
00209 
00210   // Search for maximum 1D/2D correlation
00211   static float Correlation(const gevd_bufferxy& from, const gevd_bufferxy& kernel,
00212                            gevd_bufferxy*& to);
00213   static float CorrelationAlongAxis(const gevd_bufferxy& from,
00214                                     const gevd_bufferxy& kernel,
00215                                     gevd_bufferxy*& to);
00216 
00217   static float Correlation(const float* data, const int length,// correlation at index
00218                            const float* pattern, const int radius,
00219                            const int index);
00220   static float* Correlations(const float* data, const int length, // cors around index
00221                              const float* pattern, const int radius,
00222                              const int index, const int search);
00223   static float BestCorrelation(const float* data, const int length, // search max cor
00224                                const float* pattern, const int radius,
00225                                int& shift, const int search);
00226   static float CoarseFineCorrelation(const float* dataPyr, const int dlength,
00227                                      const float* patternPyr, const int plength,
00228                                      float& shift, // pattern location in data
00229                                      const int coarse, const int fine, // level#
00230                                      const float cutoff=0, // early cutoff of search
00231                                      const float overlap=0.75f, // min overlap
00232                                      float* matches=0); // trace correlations
00233 
00234 #if 0 // commented out
00235   static gevd_bufferxy* Correlations(const gevd_bufferxy& data, const gevd_bufferxy& pattern,
00236                                      const int* indexes, const int* search);
00237   static float Correlate(const gevd_bufferxy& data, const gevd_bufferxy& pattern,
00238                          const int* indexes);
00239   static float Correlate(const gevd_bufferxy& data, const gevd_bufferxy& pattern,
00240                          int*& shifts, const int* search);
00241 #endif
00242 
00243   static void Apply(gevd_bufferxy& buf, float (*func)(float));
00244 
00245   // create test patterns
00246 #if 0 // commented out
00247   static gevd_bufferxy* MakeImpulse(const float mag,
00248                                     int x=100, int y=100);
00249   static gevd_bufferxy* MakeGaussianNoise(const float mag, const float sigma,
00250                                           int x=100, int y=100);
00251   static gevd_bufferxy* MakeCircles(const float mag, float w1, float w2,
00252                                     int x=100, int y=100);
00253   static gevd_bufferxy* MakeEllipses(const float mag, const float w1, const float w2,
00254                                      const float eccentricity,
00255                                      int x=100, int y=100);
00256   static gevd_bufferxy* MakeSuperellipses(const float mag,
00257                                           const float w1, const float w2,
00258                                           float, float, float,
00259                                           int x=100, int y=100);
00260 #endif
00261 
00262   // binary operations
00263   static gevd_bufferxy* AbsoluteDifference(const gevd_bufferxy& buf1, const gevd_bufferxy& buf2);
00264 
00265   // utilities
00266   static gevd_bufferxy* Allocate(gevd_bufferxy* space, const gevd_bufferxy& model,
00267                                  int bits_per_pixel=0, int sizeX=0, int sizeY=0);
00268   static gevd_bufferxy* SimilarBuffer(const gevd_bufferxy& buffer, // use default
00269                                       int bits_per_pixel=0,// from buffer
00270                                       int sizeX=0, int sizeY=0);
00271   static bool IsSimilarBuffer(const gevd_bufferxy& buf1,    // same dimension
00272                               const gevd_bufferxy& buf2);       // & precision
00273   static gevd_bufferxy* Extract(const gevd_bufferxy& buf,
00274                                 int sizeX=0, int sizeY=0,
00275                                 int origX=0, int origY=0);
00276   static void Update(gevd_bufferxy& old_buf, const gevd_bufferxy& new_buf,
00277                      int origX=0, int origY=0);
00278   static gevd_bufferxy* TransposeExtract(const gevd_bufferxy & buf,
00279                                          int sizeX, int sizeY, int origX, int origY);
00280   static void TransposeUpdate(gevd_bufferxy & buf, const gevd_bufferxy& sub,
00281                               int origX, int origY);
00282 
00283   static void Fill(gevd_bufferxy& buf, const float value,
00284                    int sizeX=0, int sizeY=0,
00285                    int origX=0, int origY=0);
00286   static void FillFrameX(gevd_bufferxy& buf, const float value, const int width=1);
00287   static void FillFrameY(gevd_bufferxy& buf, const float value, const int width=1);
00288   static void DrawFrame(gevd_bufferxy& buf, const int loc, const float value=0);
00289 
00290   static gevd_bufferxy* PadToPowerOf2(gevd_bufferxy& buf);
00291   static gevd_bufferxy* UnpadFromPowerOf2(gevd_bufferxy& padded, int sizeX, int sizeY);
00292 
00293   static float Maximum(const gevd_bufferxy& buf,
00294                        int sizeX=0, int sizeY=0,
00295                        int origX=0, int origY=0);
00296   static float Minimum(const gevd_bufferxy& buf,
00297                        int sizeX=0, int sizeY=0,
00298                        int origX=0, int origY=0);
00299   static bool Maximum(const float* data, const int length,
00300                       int& index, float& value);
00301 
00302   static float Sum(const gevd_bufferxy& buf,
00303                    int sizeX=0, int sizeY=0,
00304                    int origX=0, int origY=0);
00305   static int Threshold(gevd_bufferxy& buf, float noise,
00306                        int sizeX=0, int sizeY=0,
00307                        int origX=0, int origY=0);
00308 
00309   static float TruncateToPositive(gevd_bufferxy& buf);
00310   static float TruncateToCeiling(gevd_bufferxy& buf, float ceil);
00311   static void Absolute(gevd_bufferxy& buf);
00312   static void Negate(gevd_bufferxy& buf);
00313   static void Scale(gevd_bufferxy& buf, float factor);
00314   static void ShiftToPositive(gevd_bufferxy& buf);
00315   static void Normalize(gevd_bufferxy& buf, const float lo, const float hi);
00316 
00317   // conversion
00318   static bool BufferToFloat(const gevd_bufferxy& from, gevd_bufferxy& floatto);
00319   static bool FloatToBuffer(const gevd_bufferxy& floatfrom, gevd_bufferxy& to);
00320 
00321  protected:
00322   static int SetupPipeline(const float* data, const int len,
00323                            const int kradius, const bool wrap,
00324                            float*& cache, float*& pipeline);
00325   static gevd_bufferxy* WrapAlongX(const gevd_bufferxy& img);
00326   static gevd_bufferxy* WrapAlongY(const gevd_bufferxy& img);
00327   static float Gaussian(const float x, const float sigma);
00328   static float ShrinkBy2AlongX(const gevd_bufferxy& cfrom, const int y,
00329                                float* yline, const int len,
00330                                const float ka, const float kb, const float kc);
00331   static void ShrinkBy2AlongX_D( const gevd_bufferxy& from, int from_sizeX,
00332                                  int sizeX, int y, float kernel[],
00333                                  float no_value, float* yline, float* wline );
00334   static float ExpandBy2AlongX(const gevd_bufferxy& cfrom, const int y,
00335                                float* yline, const int len,
00336                                const float ka, const float kb, const float kc);
00337   static void WaveletTransformStep(float* array, const int n,
00338                                    const bool forwardp,
00339                                    const float* lo_filter,
00340                                    const float* hi_filter,
00341                                    const int ncof,
00342                                    float* wksp);
00343   static void WaveletTransformStep(float* array, const int* dims, const int ndim,
00344                                    const bool forwardp,
00345                                    const float* lo_filter,
00346                                    const float* hi_filter,
00347                                    const int ncof,
00348                                    float* buffer, float* wksp);
00349   static void CopyNdRecursive(const float* from_array,
00350                               const int from_size, const int* from_dims,
00351                               float* to_array,
00352                               const int to_size, const int* to_dims,
00353                               const int ndim, const bool fullp=true);
00354   static void TestWavelets();
00355 };
00356 
00357 #endif // gevd_float_operators_h_