00001
00007
00008
00009
00010
00011
00012
00013
00340 #include "sift.h"
00341 #include "imop.h"
00342 #include "mathop.h"
00343
00344 #include <assert.h>
00345 #include <stdlib.h>
00346 #include <string.h>
00347 #include <math.h>
00348 #include <stdio.h>
00349
00351 #define VL_SIFT_BILINEAR_ORIENTATIONS 1
00352
00353 #define EXPN_SZ 256
00354 #define EXPN_MAX 25.0
00355 double expn_tab [EXPN_SZ+1] ;
00357 #define log2(x) (log(x)/VL_LOG_OF_2)
00358
00370 VL_INLINE double
00371 fast_expn (double x)
00372 {
00373 double a,b,r ;
00374 int i ;
00375 assert(0 <= x && x <= EXPN_MAX) ;
00376
00377 x *= EXPN_SZ / EXPN_MAX ;
00378 i = vl_floor_d (x) ;
00379 r = x - i ;
00380 a = expn_tab [i ] ;
00381 b = expn_tab [i + 1] ;
00382 return a + r * (b - a) ;
00383 }
00384
00390 VL_INLINE void
00391 fast_expn_init ()
00392 {
00393 int k ;
00394 for(k = 0 ; k < EXPN_SZ + 1 ; ++ k) {
00395 expn_tab [k] = exp (- (double) k * (EXPN_MAX / EXPN_SZ)) ;
00396 }
00397 }
00398
00415 static void
00416 copy_and_upsample_rows
00417 (vl_sift_pix *dst,
00418 vl_sift_pix const *src, int width, int height)
00419 {
00420 int x, y ;
00421 vl_sift_pix a, b ;
00422
00423 for(y = 0 ; y < height ; ++y) {
00424 b = a = *src++ ;
00425 for(x = 0 ; x < width - 1 ; ++x) {
00426 b = *src++ ;
00427 *dst = a ; dst += height ;
00428 *dst = 0.5 * (a + b) ; dst += height ;
00429 a = b ;
00430 }
00431 *dst = b ; dst += height ;
00432 *dst = b ; dst += height ;
00433 dst += 1 - width * 2 * height ;
00434 }
00435 }
00436
00454 static void
00455 copy_and_downsample
00456 (vl_sift_pix *dst,
00457 vl_sift_pix const *src,
00458 int width, int height, int d)
00459 {
00460 int x, y ;
00461
00462 d = 1 << d ;
00463 for(y = 0 ; y < height ; y+=d) {
00464 vl_sift_pix const * srcrowp = src + y * width ;
00465 for(x = 0 ; x < width - (d-1) ; x+=d) {
00466 *dst++ = *srcrowp ;
00467 srcrowp += d ;
00468 }
00469 }
00470 }
00471
00491 VL_EXPORT
00492 VlSiftFilt *
00493 vl_sift_new (int width, int height,
00494 int noctaves, int nlevels,
00495 int o_min)
00496 {
00497 VlSiftFilt *f = vl_malloc (sizeof(VlSiftFilt)) ;
00498
00499 int w = VL_SHIFT_LEFT (width, -o_min) ;
00500 int h = VL_SHIFT_LEFT (height, -o_min) ;
00501 int nel = w * h ;
00502
00503
00504 if (noctaves < 0) {
00505 noctaves = VL_MAX (floor (log2 (VL_MIN(width, height))) - o_min - 3, 1) ;
00506 }
00507
00508 f-> width = width ;
00509 f-> height = height ;
00510 f-> O = noctaves ;
00511 f-> S = nlevels ;
00512 f-> o_min = o_min ;
00513 f-> s_min = -1 ;
00514 f-> s_max = nlevels + 1 ;
00515 f-> o_cur = o_min ;
00516
00517 f-> temp = vl_malloc (sizeof(vl_sift_pix) * nel ) ;
00518 f-> octave = vl_malloc (sizeof(vl_sift_pix) * nel
00519 * (f->s_max - f->s_min + 1) ) ;
00520 f-> dog = vl_malloc (sizeof(vl_sift_pix) * nel
00521 * (f->s_max - f->s_min ) ) ;
00522 f-> grad = vl_malloc (sizeof(vl_sift_pix) * nel * 2
00523 * (f->s_max - f->s_min ) ) ;
00524
00525 f-> sigman = 0.5 ;
00526 f-> sigma0 = 1.6 * pow (2.0, 1.0 / nlevels) ;
00527 f-> sigmak = pow (2.0, 1.0 / nlevels) ;
00528 f-> dsigma0 = f->sigma0 * sqrt (1.0 - 1.0 / (f->sigmak*f->sigmak)) ;
00529
00530
00531
00532
00533
00534
00535 f-> octave_width = 0 ;
00536 f-> octave_height = 0 ;
00537
00538 f-> keys = 0 ;
00539 f-> nkeys = 0 ;
00540 f-> keys_res = 0 ;
00541
00542 f-> peak_thresh = 0.0 ;
00543 f-> edge_thresh = 10.0 ;
00544 f-> norm_thresh = 0.0 ;
00545 f-> magnif = 3.0 ;
00546
00547 f-> grad_o = o_min - 1 ;
00548
00549
00550 fast_expn_init () ;
00551
00552 return f ;
00553 }
00554
00563 VL_EXPORT
00564 void
00565 vl_sift_delete (VlSiftFilt* f)
00566 {
00567 if(f) {
00568 if(f-> keys ) vl_free (f-> keys ) ;
00569 if(f-> grad ) vl_free (f-> grad ) ;
00570 if(f-> dog ) vl_free (f-> dog ) ;
00571 if(f-> octave ) vl_free (f-> octave ) ;
00572 if(f-> temp ) vl_free (f-> temp ) ;
00573 vl_free (f) ;
00574 }
00575 }
00576
00593 VL_EXPORT
00594 int
00595 vl_sift_process_first_octave (VlSiftFilt *f, vl_sift_pix const *im)
00596 {
00597 int o, s, h, w ;
00598 double sa, sb ;
00599 vl_sift_pix *octave ;
00600
00601
00602 vl_sift_pix *temp = f-> temp ;
00603 int width = f-> width ;
00604 int height = f-> height ;
00605 int o_min = f-> o_min ;
00606 int s_min = f-> s_min ;
00607 int s_max = f-> s_max ;
00608 double sigma0 = f-> sigma0 ;
00609 double sigmak = f-> sigmak ;
00610 double sigman = f-> sigman ;
00611 double dsigma0 = f-> dsigma0 ;
00612
00613
00614 f->o_cur = o_min ;
00615 f->nkeys = 0 ;
00616 w = f-> octave_width = VL_SHIFT_LEFT(f->width, - f->o_cur) ;
00617 h = f-> octave_height = VL_SHIFT_LEFT(f->height, - f->o_cur) ;
00618
00619
00620 if (f->O == 0)
00621 return VL_ERR_EOF ;
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 octave = vl_sift_get_octave (f, s_min) ;
00634
00635 if (o_min < 0) {
00636
00637 copy_and_upsample_rows (temp, im, width, height) ;
00638 copy_and_upsample_rows (octave, temp, height, 2 * width ) ;
00639
00640
00641 for(o = -1 ; o > o_min ; --o) {
00642 copy_and_upsample_rows (temp, octave,
00643 width << -o, height << -o ) ;
00644 copy_and_upsample_rows (octave, temp,
00645 width << -o, 2 * (height << -o)) ;
00646 }
00647 }
00648 else if (o_min > 0) {
00649
00650 copy_and_downsample (octave, im, width, height, o_min) ;
00651 }
00652 else {
00653
00654 memcpy(octave, im, sizeof(vl_sift_pix) * width * height) ;
00655 }
00656
00657
00658
00659
00660
00661
00662
00663 sa = sigma0 * pow (sigmak, s_min) ;
00664 sb = sigman * pow (2.0, - o_min) ;
00665
00666 if (sa > sb) {
00667 double sd = sqrt (sa*sa - sb*sb) ;
00668 vl_imsmooth_f (octave, temp, octave, w, h, sd) ;
00669 }
00670
00671
00672
00673
00674
00675 for(s = s_min + 1 ; s <= s_max ; ++s) {
00676 double sd = dsigma0 * pow (sigmak, s) ;
00677 vl_imsmooth_f (vl_sift_get_octave(f, s ), temp,
00678 vl_sift_get_octave(f, s - 1), w, h, sd) ;
00679 }
00680
00681 return VL_ERR_OK ;
00682 }
00683
00699 VL_EXPORT
00700 int
00701 vl_sift_process_next_octave (VlSiftFilt *f)
00702 {
00703
00704 int s, h, w, s_best ;
00705 double sa, sb ;
00706 vl_sift_pix *octave, *pt ;
00707
00708
00709 vl_sift_pix *temp = f-> temp ;
00710 int O = f-> O ;
00711 int S = f-> S ;
00712 int o_min = f-> o_min ;
00713 int s_min = f-> s_min ;
00714 int s_max = f-> s_max ;
00715 double sigma0 = f-> sigma0 ;
00716 double sigmak = f-> sigmak ;
00717 double dsigma0 = f-> dsigma0 ;
00718
00719
00720 if (f->o_cur == o_min + O - 1)
00721 return VL_ERR_EOF ;
00722
00723
00724 s_best = VL_MIN(s_min + S, s_max) ;
00725 w = vl_sift_get_octave_width (f) ;
00726 h = vl_sift_get_octave_height (f) ;
00727 pt = vl_sift_get_octave (f, s_best) ;
00728 octave = vl_sift_get_octave (f, s_min) ;
00729
00730
00731 copy_and_downsample (octave, pt, w, h, 1) ;
00732
00733 f-> o_cur += 1 ;
00734 f-> nkeys = 0 ;
00735 w = f-> octave_width = VL_SHIFT_LEFT(f->width, - f->o_cur) ;
00736 h = f-> octave_height = VL_SHIFT_LEFT(f->height, - f->o_cur) ;
00737
00738 sa = sigma0 * powf (sigmak, s_min ) ;
00739 sb = sigma0 * powf (sigmak, s_best - S) ;
00740
00741 if (sa > sb) {
00742 double sd = sqrt (sa*sa - sb*sb) ;
00743 vl_imsmooth_f (octave, temp, octave, w, h, sd) ;
00744 }
00745
00746
00747
00748
00749
00750 for(s = s_min + 1 ; s <= s_max ; ++s) {
00751 double sd = dsigma0 * pow (sigmak, s) ;
00752 vl_imsmooth_f (vl_sift_get_octave(f, s ), temp,
00753 vl_sift_get_octave(f, s - 1), w, h, sd) ;
00754 }
00755
00756 return VL_ERR_OK ;
00757 }
00758
00769 VL_EXPORT
00770 void
00771 vl_sift_detect (VlSiftFilt * f)
00772 {
00773 vl_sift_pix* dog = f-> dog ;
00774 int s_min = f-> s_min ;
00775 int s_max = f-> s_max ;
00776 int w = f-> octave_width ;
00777 int h = f-> octave_height ;
00778 double te = f-> edge_thresh ;
00779 double tp = f-> peak_thresh ;
00780
00781 int const xo = 1 ;
00782 int const yo = w ;
00783 int const so = w * h ;
00784
00785 double xper = pow (2.0, f->o_cur) ;
00786
00787 int x, y, s, i, ii, jj ;
00788 vl_sift_pix *pt, v ;
00789 VlSiftKeypoint *k ;
00790
00791
00792 f-> nkeys = 0 ;
00793
00794
00795 pt = f-> dog ;
00796 for (s = s_min ; s <= s_max - 1 ; ++s) {
00797 vl_sift_pix* src_a = vl_sift_get_octave (f, s ) ;
00798 vl_sift_pix* src_b = vl_sift_get_octave (f, s + 1) ;
00799 vl_sift_pix* end_a = src_a + w * h ;
00800 while (src_a != end_a) {
00801 *pt++ = *src_b++ - *src_a++ ;
00802 }
00803 }
00804
00805
00806
00807
00808
00809
00810 pt = dog + xo + yo + so ;
00811
00812 for(s = s_min + 1 ; s <= s_max - 2 ; ++s) {
00813 for(y = 1 ; y < h - 1 ; ++y) {
00814 for(x = 1 ; x < w - 1 ; ++x) {
00815 v = *pt ;
00816
00817 #define CHECK_NEIGHBORS(CMP,SGN) \
00818 ( v CMP ## = SGN 0.8 * tp && \
00819 v CMP *(pt + xo) && \
00820 v CMP *(pt - xo) && \
00821 v CMP *(pt + so) && \
00822 v CMP *(pt - so) && \
00823 v CMP *(pt + yo) && \
00824 v CMP *(pt - yo) && \
00825 \
00826 v CMP *(pt + yo + xo) && \
00827 v CMP *(pt + yo - xo) && \
00828 v CMP *(pt - yo + xo) && \
00829 v CMP *(pt - yo - xo) && \
00830 \
00831 v CMP *(pt + xo + so) && \
00832 v CMP *(pt - xo + so) && \
00833 v CMP *(pt + yo + so) && \
00834 v CMP *(pt - yo + so) && \
00835 v CMP *(pt + yo + xo + so) && \
00836 v CMP *(pt + yo - xo + so) && \
00837 v CMP *(pt - yo + xo + so) && \
00838 v CMP *(pt - yo - xo + so) && \
00839 \
00840 v CMP *(pt + xo - so) && \
00841 v CMP *(pt - xo - so) && \
00842 v CMP *(pt + yo - so) && \
00843 v CMP *(pt - yo - so) && \
00844 v CMP *(pt + yo + xo - so) && \
00845 v CMP *(pt + yo - xo - so) && \
00846 v CMP *(pt - yo + xo - so) && \
00847 v CMP *(pt - yo - xo - so) )
00848
00849 if (CHECK_NEIGHBORS(>,+) ||
00850 CHECK_NEIGHBORS(<,-) ) {
00851
00852
00853 if (f->nkeys >= f->keys_res) {
00854 f->keys_res += 500 ;
00855 if (f->keys) {
00856 f->keys = vl_realloc (f->keys,
00857 f->keys_res *
00858 sizeof(VlSiftKeypoint)) ;
00859 } else {
00860 f->keys = vl_malloc (f->keys_res *
00861 sizeof(VlSiftKeypoint)) ;
00862 }
00863 }
00864
00865 k = f->keys + (f->nkeys ++) ;
00866
00867 k-> ix = x ;
00868 k-> iy = y ;
00869 k-> is = s ;
00870 }
00871 pt += 1 ;
00872 }
00873 pt += 2 ;
00874 }
00875 pt += 2 * yo ;
00876 }
00877
00878
00879
00880
00881
00882
00883 k = f->keys ;
00884
00885 for (i = 0 ; i < f->nkeys ; ++i) {
00886
00887 int x = f-> keys [i] .ix ;
00888 int y = f-> keys [i] .iy ;
00889 int s = f-> keys [i]. is ;
00890
00891 double Dx=0,Dy=0,Ds=0,Dxx=0,Dyy=0,Dss=0,Dxy=0,Dxs=0,Dys=0 ;
00892 double A [3*3], b [3] ;
00893
00894 int dx = 0 ;
00895 int dy = 0 ;
00896
00897 int iter, i, j ;
00898
00899 for (iter = 0 ; iter < 5 ; ++iter) {
00900
00901 x += dx ;
00902 y += dy ;
00903
00904 pt = dog
00905 + xo * x
00906 + yo * y
00907 + so * (s - s_min) ;
00908
00910 #define at(dx,dy,ds) (*( pt + (dx)*xo + (dy)*yo + (ds)*so))
00911
00913 #define Aat(i,j) (A[(i)+(j)*3])
00914
00915
00916 Dx = 0.5 * (at(+1,0,0) - at(-1,0,0)) ;
00917 Dy = 0.5 * (at(0,+1,0) - at(0,-1,0));
00918 Ds = 0.5 * (at(0,0,+1) - at(0,0,-1)) ;
00919
00920
00921 Dxx = (at(+1,0,0) + at(-1,0,0) - 2.0 * at(0,0,0)) ;
00922 Dyy = (at(0,+1,0) + at(0,-1,0) - 2.0 * at(0,0,0)) ;
00923 Dss = (at(0,0,+1) + at(0,0,-1) - 2.0 * at(0,0,0)) ;
00924
00925 Dxy = 0.25 * ( at(+1,+1,0) + at(-1,-1,0) - at(-1,+1,0) - at(+1,-1,0) ) ;
00926 Dxs = 0.25 * ( at(+1,0,+1) + at(-1,0,-1) - at(-1,0,+1) - at(+1,0,-1) ) ;
00927 Dys = 0.25 * ( at(0,+1,+1) + at(0,-1,-1) - at(0,-1,+1) - at(0,+1,-1) ) ;
00928
00929
00930 Aat(0,0) = Dxx ;
00931 Aat(1,1) = Dyy ;
00932 Aat(2,2) = Dss ;
00933 Aat(0,1) = Aat(1,0) = Dxy ;
00934 Aat(0,2) = Aat(2,0) = Dxs ;
00935 Aat(1,2) = Aat(2,1) = Dys ;
00936
00937 b[0] = - Dx ;
00938 b[1] = - Dy ;
00939 b[2] = - Ds ;
00940
00941
00942 for(j = 0 ; j < 3 ; ++j) {
00943 double maxa = 0 ;
00944 double maxabsa = 0 ;
00945 int maxi = -1 ;
00946 double tmp ;
00947
00948
00949 for (i = j ; i < 3 ; ++i) {
00950 double a = Aat (i,j) ;
00951 double absa = vl_abs_d (a) ;
00952 if (absa > maxabsa) {
00953 maxa = a ;
00954 maxabsa = absa ;
00955 maxi = i ;
00956 }
00957 }
00958
00959
00960 if (maxabsa < 1e-10f) {
00961 b[0] = 0 ;
00962 b[1] = 0 ;
00963 b[2] = 0 ;
00964 break ;
00965 }
00966
00967 i = maxi ;
00968
00969
00970 for(jj = j ; jj < 3 ; ++jj) {
00971 tmp = Aat(i,jj) ; Aat(i,jj) = Aat(j,jj) ; Aat(j,jj) = tmp ;
00972 Aat(j,jj) /= maxa ;
00973 }
00974 tmp = b[j] ; b[j] = b[i] ; b[i] = tmp ;
00975 b[j] /= maxa ;
00976
00977
00978 for (ii = j+1 ; ii < 3 ; ++ii) {
00979 double x = Aat(ii,j) ;
00980 for (jj = j ; jj < 3 ; ++jj) {
00981 Aat(ii,jj) -= x * Aat(j,jj) ;
00982 }
00983 b[ii] -= x * b[j] ;
00984 }
00985 }
00986
00987
00988 for (i = 2 ; i > 0 ; --i) {
00989 double x = b[i] ;
00990 for (ii = i-1 ; ii >= 0 ; --ii) {
00991 b[ii] -= x * Aat(ii,i) ;
00992 }
00993 }
00994
00995
00996
00997
00998
00999
01000 dx= ((b[0] > 0.6 && x < w - 2) ? 1 : 0)
01001 + ((b[0] < -0.6 && x > 1 ) ? -1 : 0) ;
01002
01003 dy= ((b[1] > 0.6 && y < h - 2) ? 1 : 0)
01004 + ((b[1] < -0.6 && y > 1 ) ? -1 : 0) ;
01005
01006 if (dx == 0 && dy == 0) break ;
01007 }
01008
01009
01010 {
01011 double val = at(0,0,0)
01012 + 0.5 * (Dx * b[0] + Dy * b[1] + Ds * b[2]) ;
01013 double score = (Dxx+Dyy)*(Dxx+Dyy) / (Dxx*Dyy - Dxy*Dxy) ;
01014 double xn = x + b[0] ;
01015 double yn = y + b[1] ;
01016 double sn = s + b[2] ;
01017
01018 vl_bool good =
01019 vl_abs_d (val) > tp &&
01020 score < (te+1)*(te+1)/te &&
01021 score >= 0 &&
01022 vl_abs_d (b[0]) < 1.5 &&
01023 vl_abs_d (b[1]) < 1.5 &&
01024 vl_abs_d (b[2]) < 1.5 &&
01025 xn >= 0 &&
01026 xn <= w - 1 &&
01027 yn >= 0 &&
01028 yn <= h - 1 &&
01029 sn >= s_min &&
01030 sn <= s_max ;
01031
01032 if (good) {
01033 k-> o = f->o_cur ;
01034 k-> ix = x ;
01035 k-> iy = y ;
01036 k-> is = s ;
01037 k-> s = sn ;
01038 k-> x = xn * xper ;
01039 k-> y = yn * xper ;
01040 k-> sigma = f->sigma0 * pow (2.0, sn/f->S) * xper ;
01041 ++ k ;
01042 }
01043
01044 }
01045 }
01046
01047
01048 f-> nkeys = k - f->keys ;
01049 }
01050
01051
01064 static void
01065 update_gradient (VlSiftFilt *f)
01066 {
01067 int s_min = f->s_min ;
01068 int s_max = f->s_max ;
01069 int w = vl_sift_get_octave_width (f) ;
01070 int h = vl_sift_get_octave_height (f) ;
01071 int const xo = 1 ;
01072 int const yo = w ;
01073 int const so = h * w ;
01074 int y, s ;
01075
01076 if (f->grad_o == f->o_cur) return ;
01077
01078 for (s = s_min + 1 ;
01079 s <= s_max - 2 ; ++ s) {
01080
01081 vl_sift_pix *src, *end, *grad, gx, gy ;
01082
01083 #define SAVE_BACK \
01084 *grad++ = vl_fast_sqrt_f (gx*gx + gy*gy) ; \
01085 *grad++ = vl_mod_2pi_f (vl_fast_atan2_f (gy, gx) + 2*VL_PI) ; \
01086 ++src ; \
01087
01088 src = vl_sift_get_octave (f,s) ;
01089 grad = f->grad + 2 * so * (s - s_min -1) ;
01090
01091
01092 gx = src[+xo] - src[0] ;
01093 gy = src[+yo] - src[0] ;
01094 SAVE_BACK ;
01095
01096
01097 end = (src - 1) + w - 1 ;
01098 while (src < end) {
01099 gx = 0.5 * (src[+xo] - src[-xo]) ;
01100 gy = src[+yo] - src[0] ;
01101 SAVE_BACK ;
01102 }
01103
01104
01105 gx = src[0] - src[-xo] ;
01106 gy = src[+yo] - src[0] ;
01107 SAVE_BACK ;
01108
01109 for (y = 1 ; y < h -1 ; ++y) {
01110
01111
01112 gx = src[+xo] - src[0] ;
01113 gy = 0.5 * (src[+yo] - src[-yo]) ;
01114 SAVE_BACK ;
01115
01116
01117 end = (src - 1) + w - 1 ;
01118 while (src < end) {
01119 gx = 0.5 * (src[+xo] - src[-xo]) ;
01120 gy = 0.5 * (src[+yo] - src[-yo]) ;
01121 SAVE_BACK ;
01122 }
01123
01124
01125 gx = src[0] - src[-xo] ;
01126 gy = 0.5 * (src[+yo] - src[-yo]) ;
01127 SAVE_BACK ;
01128 }
01129
01130
01131 gx = src[+xo] - src[0] ;
01132 gy = src[ 0] - src[-yo] ;
01133 SAVE_BACK ;
01134
01135
01136 end = (src - 1) + w - 1 ;
01137 while (src < end) {
01138 gx = 0.5 * (src[+xo] - src[-xo]) ;
01139 gy = src[0] - src[-yo] ;
01140 SAVE_BACK ;
01141 }
01142
01143
01144 gx = src[0] - src[-xo] ;
01145 gy = src[0] - src[-yo] ;
01146 SAVE_BACK ;
01147 }
01148 f->grad_o = f->o_cur ;
01149 }
01150
01175 VL_EXPORT
01176 int
01177 vl_sift_calc_keypoint_orientations (VlSiftFilt *f,
01178 double angles [4],
01179 VlSiftKeypoint const *k)
01180 {
01181 double const winf = 1.5 ;
01182 double xper = pow (2.0, f->o_cur) ;
01183
01184 int w = f-> octave_width ;
01185 int h = f-> octave_height ;
01186 int const xo = 2 ;
01187 int const yo = 2 * w ;
01188 int const so = 2 * w * h ;
01189 double x = k-> x / xper ;
01190 double y = k-> y / xper ;
01191 double sigma = k-> sigma / xper ;
01192
01193 int xi = (int) (x + 0.5) ;
01194 int yi = (int) (y + 0.5) ;
01195 int si = k-> is ;
01196
01197 double const sigmaw = winf * sigma ;
01198 int W = VL_MAX(floor (3.0 * sigmaw), 1) ;
01199
01200 int nangles= 0 ;
01201
01202 enum {nbins = 36} ;
01203
01204 double hist [nbins], maxh ;
01205 vl_sift_pix const * pt ;
01206 int xs, ys, iter, i ;
01207
01208
01209 if(k->o != f->o_cur)
01210 return 0 ;
01211
01212
01213 if(xi < 0 ||
01214 xi > w - 1 ||
01215 yi < 0 ||
01216 yi > h - 1 ||
01217 si < f->s_min + 1 ||
01218 si > f->s_max - 2 ) {
01219 return 0 ;
01220 }
01221
01222
01223 update_gradient (f) ;
01224
01225
01226 memset (hist, 0, sizeof(double) * nbins) ;
01227
01228
01229 pt = f-> grad + xo*xi + yo*yi + so*(si - f->s_min - 1) ;
01230
01231 #undef at
01232 #define at(dx,dy) (*(pt + xo * (dx) + yo * (dy)))
01233
01234
01235
01236
01237
01238
01239
01240
01241 for(ys = VL_MAX (- W, - yi) ;
01242 ys <= VL_MIN (+ W, h - 1 - yi) ; ++ys) {
01243
01244 for(xs = VL_MAX (- W, - xi) ;
01245 xs <= VL_MIN (+ W, w - 1 - xi) ; ++xs) {
01246
01247
01248 double dx = (double)(xi + xs) - x;
01249 double dy = (double)(yi + ys) - y;
01250 double r2 = dx*dx + dy*dy ;
01251 double wgt, mod, ang, fbin ;
01252
01253
01254 if (r2 >= W*W + 0.6) continue ;
01255
01256 wgt = fast_expn (r2 / (2*sigmaw*sigmaw)) ;
01257 mod = *(pt + xs*xo + ys*yo ) ;
01258 ang = *(pt + xs*xo + ys*yo + 1) ;
01259 fbin = nbins * ang / (2 * VL_PI) ;
01260
01261 #if defined(VL_SIFT_BILINEAR_ORIENTATIONS)
01262 {
01263 int bin = vl_floor_d (fbin - 0.5) ;
01264 double rbin = fbin - bin - 0.5 ;
01265 hist [(bin + nbins) % nbins] += (1 - rbin) * mod * wgt ;
01266 hist [(bin + 1 ) % nbins] += ( rbin) * mod * wgt ;
01267 }
01268 #else
01269 {
01270 int bin = vl_floor_d (fbin) ;
01271 bin = vl_floor_d (nbins * ang / (2*VL_PI)) ;
01272 hist [(bin) % nbins] += mod * wgt ;
01273 }
01274 #endif
01275
01276 }
01277 }
01278
01279
01280 for (iter = 0; iter < 6; iter ++) {
01281 double prev = hist [nbins - 1] ;
01282 double first = hist [0] ;
01283 int i ;
01284 for (i = 0; i < nbins - 1; i++) {
01285 double newh = (prev + hist[i] + hist[(i+1) % nbins]) / 3.0;
01286 prev = hist[i] ;
01287 hist[i] = newh ;
01288 }
01289 hist[i] = (prev + hist[i] + first) / 3.0 ;
01290 }
01291
01292
01293 maxh = 0 ;
01294 for (i = 0 ; i < nbins ; ++i)
01295 maxh = VL_MAX (maxh, hist [i]) ;
01296
01297
01298 nangles = 0 ;
01299 for(i = 0 ; i < nbins ; ++i) {
01300 double h0 = hist [i] ;
01301 double hm = hist [(i - 1 + nbins) % nbins] ;
01302 double hp = hist [(i + 1 + nbins) % nbins] ;
01303
01304
01305 if (h0 > 0.8*maxh && h0 > hm && h0 > hp) {
01306
01307
01308 double di = - 0.5 * (hp - hm) / (hp + hm - 2 * h0) ;
01309 double th = 2 * VL_PI * (i + di + 0.5) / nbins ;
01310 angles [ nangles++ ] = th ;
01311 if( nangles == 4 )
01312 goto enough_angles ;
01313 }
01314 }
01315 enough_angles:
01316 return nangles ;
01317 }
01318
01319
01327 VL_INLINE vl_sift_pix
01328 normalize_histogram
01329 (vl_sift_pix *begin, vl_sift_pix *end)
01330 {
01331 vl_sift_pix* iter ;
01332 vl_sift_pix norm = 0.0 ;
01333
01334 for (iter = begin ; iter != end ; ++ iter)
01335 norm += (*iter) * (*iter) ;
01336
01337 norm = vl_fast_sqrt_f (norm) + VL_EPSILON_F ;
01338
01339 for (iter = begin; iter != end ; ++ iter)
01340 *iter /= norm ;
01341
01342 return norm;
01343 }
01344
01377 VL_EXPORT
01378 void
01379 vl_sift_calc_raw_descriptor (VlSiftFilt const *f,
01380 vl_sift_pix const* grad,
01381 vl_sift_pix *descr,
01382 int width, int height,
01383 double x, double y,
01384 double sigma,
01385 double angle0)
01386 {
01387 double const magnif = f-> magnif ;
01388 int const NBO = 8 ;
01389 int const NBP = 4 ;
01390
01391 int w = width ;
01392 int h = height ;
01393 int const xo = 2 ;
01394 int const yo = 2 * w ;
01395
01396 int xi = (int) (x + 0.5) ;
01397 int yi = (int) (y + 0.5) ;
01398
01399 double const st0 = sin (angle0) ;
01400 double const ct0 = cos (angle0) ;
01401 double const SBP = magnif * sigma + VL_EPSILON_D ;
01402 int const W = floor
01403 (sqrt(2.0) * SBP * (NBP + 1) / 2.0 + 0.5) ;
01404
01405 int const binto = 1 ;
01406 int const binyo = NBO * NBP ;
01407 int const binxo = NBO ;
01408
01409 int bin, dxi, dyi ;
01410 vl_sift_pix const *pt ;
01411 vl_sift_pix *dpt ;
01412
01413
01414 if(xi < 0 ||
01415 xi >= w ||
01416 yi < 0 ||
01417 yi >= h - 1 )
01418 return ;
01419
01420
01421 memset (descr, 0, sizeof(vl_sift_pix) * NBO*NBP*NBP) ;
01422
01423
01424
01425
01426 pt = grad + xi*xo + yi*yo ;
01427 dpt = descr + (NBP/2) * binyo + (NBP/2) * binxo ;
01428
01429 #undef atd
01430 #define atd(dbinx,dbiny,dbint) *(dpt + (dbint)*binto + (dbiny)*binyo + (dbinx)*binxo)
01431
01432
01433
01434
01435
01436 for(dyi = VL_MAX (- W, 1 - yi ) ;
01437 dyi <= VL_MIN (+ W, h - yi - 2) ; ++ dyi) {
01438
01439 for(dxi = VL_MAX (- W, 1 - xi ) ;
01440 dxi <= VL_MIN (+ W, w - xi - 2) ; ++ dxi) {
01441
01442
01443 vl_sift_pix mod = *( pt + dxi*xo + dyi*yo + 0 ) ;
01444 vl_sift_pix angle = *( pt + dxi*xo + dyi*yo + 1 ) ;
01445 vl_sift_pix theta = vl_mod_2pi_f (angle - angle0) ;
01446
01447
01448 vl_sift_pix dx = xi + dxi - x;
01449 vl_sift_pix dy = yi + dyi - y;
01450
01451
01452
01453 vl_sift_pix nx = ( ct0 * dx + st0 * dy) / SBP ;
01454 vl_sift_pix ny = (-st0 * dx + ct0 * dy) / SBP ;
01455 vl_sift_pix nt = NBO * theta / (2 * VL_PI) ;
01456
01457
01458
01459
01460
01461 vl_sift_pix const wsigma = NBP/2 ;
01462 vl_sift_pix win = fast_expn
01463 ((nx*nx + ny*ny)/(2.0 * wsigma * wsigma)) ;
01464
01465
01466
01467 int binx = vl_floor_f (nx - 0.5) ;
01468 int biny = vl_floor_f (ny - 0.5) ;
01469 int bint = vl_floor_f (nt) ;
01470 vl_sift_pix rbinx = nx - (binx + 0.5) ;
01471 vl_sift_pix rbiny = ny - (biny + 0.5) ;
01472 vl_sift_pix rbint = nt - bint ;
01473 int dbinx ;
01474 int dbiny ;
01475 int dbint ;
01476
01477
01478 for(dbinx = 0 ; dbinx < 2 ; ++dbinx) {
01479 for(dbiny = 0 ; dbiny < 2 ; ++dbiny) {
01480 for(dbint = 0 ; dbint < 2 ; ++dbint) {
01481
01482 if (binx + dbinx >= - (NBP/2) &&
01483 binx + dbinx < (NBP/2) &&
01484 biny + dbiny >= - (NBP/2) &&
01485 biny + dbiny < (NBP/2) ) {
01486 vl_sift_pix weight = win
01487 * mod
01488 * vl_abs_f (1 - dbinx - rbinx)
01489 * vl_abs_f (1 - dbiny - rbiny)
01490 * vl_abs_f (1 - dbint - rbint) ;
01491
01492 atd(binx+dbinx, biny+dbiny, (bint+dbint) % NBO) += weight ;
01493 }
01494 }
01495 }
01496 }
01497 }
01498 }
01499
01500
01501 if(1) {
01502
01503
01504 vl_sift_pix norm = normalize_histogram (descr, descr + NBO*NBP*NBP) ;
01505
01506
01507 if(f-> norm_thresh && norm < f-> norm_thresh) {
01508 for(bin = 0; bin < NBO*NBP*NBP ; ++ bin)
01509 descr [bin] = 0;
01510 }
01511 else {
01512
01513
01514 for(bin = 0; bin < NBO*NBP*NBP ; ++ bin) {
01515 if (descr [bin] > 0.2) descr [bin] = 0.2;
01516 }
01517
01518
01519 normalize_histogram (descr, descr + NBO*NBP*NBP) ;
01520 }
01521 }
01522 }
01523
01524
01541 VL_EXPORT
01542 void
01543 vl_sift_calc_keypoint_descriptor (VlSiftFilt *f,
01544 vl_sift_pix *descr,
01545 VlSiftKeypoint const* k,
01546 double angle0)
01547 {
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564 double const magnif = f-> magnif ;
01565 int const NBO = 8 ;
01566 int const NBP = 4 ;
01567
01568 double xper = pow (2.0, f->o_cur) ;
01569
01570 int w = f-> octave_width ;
01571 int h = f-> octave_height ;
01572 int const xo = 2 ;
01573 int const yo = 2 * w ;
01574 int const so = 2 * w * h ;
01575 double x = k-> x / xper ;
01576 double y = k-> y / xper ;
01577 double sigma = k-> sigma / xper ;
01578
01579 int xi = (int) (x + 0.5) ;
01580 int yi = (int) (y + 0.5) ;
01581 int si = k-> is ;
01582
01583 double const st0 = sin (angle0) ;
01584 double const ct0 = cos (angle0) ;
01585 double const SBP = magnif * sigma ;
01586 int const W = floor
01587 (sqrt(2.0) * SBP * (NBP + 1) / 2.0 + 0.5) ;
01588
01589 int const binto = 1 ;
01590 int const binyo = NBO * NBP ;
01591 int const binxo = NBO ;
01592
01593 int bin, dxi, dyi ;
01594 vl_sift_pix const *pt ;
01595 vl_sift_pix *dpt ;
01596
01597
01598 if(k->o != f->o_cur ||
01599 xi < 0 ||
01600 xi >= w ||
01601 yi < 0 ||
01602 yi >= h - 1 ||
01603 si < f->s_min + 1 ||
01604 si > f->s_max - 2 )
01605 return ;
01606
01607
01608 update_gradient (f) ;
01609
01610
01611
01612
01613 memset (descr, 0, sizeof(vl_sift_pix) * NBO*NBP*NBP) ;
01614
01615
01616
01617
01618 pt = f->grad + xi*xo + yi*yo + (si - f->s_min - 1)*so ;
01619 dpt = descr + (NBP/2) * binyo + (NBP/2) * binxo ;
01620
01621 #undef atd
01622 #define atd(dbinx,dbiny,dbint) *(dpt + (dbint)*binto + (dbiny)*binyo + (dbinx)*binxo)
01623
01624
01625
01626
01627
01628 for(dyi = VL_MAX (- W, 1 - yi ) ;
01629 dyi <= VL_MIN (+ W, h - yi - 2) ; ++ dyi) {
01630
01631 for(dxi = VL_MAX (- W, 1 - xi ) ;
01632 dxi <= VL_MIN (+ W, w - xi - 2) ; ++ dxi) {
01633
01634
01635 vl_sift_pix mod = *( pt + dxi*xo + dyi*yo + 0 ) ;
01636 vl_sift_pix angle = *( pt + dxi*xo + dyi*yo + 1 ) ;
01637 vl_sift_pix theta = vl_mod_2pi_f (angle - angle0) ;
01638
01639
01640 vl_sift_pix dx = xi + dxi - x;
01641 vl_sift_pix dy = yi + dyi - y;
01642
01643
01644
01645 vl_sift_pix nx = ( ct0 * dx + st0 * dy) / SBP ;
01646 vl_sift_pix ny = (-st0 * dx + ct0 * dy) / SBP ;
01647 vl_sift_pix nt = NBO * theta / (2 * VL_PI) ;
01648
01649
01650
01651
01652
01653 vl_sift_pix const wsigma = NBP/2 ;
01654 vl_sift_pix win = fast_expn
01655 ((nx*nx + ny*ny)/(2.0 * wsigma * wsigma)) ;
01656
01657
01658
01659 int binx = vl_floor_f (nx - 0.5) ;
01660 int biny = vl_floor_f (ny - 0.5) ;
01661 int bint = vl_floor_f (nt) ;
01662 vl_sift_pix rbinx = nx - (binx + 0.5) ;
01663 vl_sift_pix rbiny = ny - (biny + 0.5) ;
01664 vl_sift_pix rbint = nt - bint ;
01665 int dbinx ;
01666 int dbiny ;
01667 int dbint ;
01668
01669
01670 for(dbinx = 0 ; dbinx < 2 ; ++dbinx) {
01671 for(dbiny = 0 ; dbiny < 2 ; ++dbiny) {
01672 for(dbint = 0 ; dbint < 2 ; ++dbint) {
01673
01674 if (binx + dbinx >= - (NBP/2) &&
01675 binx + dbinx < (NBP/2) &&
01676 biny + dbiny >= - (NBP/2) &&
01677 biny + dbiny < (NBP/2) ) {
01678 vl_sift_pix weight = win
01679 * mod
01680 * vl_abs_f (1 - dbinx - rbinx)
01681 * vl_abs_f (1 - dbiny - rbiny)
01682 * vl_abs_f (1 - dbint - rbint) ;
01683
01684 atd(binx+dbinx, biny+dbiny, (bint+dbint) % NBO) += weight ;
01685 }
01686 }
01687 }
01688 }
01689 }
01690 }
01691
01692
01693 if(1) {
01694
01695
01696 vl_sift_pix norm = normalize_histogram (descr, descr + NBO*NBP*NBP) ;
01697
01698
01699 if(f-> norm_thresh && norm < f-> norm_thresh) {
01700 for(bin = 0; bin < NBO*NBP*NBP ; ++ bin)
01701 descr [bin] = 0;
01702 }
01703 else {
01704
01705
01706 for(bin = 0; bin < NBO*NBP*NBP ; ++ bin) {
01707 if (descr [bin] > 0.2) descr [bin] = 0.2;
01708 }
01709
01710
01711 normalize_histogram (descr, descr + NBO*NBP*NBP) ;
01712 }
01713 }
01714
01715 }
01716
01730 VL_EXPORT
01731 void
01732 vl_sift_keypoint_init (VlSiftFilt const *f,
01733 VlSiftKeypoint *k,
01734 double x,
01735 double y,
01736 double sigma)
01737 {
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796 int o, ix, iy, is ;
01797 double s, phi, xper ;
01798
01799 phi = log2 (sigma / f->sigma0) ;
01800 o = vl_floor_d (phi - ((double) f->s_min + 0.5) / f->S) ;
01801 o = VL_MIN (o, f->o_min + f->O - 1) ;
01802 o = VL_MAX (o, f->o_min ) ;
01803 s = f->S * (phi - o) ;
01804
01805 is = (int)(s + 0.5) ;
01806 is = VL_MIN(is, f->s_max - 2) ;
01807 is = VL_MAX(is, f->s_min + 1) ;
01808
01809 xper = pow (2.0, o) ;
01810 ix = (int)(x / xper + 0.5) ;
01811 iy = (int)(y / xper + 0.5) ;
01812
01813 k -> o = o ;
01814
01815 k -> ix = ix ;
01816 k -> iy = iy ;
01817 k -> is = is ;
01818
01819 k -> x = x ;
01820 k -> y = y ;
01821 k -> s = s ;
01822
01823 k->sigma = sigma ;
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835 }