00001
00007
00008
00009 #include "dsift.h"
00010 #include "pgm.h"
00011 #include "mathop.h"
00012 #include "imopv.h"
00013 #include <math.h>
00014 #include <string.h>
00015
00247 float * _vl_dsift_new_kernel (int binSize, int numBins, int binIndex)
00248 {
00249 int filtLen = 2 * binSize - 1 ;
00250 float * ker = vl_malloc (sizeof(float) * filtLen) ;
00251 float * kerIter = ker ;
00252 float delta = binSize * (binIndex - 0.5F * (numBins - 1)) ;
00253 float sigma = 0.5F * ((numBins - 1) * binSize + 1) ;
00254
00255
00256
00257
00258 int x ;
00259
00260 for (x = - binSize + 1 ; x <= + binSize - 1 ; ++ x) {
00261 float z = (x - delta) / sigma ;
00262 *kerIter++ = (1.0f - fabsf(x) / binSize) *
00263 ((binIndex >= 0) ? expf(- 0.5F * z*z) : 1.0F) ;
00264
00265
00266
00267 }
00268 return ker ;
00269 }
00270
00278 VL_INLINE float
00279 _vl_dsift_normalize_histogram
00280 (float *begin, float *end)
00281 {
00282 float* iter ;
00283 float norm = 0.0 ;
00284
00285 for (iter = begin ; iter != end ; ++ iter)
00286 norm += (*iter) * (*iter) ;
00287
00288 norm = vl_fast_sqrt_f (norm) + VL_EPSILON_F ;
00289
00290 for (iter = begin; iter != end ; ++ iter)
00291 *iter /= norm ;
00292
00293 return norm;
00294 }
00295
00302 void
00303 _vl_dsift_free_buffers (VlDsiftFilter* self)
00304 {
00305 if (self->frames) {
00306 vl_free(self->frames) ;
00307 self->frames = NULL ;
00308 }
00309 if (self->descrs) {
00310 vl_free(self->descrs) ;
00311 self->descrs = NULL ;
00312 }
00313 if (self->grads) {
00314 int t ;
00315 for (t = 0 ; t < self->numGradAlloc ; ++t)
00316 if (self->grads[t]) vl_free(self->grads[t]) ;
00317 vl_free(self->grads) ;
00318 self->grads = NULL ;
00319 }
00320 self->numFrameAlloc = 0 ;
00321 self->numBinAlloc = 0 ;
00322 self->numGradAlloc = 0 ;
00323 }
00324
00325
00329 void _vl_dsift_update_buffers (VlDsiftFilter *self)
00330 {
00331 int x1 = self->boundMinX ;
00332 int x2 = self->boundMaxX ;
00333 int y1 = self->boundMinY ;
00334 int y2 = self->boundMaxY ;
00335
00336 int rangeX = x2 - x1 - (self->geom.numBinX - 1) * self->geom.binSizeX ;
00337 int rangeY = y2 - y1 - (self->geom.numBinY - 1) * self->geom.binSizeY ;
00338
00339 int numFramesX = (rangeX >= 0) ? rangeX / self->stepX + 1 : 0 ;
00340 int numFramesY = (rangeY >= 0) ? rangeY / self->stepY + 1 : 0 ;
00341
00342 self->numFrames = numFramesX * numFramesY ;
00343 self->descrSize = self->geom.numBinT *
00344 self->geom.numBinX *
00345 self->geom.numBinY ;
00346 }
00347
00357 void
00358 _vl_dsift_alloc_buffers (VlDsiftFilter* self)
00359 {
00360 _vl_dsift_update_buffers (self) ;
00361 {
00362 int numFrameAlloc = vl_dsift_get_keypoint_num (self) ;
00363 int numBinAlloc = vl_dsift_get_descriptor_size (self) ;
00364 int numGradAlloc = self->geom.numBinT ;
00365
00366
00367 if (numBinAlloc != self->numBinAlloc ||
00368 numGradAlloc != self->numGradAlloc ||
00369 numFrameAlloc != self->numFrameAlloc) {
00370
00371 int t ;
00372
00373 _vl_dsift_free_buffers(self) ;
00374
00375 self->frames = vl_malloc(sizeof(VlDsiftKeypoint) * numFrameAlloc) ;
00376 self->descrs = vl_malloc(sizeof(float) * numBinAlloc * numFrameAlloc) ;
00377 self->grads = vl_malloc(sizeof(float*) * numGradAlloc) ;
00378 for (t = 0 ; t < numGradAlloc ; ++t) {
00379 self->grads[t] =
00380 vl_malloc(sizeof(float) * self->imWidth * self->imHeight) ;
00381 }
00382 self->numBinAlloc = numBinAlloc ;
00383 self->numGradAlloc = numGradAlloc ;
00384 self->numFrameAlloc = numFrameAlloc ;
00385 }
00386 }
00387 }
00388
00398 VL_EXPORT
00399 VlDsiftFilter*
00400 vl_dsift_new (int imWidth, int imHeight)
00401 {
00402 VlDsiftFilter* self = vl_malloc (sizeof(VlDsiftFilter)) ;
00403 self->imWidth = imWidth ;
00404 self->imHeight = imHeight ;
00405
00406 self->stepX = 5 ;
00407 self->stepY = 5 ;
00408
00409 self->boundMinX = 0 ;
00410 self->boundMinY = 0 ;
00411 self->boundMaxX = imWidth - 1 ;
00412 self->boundMaxY = imHeight - 1 ;
00413
00414 self->geom.numBinX = 4 ;
00415 self->geom.numBinY = 4 ;
00416 self->geom.numBinT = 8 ;
00417 self->geom.binSizeX = 5 ;
00418 self->geom.binSizeY = 5 ;
00419
00420 self->useFlatWindow = VL_FALSE ;
00421
00422 self->convTmp1 = vl_malloc(sizeof(float) * self->imWidth * self->imHeight) ;
00423 self->convTmp2 = vl_malloc(sizeof(float) * self->imWidth * self->imHeight) ;
00424
00425 self->numBinAlloc = 0 ;
00426 self->numFrameAlloc = 0 ;
00427 self->numGradAlloc = 0 ;
00428
00429 self->descrSize = 0 ;
00430 self->numFrames = 0 ;
00431 self->grads = NULL ;
00432 self->frames = NULL ;
00433 self->descrs = NULL ;
00434
00435 _vl_dsift_update_buffers(self) ;
00436 return self ;
00437 }
00438
00452 VL_EXPORT
00453 VlDsiftFilter*
00454 vl_dsift_new_basic (int imWidth, int imHeight, int step, int binSize)
00455 {
00456 VlDsiftFilter* self = vl_dsift_new(imWidth, imHeight) ;
00457 VlDsiftDescriptorGeometry geom = *vl_dsift_get_geometry(self) ;
00458 geom.binSizeX = binSize ;
00459 geom.binSizeY = binSize ;
00460 vl_dsift_set_geometry(self, &geom) ;
00461 vl_dsift_set_steps(self, step, step) ;
00462 return self ;
00463 }
00464
00470 VL_EXPORT
00471 void
00472 vl_dsift_delete (VlDsiftFilter *self)
00473 {
00474 _vl_dsift_free_buffers (self) ;
00475 if (self->convTmp2) vl_free(self->convTmp2) ;
00476 if (self->convTmp1) vl_free(self->convTmp1) ;
00477 vl_free (self) ;
00478 }
00479
00480
00487 VL_INLINE
00488 void _vl_dsift_with_gaussian_window (VlDsiftFilter* self)
00489 {
00490 int binx, biny, bint ;
00491 int framex, framey ;
00492 float *xker, *yker ;
00493
00494 int Wx = self->geom.binSizeX - 1 ;
00495 int Wy = self->geom.binSizeY - 1 ;
00496
00497 for (biny = 0 ; biny < self->geom.numBinY ; ++biny) {
00498
00499 yker = _vl_dsift_new_kernel(self->geom.binSizeY,
00500 self->geom.numBinY,
00501 biny) ;
00502
00503 for (binx = 0 ; binx < self->geom.numBinX ; ++binx) {
00504
00505 xker = _vl_dsift_new_kernel(self->geom.binSizeX,
00506 self->geom.numBinX,
00507 binx) ;
00508
00509 for (bint = 0 ; bint < self->geom.numBinT ; ++bint) {
00510
00511 vl_imconvcol_vf (self->convTmp1, self->imHeight,
00512 self->grads[bint], self->imWidth, self->imHeight,
00513 self->imWidth,
00514 yker, -Wy, +Wy, 1,
00515 VL_PAD_BY_CONTINUITY|VL_TRANSPOSE) ;
00516
00517 vl_imconvcol_vf (self->convTmp2, self->imWidth,
00518 self->convTmp1, self->imHeight, self->imWidth,
00519 self->imHeight,
00520 xker, -Wx, +Wx, 1,
00521 VL_PAD_BY_CONTINUITY|VL_TRANSPOSE) ;
00522
00523 {
00524 float *dst = self->descrs
00525 + bint
00526 + binx * self->geom.numBinT
00527 + biny * (self->geom.numBinX * self->geom.numBinT) ;
00528
00529 float *src = self->convTmp2 ;
00530
00531 int frameSizeX = self->geom.binSizeX * (self->geom.numBinX - 1) + 1 ;
00532 int frameSizeY = self->geom.binSizeY * (self->geom.numBinY - 1) + 1 ;
00533 int descrSize = vl_dsift_get_descriptor_size (self) ;
00534
00535 for (framey = self->boundMinY ;
00536 framey <= self->boundMaxY - frameSizeY + 1 ;
00537 framey += self->stepY) {
00538 for (framex = self->boundMinX ;
00539 framex <= self->boundMaxX - frameSizeX + 1 ;
00540 framex += self->stepX) {
00541 *dst = src [(framex + binx * self->geom.binSizeX) * 1 +
00542 (framey + biny * self->geom.binSizeY) * self->imWidth] ;
00543 dst += descrSize ;
00544 }
00545 }
00546 }
00547
00548 }
00549 vl_free (xker) ;
00550 }
00551 vl_free (yker) ;
00552 }
00553 }
00554
00560 VL_INLINE
00561 void _vl_dsift_with_flat_window (VlDsiftFilter* self)
00562 {
00563 int binx, biny, bint ;
00564 int framex, framey ;
00565
00566
00567 for (bint = 0 ; bint < self->geom.numBinT ; ++bint) {
00568
00569 vl_imconvcoltri_vf (self->convTmp1, self->imHeight,
00570 self->grads [bint], self->imWidth, self->imHeight,
00571 self->imWidth,
00572 self->geom.binSizeY - 1,
00573 1,
00574 VL_PAD_BY_CONTINUITY|VL_TRANSPOSE) ;
00575
00576 vl_imconvcoltri_vf (self->convTmp2, self->imWidth,
00577 self->convTmp1, self->imHeight, self->imWidth,
00578 self->imHeight,
00579 self->geom.binSizeX - 1,
00580 1,
00581 VL_PAD_BY_CONTINUITY|VL_TRANSPOSE) ;
00582
00583 for (biny = 0 ; biny < self->geom.numBinY ; ++biny) {
00584 for (binx = 0 ; binx < self->geom.numBinX ; ++binx) {
00585
00586 float *dst = self->descrs
00587 + bint
00588 + binx * self->geom.numBinT
00589 + biny * (self->geom.numBinX * self->geom.numBinT) ;
00590
00591 float *src = self->convTmp2 ;
00592
00593 int frameSizeX = self->geom.binSizeX * (self->geom.numBinX - 1) + 1 ;
00594 int frameSizeY = self->geom.binSizeY * (self->geom.numBinY - 1) + 1 ;
00595 int descrSize = vl_dsift_get_descriptor_size (self) ;
00596
00597 for (framey = self->boundMinY ;
00598 framey <= self->boundMaxY - frameSizeY + 1 ;
00599 framey += self->stepY) {
00600 for (framex = self->boundMinX ;
00601 framex <= self->boundMaxX - frameSizeX + 1 ;
00602 framex += self->stepX) {
00603 *dst = src [(framex + binx * self->geom.binSizeX) * 1 +
00604 (framey + biny * self->geom.binSizeY) * self->imWidth] ;
00605 dst += descrSize ;
00606 }
00607 }
00608 }
00609 }
00610 }
00611 }
00612
00620 void vl_dsift_process (VlDsiftFilter* self, float const* im)
00621 {
00622 int t, x, y ;
00623
00624
00625 _vl_dsift_alloc_buffers (self) ;
00626
00627
00628 for (t = 0 ; t < self->geom.numBinT ; ++t)
00629 memset (self->grads[t], 0,
00630 sizeof(float) * self->imWidth * self->imHeight) ;
00631
00632 #undef at
00633 #define at(x,y) (im[(y)*self->imWidth+(x)])
00634
00635
00636
00637 for (y = 0 ; y < self->imHeight ; ++ y) {
00638 for (x = 0 ; x < self->imWidth ; ++ x) {
00639 float gx, gy ;
00640 float angle, mod, nt, rbint ;
00641 int bint ;
00642
00643
00644 if (y == 0) {
00645 gy = at(x,y+1) - at(x,y) ;
00646 } else if (y == self->imHeight - 1) {
00647 gy = at(x,y) - at(x,y-1) ;
00648 } else {
00649 gy = 0.5F * (at(x,y+1) - at(x,y-1)) ;
00650 }
00651
00652
00653 if (x == 0) {
00654 gx = at(x+1,y) - at(x,y) ;
00655 } else if (x == self->imWidth - 1) {
00656 gx = at(x,y) - at(x-1,y) ;
00657 } else {
00658 gx = 0.5F * (at(x+1,y) - at(x-1,y)) ;
00659 }
00660
00661
00662 angle = vl_fast_atan2_f (gy,gx) ;
00663 mod = vl_fast_sqrt_f (gx*gx + gy*gy) ;
00664
00665
00666 nt = vl_mod_2pi_f (angle) * (self->geom.numBinT / (2*VL_PI)) ;
00667 bint = vl_floor_f (nt) ;
00668 rbint = nt - bint ;
00669
00670
00671 self->grads [(bint ) % self->geom.numBinT][x + y * self->imWidth] = (1 - rbint) * mod ;
00672 self->grads [(bint + 1) % self->geom.numBinT][x + y * self->imWidth] = ( rbint) * mod ;
00673 }
00674 }
00675
00676 if (self->useFlatWindow) {
00677 _vl_dsift_with_flat_window(self) ;
00678 } else {
00679 _vl_dsift_with_gaussian_window(self) ;
00680 }
00681
00682 {
00683 VlDsiftKeypoint* frameIter = self->frames ;
00684 float * descrIter = self->descrs ;
00685 int framex, framey, bint ;
00686
00687 int frameSizeX = self->geom.binSizeX * (self->geom.numBinX - 1) + 1 ;
00688 int frameSizeY = self->geom.binSizeY * (self->geom.numBinY - 1) + 1 ;
00689 int descrSize = vl_dsift_get_descriptor_size (self) ;
00690
00691 float deltaCenterX = 0.5F * self->geom.binSizeX * (self->geom.numBinX - 1) ;
00692 float deltaCenterY = 0.5F * self->geom.binSizeY * (self->geom.numBinY - 1) ;
00693
00694 float normConstant = frameSizeX * frameSizeY ;
00695
00696 if (self->useFlatWindow) {
00697
00698 normConstant /= self->geom.binSizeX * self->geom.binSizeY ;
00699 }
00700
00701 for (framey = self->boundMinY ;
00702 framey <= self->boundMaxY - frameSizeY + 1 ;
00703 framey += self->stepY) {
00704
00705 for (framex = self->boundMinX ;
00706 framex <= self->boundMaxX - frameSizeX + 1 ;
00707 framex += self->stepX) {
00708
00709 frameIter->x = framex + deltaCenterX ;
00710 frameIter->y = framey + deltaCenterY ;
00711
00712
00713 {
00714 float mass = 0 ;
00715 for (bint = 0 ; bint < descrSize ; ++ bint)
00716 mass += descrIter[bint] ;
00717 mass /= normConstant ;
00718 frameIter->norm = mass ;
00719 }
00720
00721
00722 _vl_dsift_normalize_histogram (descrIter, descrIter + descrSize) ;
00723
00724
00725 for(bint = 0 ; bint < descrSize ; ++ bint)
00726 if (descrIter[bint] > 0.2F) descrIter[bint] = 0.2F ;
00727
00728
00729 _vl_dsift_normalize_histogram (descrIter, descrIter + descrSize) ;
00730
00731 frameIter ++ ;
00732 descrIter += descrSize ;
00733 }
00734 }
00735 }
00736 }