Go to the documentation of this file.00001
00006
00007
00008
00009
00010
00011
00012
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
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
00291 kappa_hat = VL_MAX(kappa_hat, 0.0) ;
00292 break ;
00293 default:
00294 abort() ;
00295 }
00296 return kappa_hat ;
00297 }
00298
00299
00300
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
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
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 }
00424 }
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
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
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
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
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
00580 #endif