homkermap.c
Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 2007-12 Andrea Vedaldi and Brian Fulkerson.
00008 Copyright (C) 2013 Andrea Vedaldi.
00009 All rights reserved.
00010 
00011 This file is part of the VLFeat library and is made available under
00012 the terms of the BSD license (see the COPYING file).
00013 */
00014 
00211 /* ---------------------------------------------------------------- */
00212 #ifndef VL_HOMKERMAP_INSTANTIATING
00213 /* ---------------------------------------------------------------- */
00214 
00215 #include "homkermap.h"
00216 #include "mathop.h"
00217 #include <math.h>
00218 
00219 struct _VlHomogeneousKernelMap
00220 {
00221   VlHomogeneousKernelType kernelType ;
00222   double gamma ;
00223   VlHomogeneousKernelMapWindowType windowType ;
00224   vl_size order ;
00225   double period ;
00226   vl_size numSubdivisions ;
00227   double subdivision  ;
00228   vl_index minExponent ;
00229   vl_index maxExponent ;
00230   double * table ;
00231 } ;
00232 
00239 VL_INLINE double
00240 vl_homogeneouskernelmap_get_spectrum (VlHomogeneousKernelMap const * self, double omega)
00241 {
00242   assert (self) ;
00243   switch (self->kernelType) {
00244     case VlHomogeneousKernelIntersection:
00245       return (2.0 / VL_PI) / (1 + 4 * omega*omega) ;
00246     case VlHomogeneousKernelChi2:
00247       return 2.0 / (exp(VL_PI * omega) + exp(-VL_PI * omega)) ;
00248     case VlHomogeneousKernelJS:
00249       return (2.0 / log(4.0)) *
00250       2.0 / (exp(VL_PI * omega) + exp(-VL_PI * omega)) /
00251       (1 + 4 * omega*omega) ;
00252     default:
00253       abort() ;
00254   }
00255 }
00256 
00257 /* helper */
00258 VL_INLINE double sinc(double x)
00259 {
00260   if (x == 0.0) return 1.0 ;
00261   return sin(x) / x ;
00262 }
00263 
00270 VL_INLINE double
00271 vl_homogeneouskernelmap_get_smooth_spectrum (VlHomogeneousKernelMap const * self, double omega)
00272 {
00273   double kappa_hat = 0 ;
00274   double omegap ;
00275   double epsilon = 1e-2 ;
00276   double const omegaRange = 2.0 / (self->period * epsilon) ;
00277   double const domega = 2 * omegaRange / (2 * 1024.0 + 1) ;
00278   assert (self) ;
00279   switch (self->windowType) {
00280     case VlHomogeneousKernelMapWindowUniform:
00281       kappa_hat = vl_homogeneouskernelmap_get_spectrum(self, omega) ;
00282       break ;
00283     case VlHomogeneousKernelMapWindowRectangular:
00284       for (omegap = - omegaRange ; omegap <= omegaRange ; omegap += domega) {
00285         double win = sinc((self->period/2.0) * omegap) ;
00286         win *= (self->period/(2.0*VL_PI)) ;
00287         kappa_hat += win * vl_homogeneouskernelmap_get_spectrum(self, omegap + omega) ;
00288       }
00289       kappa_hat *= domega ;
00290       /* project on the postivie orthant (see PAMI) */
00291       kappa_hat = VL_MAX(kappa_hat, 0.0) ;
00292       break ;
00293     default:
00294       abort() ;
00295   }
00296   return kappa_hat ;
00297 }
00298 
00299 /* ---------------------------------------------------------------- */
00300 /*                                     Constructors and destructors */
00301 /* ---------------------------------------------------------------- */
00302 
00325 VlHomogeneousKernelMap *
00326 vl_homogeneouskernelmap_new (VlHomogeneousKernelType kernelType,
00327                              double gamma,
00328                              vl_size order,
00329                              double period,
00330                              VlHomogeneousKernelMapWindowType windowType)
00331 {
00332   int tableWidth, tableHeight ;
00333   VlHomogeneousKernelMap * self = vl_malloc(sizeof(VlHomogeneousKernelMap)) ;
00334   if (! self) return NULL ;
00335 
00336   assert(gamma > 0) ;
00337 
00338   assert(kernelType == VlHomogeneousKernelIntersection ||
00339          kernelType == VlHomogeneousKernelChi2 ||
00340          kernelType == VlHomogeneousKernelJS) ;
00341 
00342   assert(windowType == VlHomogeneousKernelMapWindowUniform ||
00343          windowType == VlHomogeneousKernelMapWindowRectangular) ;
00344 
00345   if (period < 0) {
00346     switch (windowType) {
00347     case VlHomogeneousKernelMapWindowUniform:
00348       switch (kernelType) {
00349       case VlHomogeneousKernelChi2:         period = 5.86 * sqrt(order + 0)  + 3.65 ; break ;
00350       case VlHomogeneousKernelJS:           period = 6.64 * sqrt(order + 0)  + 7.24 ; break ;
00351       case VlHomogeneousKernelIntersection: period = 2.38 * log(order + 0.8) + 5.6 ; break ;
00352       }
00353       break ;
00354     case VlHomogeneousKernelMapWindowRectangular:
00355       switch (kernelType) {
00356       case VlHomogeneousKernelChi2:         period = 8.80 * sqrt(order + 4.44) - 12.6 ; break ;
00357       case VlHomogeneousKernelJS:           period = 9.63 * sqrt(order + 1.00) - 2.93;  break ;
00358       case VlHomogeneousKernelIntersection: period = 2.00 * log(order + 0.99)  + 3.52 ; break ;
00359       }
00360       break ;
00361     }
00362     period = VL_MAX(period, 1.0) ;
00363   }
00364 
00365   self->kernelType = kernelType ;
00366   self->windowType = windowType ;
00367   self->gamma = gamma ;
00368   self->order = order ;
00369   self->period = period ;
00370   self->numSubdivisions = 8 + 8*order ;
00371   self->subdivision = 1.0 / self->numSubdivisions ;
00372   self->minExponent = -20 ;
00373   self->maxExponent = 8 ;
00374 
00375   tableHeight = (int) (2*self->order + 1) ;
00376   tableWidth = (int) (self->numSubdivisions * (self->maxExponent - self->minExponent + 1)) ;
00377   self->table = vl_malloc (sizeof(double) *
00378                            (tableHeight * tableWidth + 2*(1+self->order))) ;
00379   if (! self->table) {
00380     vl_free(self) ;
00381     return NULL ;
00382   }
00383 
00384   {
00385     vl_index exponent ;
00386     vl_uindex i, j ;
00387     double * tablep = self->table ;
00388     double * kappa = self->table + tableHeight * tableWidth ;
00389     double * freq = kappa + (1+self->order) ;
00390     double L = 2.0 * VL_PI / self->period ;
00391 
00392     /* precompute the sampled periodicized spectrum */
00393     j = 0 ;
00394     i = 0 ;
00395     while (i <= self->order) {
00396       freq[i] = j ;
00397       kappa[i] = vl_homogeneouskernelmap_get_smooth_spectrum(self, j * L) ;
00398       ++ j ;
00399       if (kappa[i] > 0 || j >= 3*i) ++ i ;
00400     }
00401 
00402     /* fill table */
00403     for (exponent  = self->minExponent ;
00404          exponent <= self->maxExponent ; ++ exponent) {
00405 
00406       double x, Lxgamma, Llogx, xgamma ;
00407       double sqrt2kappaLxgamma ;
00408       double mantissa = 1.0 ;
00409 
00410       for (i = 0 ; i < self->numSubdivisions ;
00411            ++i, mantissa += self->subdivision) {
00412         x = ldexp(mantissa, (int)exponent) ;
00413         xgamma = pow(x, self->gamma) ;
00414         Lxgamma = L * xgamma ;
00415         Llogx = L * log(x) ;
00416 
00417         *tablep++ = sqrt(Lxgamma * kappa[0]) ;
00418         for (j = 1 ; j <= self->order ; ++j) {
00419           sqrt2kappaLxgamma = sqrt(2.0 * Lxgamma * kappa[j]) ;
00420           *tablep++ = sqrt2kappaLxgamma * cos(freq[j] * Llogx) ;
00421           *tablep++ = sqrt2kappaLxgamma * sin(freq[j] * Llogx) ;
00422         }
00423       } /* next mantissa */
00424     } /* next exponent */
00425   }
00426   return self ;
00427 }
00428 
00434 void
00435 vl_homogeneouskernelmap_delete (VlHomogeneousKernelMap * self)
00436 {
00437   vl_free(self->table) ;
00438   self->table = NULL ;
00439   vl_free(self) ;
00440 }
00441 
00442 /* ---------------------------------------------------------------- */
00443 /*                                     Retrieve data and parameters */
00444 /* ---------------------------------------------------------------- */
00445 
00451 vl_size
00452 vl_homogeneouskernelmap_get_order (VlHomogeneousKernelMap const * self)
00453 {
00454   assert(self) ;
00455   return self->order ;
00456 }
00457 
00463 vl_size
00464 vl_homogeneouskernelmap_get_dimension (VlHomogeneousKernelMap const * self)
00465 {
00466   assert(self) ;
00467   return 2 * self->order + 1 ;
00468 }
00469 
00475 VlHomogeneousKernelType
00476 vl_homogeneouskernelmap_get_kernel_type (VlHomogeneousKernelMap const * self)
00477 {
00478   assert(self) ;
00479   return self->kernelType ;
00480 }
00481 
00487 VlHomogeneousKernelMapWindowType
00488 vl_homogeneouskernelmap_get_window_type (VlHomogeneousKernelMap const * self)
00489 {
00490   assert(self) ;
00491   return self->windowType ;
00492 }
00493 
00494 /* ---------------------------------------------------------------- */
00495 /*                                                     Process data */
00496 /* ---------------------------------------------------------------- */
00497 
00514 #define FLT VL_TYPE_FLOAT
00515 #define VL_HOMKERMAP_INSTANTIATING
00516 #include "homkermap.c"
00517 
00518 #define FLT VL_TYPE_DOUBLE
00519 #define VL_HOMKERMAP_INSTANTIATING
00520 #include "homkermap.c"
00521 
00522 /* VL_HOMKERMAP_INSTANTIATING */
00523 #endif
00524 
00525 /* ---------------------------------------------------------------- */
00526 #ifdef VL_HOMKERMAP_INSTANTIATING
00527 /* ---------------------------------------------------------------- */
00528 
00529 #include "float.th"
00530 
00531 void
00532 VL_XCAT(vl_homogeneouskernelmap_evaluate_,SFX)
00533 (VlHomogeneousKernelMap const * self,
00534  T * destination,
00535  vl_size stride,
00536  double x)
00537 {
00538   /* break value into exponent and mantissa */
00539   int exponent ;
00540   int unsigned j ;
00541   double mantissa = frexp(x, &exponent) ;
00542   double sign = (mantissa >= 0.0) ? +1.0 : -1.0 ;
00543   mantissa *= 2*sign ;
00544   exponent -- ;
00545 
00546   if (mantissa == 0 ||
00547       exponent <= self->minExponent ||
00548       exponent >= self->maxExponent) {
00549     for (j = 0 ; j < 2*self->order+1 ; ++j) {
00550       *destination = (T) 0.0 ;
00551       destination += stride ;
00552     }
00553     return  ;
00554   }
00555   {
00556     vl_size featureDimension = 2*self->order + 1 ;
00557     double const * v1 = self->table +
00558     (exponent - self->minExponent) * self->numSubdivisions * featureDimension ;
00559     double const * v2 ;
00560     double f1, f2 ;
00561 
00562     mantissa -= 1.0 ;
00563     while (mantissa >= self->subdivision) {
00564       mantissa -= self->subdivision ;
00565       v1 += featureDimension ;
00566     }
00567     v2 = v1 + featureDimension ;
00568     for (j = 0 ; j < featureDimension ; ++j) {
00569       f1 = *v1++ ;
00570       f2 = *v2++ ;
00571       *destination = (T) sign * ((f2 - f1) * (self->numSubdivisions * mantissa) + f1) ;
00572       destination += stride ;
00573     }
00574   }
00575 }
00576 
00577 #undef FLT
00578 #undef VL_HOMKERMAP_INSTANTIATING
00579 /* VL_HOMKERMAP_INSTANTIATING */
00580 #endif


libvlfeat
Author(s): Andrea Vedaldi
autogenerated on Thu Jun 6 2019 20:25:51