00001
00007
00008
00009
00010
00011
00012
00013
00674 #include "sift.h"
00675 #include "imop.h"
00676 #include "mathop.h"
00677
00678 #include <assert.h>
00679 #include <stdlib.h>
00680 #include <string.h>
00681 #include <math.h>
00682 #include <stdio.h>
00683
00685 #define VL_SIFT_BILINEAR_ORIENTATIONS 1
00686
00687 #define EXPN_SZ 256
00688 #define EXPN_MAX 25.0
00689 double expn_tab [EXPN_SZ+1] ;
00691 #define NBO 8
00692 #define NBP 4
00693
00694 #define log2(x) (log(x)/VL_LOG_OF_2)
00695
00707 VL_INLINE double
00708 fast_expn (double x)
00709 {
00710 double a,b,r ;
00711 int i ;
00712
00713
00714 if (x > EXPN_MAX) return 0.0 ;
00715
00716 x *= EXPN_SZ / EXPN_MAX ;
00717 i = vl_floor_d (x) ;
00718 r = x - i ;
00719 a = expn_tab [i ] ;
00720 b = expn_tab [i + 1] ;
00721 return a + r * (b - a) ;
00722 }
00723
00729 VL_INLINE void
00730 fast_expn_init ()
00731 {
00732 int k ;
00733 for(k = 0 ; k < EXPN_SZ + 1 ; ++ k) {
00734 expn_tab [k] = exp (- (double) k * (EXPN_MAX / EXPN_SZ)) ;
00735 }
00736 }
00737
00754 static void
00755 copy_and_upsample_rows
00756 (vl_sift_pix *dst,
00757 vl_sift_pix const *src, int width, int height)
00758 {
00759 int x, y ;
00760 vl_sift_pix a, b ;
00761
00762 for(y = 0 ; y < height ; ++y) {
00763 b = a = *src++ ;
00764 for(x = 0 ; x < width - 1 ; ++x) {
00765 b = *src++ ;
00766 *dst = a ; dst += height ;
00767 *dst = 0.5 * (a + b) ; dst += height ;
00768 a = b ;
00769 }
00770 *dst = b ; dst += height ;
00771 *dst = b ; dst += height ;
00772 dst += 1 - width * 2 * height ;
00773 }
00774 }
00775
00793 static void
00794 copy_and_downsample
00795 (vl_sift_pix *dst,
00796 vl_sift_pix const *src,
00797 int width, int height, int d)
00798 {
00799 int x, y ;
00800
00801 d = 1 << d ;
00802 for(y = 0 ; y < height ; y+=d) {
00803 vl_sift_pix const * srcrowp = src + y * width ;
00804 for(x = 0 ; x < width - (d-1) ; x+=d) {
00805 *dst++ = *srcrowp ;
00806 srcrowp += d ;
00807 }
00808 }
00809 }
00810
00830 VL_EXPORT
00831 VlSiftFilt *
00832 vl_sift_new (int width, int height,
00833 int noctaves, int nlevels,
00834 int o_min)
00835 {
00836 VlSiftFilt *f = vl_malloc (sizeof(VlSiftFilt)) ;
00837
00838 int w = VL_SHIFT_LEFT (width, -o_min) ;
00839 int h = VL_SHIFT_LEFT (height, -o_min) ;
00840 int nel = w * h ;
00841
00842
00843 if (noctaves < 0) {
00844 noctaves = VL_MAX (floor (log2 (VL_MIN(width, height))) - o_min - 3, 1) ;
00845 }
00846
00847 f-> width = width ;
00848 f-> height = height ;
00849 f-> O = noctaves ;
00850 f-> S = nlevels ;
00851 f-> o_min = o_min ;
00852 f-> s_min = -1 ;
00853 f-> s_max = nlevels + 1 ;
00854 f-> o_cur = o_min ;
00855
00856 f-> temp = vl_malloc (sizeof(vl_sift_pix) * nel ) ;
00857 f-> octave = vl_malloc (sizeof(vl_sift_pix) * nel
00858 * (f->s_max - f->s_min + 1) ) ;
00859 f-> dog = vl_malloc (sizeof(vl_sift_pix) * nel
00860 * (f->s_max - f->s_min ) ) ;
00861 f-> grad = vl_malloc (sizeof(vl_sift_pix) * nel * 2
00862 * (f->s_max - f->s_min ) ) ;
00863
00864 f-> sigman = 0.5 ;
00865 f-> sigma0 = 1.6 * pow (2.0, 1.0 / nlevels) ;
00866 f-> sigmak = pow (2.0, 1.0 / nlevels) ;
00867 f-> dsigma0 = f->sigma0 * sqrt (1.0 - 1.0 / (f->sigmak*f->sigmak)) ;
00868
00869
00870
00871
00872
00873
00874 f-> octave_width = 0 ;
00875 f-> octave_height = 0 ;
00876
00877 f-> keys = 0 ;
00878 f-> nkeys = 0 ;
00879 f-> keys_res = 0 ;
00880
00881 f-> peak_thresh = 0.0 ;
00882 f-> edge_thresh = 10.0 ;
00883 f-> norm_thresh = 0.0 ;
00884 f-> magnif = 3.0 ;
00885 f-> windowSize = NBP / 2 ;
00886
00887 f-> grad_o = o_min - 1 ;
00888
00889
00890 fast_expn_init () ;
00891
00892 return f ;
00893 }
00894
00903 VL_EXPORT
00904 void
00905 vl_sift_delete (VlSiftFilt* f)
00906 {
00907 if(f) {
00908 if(f-> keys ) vl_free (f-> keys ) ;
00909 if(f-> grad ) vl_free (f-> grad ) ;
00910 if(f-> dog ) vl_free (f-> dog ) ;
00911 if(f-> octave ) vl_free (f-> octave ) ;
00912 if(f-> temp ) vl_free (f-> temp ) ;
00913 vl_free (f) ;
00914 }
00915 }
00916
00933 VL_EXPORT
00934 int
00935 vl_sift_process_first_octave (VlSiftFilt *f, vl_sift_pix const *im)
00936 {
00937 int o, s, h, w ;
00938 double sa, sb ;
00939 vl_sift_pix *octave ;
00940
00941
00942 vl_sift_pix *temp = f-> temp ;
00943 int width = f-> width ;
00944 int height = f-> height ;
00945 int o_min = f-> o_min ;
00946 int s_min = f-> s_min ;
00947 int s_max = f-> s_max ;
00948 double sigma0 = f-> sigma0 ;
00949 double sigmak = f-> sigmak ;
00950 double sigman = f-> sigman ;
00951 double dsigma0 = f-> dsigma0 ;
00952
00953
00954 f->o_cur = o_min ;
00955 f->nkeys = 0 ;
00956 w = f-> octave_width = VL_SHIFT_LEFT(f->width, - f->o_cur) ;
00957 h = f-> octave_height = VL_SHIFT_LEFT(f->height, - f->o_cur) ;
00958
00959
00960 if (f->O == 0)
00961 return VL_ERR_EOF ;
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973 octave = vl_sift_get_octave (f, s_min) ;
00974
00975 if (o_min < 0) {
00976
00977 copy_and_upsample_rows (temp, im, width, height) ;
00978 copy_and_upsample_rows (octave, temp, height, 2 * width ) ;
00979
00980
00981 for(o = -1 ; o > o_min ; --o) {
00982 copy_and_upsample_rows (temp, octave,
00983 width << -o, height << -o ) ;
00984 copy_and_upsample_rows (octave, temp,
00985 width << -o, 2 * (height << -o)) ;
00986 }
00987 }
00988 else if (o_min > 0) {
00989
00990 copy_and_downsample (octave, im, width, height, o_min) ;
00991 }
00992 else {
00993
00994 memcpy(octave, im, sizeof(vl_sift_pix) * width * height) ;
00995 }
00996
00997
00998
00999
01000
01001
01002
01003 sa = sigma0 * pow (sigmak, s_min) ;
01004 sb = sigman * pow (2.0, - o_min) ;
01005
01006 if (sa > sb) {
01007 double sd = sqrt (sa*sa - sb*sb) ;
01008 vl_imsmooth_f (octave, temp, octave, w, h, sd) ;
01009 }
01010
01011
01012
01013
01014
01015 for(s = s_min + 1 ; s <= s_max ; ++s) {
01016 double sd = dsigma0 * pow (sigmak, s) ;
01017 vl_imsmooth_f (vl_sift_get_octave(f, s ), temp,
01018 vl_sift_get_octave(f, s - 1), w, h, sd) ;
01019 }
01020
01021 return VL_ERR_OK ;
01022 }
01023
01039 VL_EXPORT
01040 int
01041 vl_sift_process_next_octave (VlSiftFilt *f)
01042 {
01043
01044 int s, h, w, s_best ;
01045 double sa, sb ;
01046 vl_sift_pix *octave, *pt ;
01047
01048
01049 vl_sift_pix *temp = f-> temp ;
01050 int O = f-> O ;
01051 int S = f-> S ;
01052 int o_min = f-> o_min ;
01053 int s_min = f-> s_min ;
01054 int s_max = f-> s_max ;
01055 double sigma0 = f-> sigma0 ;
01056 double sigmak = f-> sigmak ;
01057 double dsigma0 = f-> dsigma0 ;
01058
01059
01060 if (f->o_cur == o_min + O - 1)
01061 return VL_ERR_EOF ;
01062
01063
01064 s_best = VL_MIN(s_min + S, s_max) ;
01065 w = vl_sift_get_octave_width (f) ;
01066 h = vl_sift_get_octave_height (f) ;
01067 pt = vl_sift_get_octave (f, s_best) ;
01068 octave = vl_sift_get_octave (f, s_min) ;
01069
01070
01071 copy_and_downsample (octave, pt, w, h, 1) ;
01072
01073 f-> o_cur += 1 ;
01074 f-> nkeys = 0 ;
01075 w = f-> octave_width = VL_SHIFT_LEFT(f->width, - f->o_cur) ;
01076 h = f-> octave_height = VL_SHIFT_LEFT(f->height, - f->o_cur) ;
01077
01078 sa = sigma0 * powf (sigmak, s_min ) ;
01079 sb = sigma0 * powf (sigmak, s_best - S) ;
01080
01081 if (sa > sb) {
01082 double sd = sqrt (sa*sa - sb*sb) ;
01083 vl_imsmooth_f (octave, temp, octave, w, h, sd) ;
01084 }
01085
01086
01087
01088
01089
01090 for(s = s_min + 1 ; s <= s_max ; ++s) {
01091 double sd = dsigma0 * pow (sigmak, s) ;
01092 vl_imsmooth_f (vl_sift_get_octave(f, s ), temp,
01093 vl_sift_get_octave(f, s - 1), w, h, sd) ;
01094 }
01095
01096 return VL_ERR_OK ;
01097 }
01098
01109 VL_EXPORT
01110 void
01111 vl_sift_detect (VlSiftFilt * f)
01112 {
01113 vl_sift_pix* dog = f-> dog ;
01114 int s_min = f-> s_min ;
01115 int s_max = f-> s_max ;
01116 int w = f-> octave_width ;
01117 int h = f-> octave_height ;
01118 double te = f-> edge_thresh ;
01119 double tp = f-> peak_thresh ;
01120
01121 int const xo = 1 ;
01122 int const yo = w ;
01123 int const so = w * h ;
01124
01125 double xper = pow (2.0, f->o_cur) ;
01126
01127 int x, y, s, i, ii, jj ;
01128 vl_sift_pix *pt, v ;
01129 VlSiftKeypoint *k ;
01130
01131
01132 f-> nkeys = 0 ;
01133
01134
01135 pt = f-> dog ;
01136 for (s = s_min ; s <= s_max - 1 ; ++s) {
01137 vl_sift_pix* src_a = vl_sift_get_octave (f, s ) ;
01138 vl_sift_pix* src_b = vl_sift_get_octave (f, s + 1) ;
01139 vl_sift_pix* end_a = src_a + w * h ;
01140 while (src_a != end_a) {
01141 *pt++ = *src_b++ - *src_a++ ;
01142 }
01143 }
01144
01145
01146
01147
01148
01149
01150 pt = dog + xo + yo + so ;
01151
01152 for(s = s_min + 1 ; s <= s_max - 2 ; ++s) {
01153 for(y = 1 ; y < h - 1 ; ++y) {
01154 for(x = 1 ; x < w - 1 ; ++x) {
01155 v = *pt ;
01156
01157 #define CHECK_NEIGHBORS(CMP,SGN) \
01158 ( v CMP ## = SGN 0.8 * tp && \
01159 v CMP *(pt + xo) && \
01160 v CMP *(pt - xo) && \
01161 v CMP *(pt + so) && \
01162 v CMP *(pt - so) && \
01163 v CMP *(pt + yo) && \
01164 v CMP *(pt - yo) && \
01165 \
01166 v CMP *(pt + yo + xo) && \
01167 v CMP *(pt + yo - xo) && \
01168 v CMP *(pt - yo + xo) && \
01169 v CMP *(pt - yo - xo) && \
01170 \
01171 v CMP *(pt + xo + so) && \
01172 v CMP *(pt - xo + so) && \
01173 v CMP *(pt + yo + so) && \
01174 v CMP *(pt - yo + so) && \
01175 v CMP *(pt + yo + xo + so) && \
01176 v CMP *(pt + yo - xo + so) && \
01177 v CMP *(pt - yo + xo + so) && \
01178 v CMP *(pt - yo - xo + so) && \
01179 \
01180 v CMP *(pt + xo - so) && \
01181 v CMP *(pt - xo - so) && \
01182 v CMP *(pt + yo - so) && \
01183 v CMP *(pt - yo - so) && \
01184 v CMP *(pt + yo + xo - so) && \
01185 v CMP *(pt + yo - xo - so) && \
01186 v CMP *(pt - yo + xo - so) && \
01187 v CMP *(pt - yo - xo - so) )
01188
01189 if (CHECK_NEIGHBORS(>,+) ||
01190 CHECK_NEIGHBORS(<,-) ) {
01191
01192
01193 if (f->nkeys >= f->keys_res) {
01194 f->keys_res += 500 ;
01195 if (f->keys) {
01196 f->keys = vl_realloc (f->keys,
01197 f->keys_res *
01198 sizeof(VlSiftKeypoint)) ;
01199 } else {
01200 f->keys = vl_malloc (f->keys_res *
01201 sizeof(VlSiftKeypoint)) ;
01202 }
01203 }
01204
01205 k = f->keys + (f->nkeys ++) ;
01206
01207 k-> ix = x ;
01208 k-> iy = y ;
01209 k-> is = s ;
01210 }
01211 pt += 1 ;
01212 }
01213 pt += 2 ;
01214 }
01215 pt += 2 * yo ;
01216 }
01217
01218
01219
01220
01221
01222
01223 k = f->keys ;
01224
01225 for (i = 0 ; i < f->nkeys ; ++i) {
01226
01227 int x = f-> keys [i] .ix ;
01228 int y = f-> keys [i] .iy ;
01229 int s = f-> keys [i]. is ;
01230
01231 double Dx=0,Dy=0,Ds=0,Dxx=0,Dyy=0,Dss=0,Dxy=0,Dxs=0,Dys=0 ;
01232 double A [3*3], b [3] ;
01233
01234 int dx = 0 ;
01235 int dy = 0 ;
01236
01237 int iter, i, j ;
01238
01239 for (iter = 0 ; iter < 5 ; ++iter) {
01240
01241 x += dx ;
01242 y += dy ;
01243
01244 pt = dog
01245 + xo * x
01246 + yo * y
01247 + so * (s - s_min) ;
01248
01250 #define at(dx,dy,ds) (*( pt + (dx)*xo + (dy)*yo + (ds)*so))
01251
01253 #define Aat(i,j) (A[(i)+(j)*3])
01254
01255
01256 Dx = 0.5 * (at(+1,0,0) - at(-1,0,0)) ;
01257 Dy = 0.5 * (at(0,+1,0) - at(0,-1,0));
01258 Ds = 0.5 * (at(0,0,+1) - at(0,0,-1)) ;
01259
01260
01261 Dxx = (at(+1,0,0) + at(-1,0,0) - 2.0 * at(0,0,0)) ;
01262 Dyy = (at(0,+1,0) + at(0,-1,0) - 2.0 * at(0,0,0)) ;
01263 Dss = (at(0,0,+1) + at(0,0,-1) - 2.0 * at(0,0,0)) ;
01264
01265 Dxy = 0.25 * ( at(+1,+1,0) + at(-1,-1,0) - at(-1,+1,0) - at(+1,-1,0) ) ;
01266 Dxs = 0.25 * ( at(+1,0,+1) + at(-1,0,-1) - at(-1,0,+1) - at(+1,0,-1) ) ;
01267 Dys = 0.25 * ( at(0,+1,+1) + at(0,-1,-1) - at(0,-1,+1) - at(0,+1,-1) ) ;
01268
01269
01270 Aat(0,0) = Dxx ;
01271 Aat(1,1) = Dyy ;
01272 Aat(2,2) = Dss ;
01273 Aat(0,1) = Aat(1,0) = Dxy ;
01274 Aat(0,2) = Aat(2,0) = Dxs ;
01275 Aat(1,2) = Aat(2,1) = Dys ;
01276
01277 b[0] = - Dx ;
01278 b[1] = - Dy ;
01279 b[2] = - Ds ;
01280
01281
01282 for(j = 0 ; j < 3 ; ++j) {
01283 double maxa = 0 ;
01284 double maxabsa = 0 ;
01285 int maxi = -1 ;
01286 double tmp ;
01287
01288
01289 for (i = j ; i < 3 ; ++i) {
01290 double a = Aat (i,j) ;
01291 double absa = vl_abs_d (a) ;
01292 if (absa > maxabsa) {
01293 maxa = a ;
01294 maxabsa = absa ;
01295 maxi = i ;
01296 }
01297 }
01298
01299
01300 if (maxabsa < 1e-10f) {
01301 b[0] = 0 ;
01302 b[1] = 0 ;
01303 b[2] = 0 ;
01304 break ;
01305 }
01306
01307 i = maxi ;
01308
01309
01310 for(jj = j ; jj < 3 ; ++jj) {
01311 tmp = Aat(i,jj) ; Aat(i,jj) = Aat(j,jj) ; Aat(j,jj) = tmp ;
01312 Aat(j,jj) /= maxa ;
01313 }
01314 tmp = b[j] ; b[j] = b[i] ; b[i] = tmp ;
01315 b[j] /= maxa ;
01316
01317
01318 for (ii = j+1 ; ii < 3 ; ++ii) {
01319 double x = Aat(ii,j) ;
01320 for (jj = j ; jj < 3 ; ++jj) {
01321 Aat(ii,jj) -= x * Aat(j,jj) ;
01322 }
01323 b[ii] -= x * b[j] ;
01324 }
01325 }
01326
01327
01328 for (i = 2 ; i > 0 ; --i) {
01329 double x = b[i] ;
01330 for (ii = i-1 ; ii >= 0 ; --ii) {
01331 b[ii] -= x * Aat(ii,i) ;
01332 }
01333 }
01334
01335
01336
01337
01338
01339
01340 dx= ((b[0] > 0.6 && x < w - 2) ? 1 : 0)
01341 + ((b[0] < -0.6 && x > 1 ) ? -1 : 0) ;
01342
01343 dy= ((b[1] > 0.6 && y < h - 2) ? 1 : 0)
01344 + ((b[1] < -0.6 && y > 1 ) ? -1 : 0) ;
01345
01346 if (dx == 0 && dy == 0) break ;
01347 }
01348
01349
01350 {
01351 double val = at(0,0,0)
01352 + 0.5 * (Dx * b[0] + Dy * b[1] + Ds * b[2]) ;
01353 double score = (Dxx+Dyy)*(Dxx+Dyy) / (Dxx*Dyy - Dxy*Dxy) ;
01354 double xn = x + b[0] ;
01355 double yn = y + b[1] ;
01356 double sn = s + b[2] ;
01357
01358 vl_bool good =
01359 vl_abs_d (val) > tp &&
01360 score < (te+1)*(te+1)/te &&
01361 score >= 0 &&
01362 vl_abs_d (b[0]) < 1.5 &&
01363 vl_abs_d (b[1]) < 1.5 &&
01364 vl_abs_d (b[2]) < 1.5 &&
01365 xn >= 0 &&
01366 xn <= w - 1 &&
01367 yn >= 0 &&
01368 yn <= h - 1 &&
01369 sn >= s_min &&
01370 sn <= s_max ;
01371
01372 if (good) {
01373 k-> o = f->o_cur ;
01374 k-> ix = x ;
01375 k-> iy = y ;
01376 k-> is = s ;
01377 k-> s = sn ;
01378 k-> x = xn * xper ;
01379 k-> y = yn * xper ;
01380 k-> sigma = f->sigma0 * pow (2.0, sn/f->S) * xper ;
01381 ++ k ;
01382 }
01383
01384 }
01385 }
01386
01387
01388 f-> nkeys = k - f->keys ;
01389 }
01390
01391
01404 static void
01405 update_gradient (VlSiftFilt *f)
01406 {
01407 int s_min = f->s_min ;
01408 int s_max = f->s_max ;
01409 int w = vl_sift_get_octave_width (f) ;
01410 int h = vl_sift_get_octave_height (f) ;
01411 int const xo = 1 ;
01412 int const yo = w ;
01413 int const so = h * w ;
01414 int y, s ;
01415
01416 if (f->grad_o == f->o_cur) return ;
01417
01418 for (s = s_min + 1 ;
01419 s <= s_max - 2 ; ++ s) {
01420
01421 vl_sift_pix *src, *end, *grad, gx, gy ;
01422
01423 #define SAVE_BACK \
01424 *grad++ = vl_fast_sqrt_f (gx*gx + gy*gy) ; \
01425 *grad++ = vl_mod_2pi_f (vl_fast_atan2_f (gy, gx) + 2*VL_PI) ; \
01426 ++src ; \
01427
01428 src = vl_sift_get_octave (f,s) ;
01429 grad = f->grad + 2 * so * (s - s_min -1) ;
01430
01431
01432 gx = src[+xo] - src[0] ;
01433 gy = src[+yo] - src[0] ;
01434 SAVE_BACK ;
01435
01436
01437 end = (src - 1) + w - 1 ;
01438 while (src < end) {
01439 gx = 0.5 * (src[+xo] - src[-xo]) ;
01440 gy = src[+yo] - src[0] ;
01441 SAVE_BACK ;
01442 }
01443
01444
01445 gx = src[0] - src[-xo] ;
01446 gy = src[+yo] - src[0] ;
01447 SAVE_BACK ;
01448
01449 for (y = 1 ; y < h -1 ; ++y) {
01450
01451
01452 gx = src[+xo] - src[0] ;
01453 gy = 0.5 * (src[+yo] - src[-yo]) ;
01454 SAVE_BACK ;
01455
01456
01457 end = (src - 1) + w - 1 ;
01458 while (src < end) {
01459 gx = 0.5 * (src[+xo] - src[-xo]) ;
01460 gy = 0.5 * (src[+yo] - src[-yo]) ;
01461 SAVE_BACK ;
01462 }
01463
01464
01465 gx = src[0] - src[-xo] ;
01466 gy = 0.5 * (src[+yo] - src[-yo]) ;
01467 SAVE_BACK ;
01468 }
01469
01470
01471 gx = src[+xo] - src[0] ;
01472 gy = src[ 0] - src[-yo] ;
01473 SAVE_BACK ;
01474
01475
01476 end = (src - 1) + w - 1 ;
01477 while (src < end) {
01478 gx = 0.5 * (src[+xo] - src[-xo]) ;
01479 gy = src[0] - src[-yo] ;
01480 SAVE_BACK ;
01481 }
01482
01483
01484 gx = src[0] - src[-xo] ;
01485 gy = src[0] - src[-yo] ;
01486 SAVE_BACK ;
01487 }
01488 f->grad_o = f->o_cur ;
01489 }
01490
01515 VL_EXPORT
01516 int
01517 vl_sift_calc_keypoint_orientations (VlSiftFilt *f,
01518 double angles [4],
01519 VlSiftKeypoint const *k)
01520 {
01521 double const winf = 1.5 ;
01522 double xper = pow (2.0, f->o_cur) ;
01523
01524 int w = f-> octave_width ;
01525 int h = f-> octave_height ;
01526 int const xo = 2 ;
01527 int const yo = 2 * w ;
01528 int const so = 2 * w * h ;
01529 double x = k-> x / xper ;
01530 double y = k-> y / xper ;
01531 double sigma = k-> sigma / xper ;
01532
01533 int xi = (int) (x + 0.5) ;
01534 int yi = (int) (y + 0.5) ;
01535 int si = k-> is ;
01536
01537 double const sigmaw = winf * sigma ;
01538 int W = VL_MAX(floor (3.0 * sigmaw), 1) ;
01539
01540 int nangles= 0 ;
01541
01542 enum {nbins = 36} ;
01543
01544 double hist [nbins], maxh ;
01545 vl_sift_pix const * pt ;
01546 int xs, ys, iter, i ;
01547
01548
01549 if(k->o != f->o_cur)
01550 return 0 ;
01551
01552
01553 if(xi < 0 ||
01554 xi > w - 1 ||
01555 yi < 0 ||
01556 yi > h - 1 ||
01557 si < f->s_min + 1 ||
01558 si > f->s_max - 2 ) {
01559 return 0 ;
01560 }
01561
01562
01563 update_gradient (f) ;
01564
01565
01566 memset (hist, 0, sizeof(double) * nbins) ;
01567
01568
01569 pt = f-> grad + xo*xi + yo*yi + so*(si - f->s_min - 1) ;
01570
01571 #undef at
01572 #define at(dx,dy) (*(pt + xo * (dx) + yo * (dy)))
01573
01574 for(ys = VL_MAX (- W, - yi) ;
01575 ys <= VL_MIN (+ W, h - 1 - yi) ; ++ys) {
01576
01577 for(xs = VL_MAX (- W, - xi) ;
01578 xs <= VL_MIN (+ W, w - 1 - xi) ; ++xs) {
01579
01580
01581 double dx = (double)(xi + xs) - x;
01582 double dy = (double)(yi + ys) - y;
01583 double r2 = dx*dx + dy*dy ;
01584 double wgt, mod, ang, fbin ;
01585
01586
01587 if (r2 >= W*W + 0.6) continue ;
01588
01589 wgt = fast_expn (r2 / (2*sigmaw*sigmaw)) ;
01590 mod = *(pt + xs*xo + ys*yo ) ;
01591 ang = *(pt + xs*xo + ys*yo + 1) ;
01592 fbin = nbins * ang / (2 * VL_PI) ;
01593
01594 #if defined(VL_SIFT_BILINEAR_ORIENTATIONS)
01595 {
01596 int bin = vl_floor_d (fbin - 0.5) ;
01597 double rbin = fbin - bin - 0.5 ;
01598 hist [(bin + nbins) % nbins] += (1 - rbin) * mod * wgt ;
01599 hist [(bin + 1 ) % nbins] += ( rbin) * mod * wgt ;
01600 }
01601 #else
01602 {
01603 int bin = vl_floor_d (fbin) ;
01604 bin = vl_floor_d (nbins * ang / (2*VL_PI)) ;
01605 hist [(bin) % nbins] += mod * wgt ;
01606 }
01607 #endif
01608
01609 }
01610 }
01611
01612
01613 for (iter = 0; iter < 6; iter ++) {
01614 double prev = hist [nbins - 1] ;
01615 double first = hist [0] ;
01616 int i ;
01617 for (i = 0; i < nbins - 1; i++) {
01618 double newh = (prev + hist[i] + hist[(i+1) % nbins]) / 3.0;
01619 prev = hist[i] ;
01620 hist[i] = newh ;
01621 }
01622 hist[i] = (prev + hist[i] + first) / 3.0 ;
01623 }
01624
01625
01626 maxh = 0 ;
01627 for (i = 0 ; i < nbins ; ++i)
01628 maxh = VL_MAX (maxh, hist [i]) ;
01629
01630
01631 nangles = 0 ;
01632 for(i = 0 ; i < nbins ; ++i) {
01633 double h0 = hist [i] ;
01634 double hm = hist [(i - 1 + nbins) % nbins] ;
01635 double hp = hist [(i + 1 + nbins) % nbins] ;
01636
01637
01638 if (h0 > 0.8*maxh && h0 > hm && h0 > hp) {
01639
01640
01641 double di = - 0.5 * (hp - hm) / (hp + hm - 2 * h0) ;
01642 double th = 2 * VL_PI * (i + di + 0.5) / nbins ;
01643 angles [ nangles++ ] = th ;
01644 if( nangles == 4 )
01645 goto enough_angles ;
01646 }
01647 }
01648 enough_angles:
01649 return nangles ;
01650 }
01651
01652
01660 VL_INLINE vl_sift_pix
01661 normalize_histogram
01662 (vl_sift_pix *begin, vl_sift_pix *end)
01663 {
01664 vl_sift_pix* iter ;
01665 vl_sift_pix norm = 0.0 ;
01666
01667 for (iter = begin ; iter != end ; ++ iter)
01668 norm += (*iter) * (*iter) ;
01669
01670 norm = vl_fast_sqrt_f (norm) + VL_EPSILON_F ;
01671
01672 for (iter = begin; iter != end ; ++ iter)
01673 *iter /= norm ;
01674
01675 return norm;
01676 }
01677
01710 VL_EXPORT
01711 void
01712 vl_sift_calc_raw_descriptor (VlSiftFilt const *f,
01713 vl_sift_pix const* grad,
01714 vl_sift_pix *descr,
01715 int width, int height,
01716 double x, double y,
01717 double sigma,
01718 double angle0)
01719 {
01720 double const magnif = f-> magnif ;
01721
01722 int w = width ;
01723 int h = height ;
01724 int const xo = 2 ;
01725 int const yo = 2 * w ;
01726
01727 int xi = (int) (x + 0.5) ;
01728 int yi = (int) (y + 0.5) ;
01729
01730 double const st0 = sin (angle0) ;
01731 double const ct0 = cos (angle0) ;
01732 double const SBP = magnif * sigma + VL_EPSILON_D ;
01733 int const W = floor
01734 (sqrt(2.0) * SBP * (NBP + 1) / 2.0 + 0.5) ;
01735
01736 int const binto = 1 ;
01737 int const binyo = NBO * NBP ;
01738 int const binxo = NBO ;
01739
01740 int bin, dxi, dyi ;
01741 vl_sift_pix const *pt ;
01742 vl_sift_pix *dpt ;
01743
01744
01745 if(xi < 0 ||
01746 xi >= w ||
01747 yi < 0 ||
01748 yi >= h - 1 )
01749 return ;
01750
01751
01752 memset (descr, 0, sizeof(vl_sift_pix) * NBO*NBP*NBP) ;
01753
01754
01755
01756
01757 pt = grad + xi*xo + yi*yo ;
01758 dpt = descr + (NBP/2) * binyo + (NBP/2) * binxo ;
01759
01760 #undef atd
01761 #define atd(dbinx,dbiny,dbint) *(dpt + (dbint)*binto + (dbiny)*binyo + (dbinx)*binxo)
01762
01763
01764
01765
01766
01767 for(dyi = VL_MAX(- W, - yi ) ;
01768 dyi <= VL_MIN(+ W, h - yi -1) ; ++ dyi) {
01769
01770 for(dxi = VL_MAX(- W, - xi ) ;
01771 dxi <= VL_MIN(+ W, w - xi -1) ; ++ dxi) {
01772
01773
01774 vl_sift_pix mod = *( pt + dxi*xo + dyi*yo + 0 ) ;
01775 vl_sift_pix angle = *( pt + dxi*xo + dyi*yo + 1 ) ;
01776 vl_sift_pix theta = vl_mod_2pi_f (angle - angle0) ;
01777
01778
01779 vl_sift_pix dx = xi + dxi - x;
01780 vl_sift_pix dy = yi + dyi - y;
01781
01782
01783
01784 vl_sift_pix nx = ( ct0 * dx + st0 * dy) / SBP ;
01785 vl_sift_pix ny = (-st0 * dx + ct0 * dy) / SBP ;
01786 vl_sift_pix nt = NBO * theta / (2 * VL_PI) ;
01787
01788
01789
01790
01791
01792 vl_sift_pix const wsigma = f->windowSize ;
01793 vl_sift_pix win = fast_expn
01794 ((nx*nx + ny*ny)/(2.0 * wsigma * wsigma)) ;
01795
01796
01797
01798 int binx = vl_floor_f (nx - 0.5) ;
01799 int biny = vl_floor_f (ny - 0.5) ;
01800 int bint = vl_floor_f (nt) ;
01801 vl_sift_pix rbinx = nx - (binx + 0.5) ;
01802 vl_sift_pix rbiny = ny - (biny + 0.5) ;
01803 vl_sift_pix rbint = nt - bint ;
01804 int dbinx ;
01805 int dbiny ;
01806 int dbint ;
01807
01808
01809 for(dbinx = 0 ; dbinx < 2 ; ++dbinx) {
01810 for(dbiny = 0 ; dbiny < 2 ; ++dbiny) {
01811 for(dbint = 0 ; dbint < 2 ; ++dbint) {
01812
01813 if (binx + dbinx >= - (NBP/2) &&
01814 binx + dbinx < (NBP/2) &&
01815 biny + dbiny >= - (NBP/2) &&
01816 biny + dbiny < (NBP/2) ) {
01817 vl_sift_pix weight = win
01818 * mod
01819 * vl_abs_f (1 - dbinx - rbinx)
01820 * vl_abs_f (1 - dbiny - rbiny)
01821 * vl_abs_f (1 - dbint - rbint) ;
01822
01823 atd(binx+dbinx, biny+dbiny, (bint+dbint) % NBO) += weight ;
01824 }
01825 }
01826 }
01827 }
01828 }
01829 }
01830
01831
01832 if(1) {
01833
01834
01835 vl_sift_pix norm = normalize_histogram (descr, descr + NBO*NBP*NBP) ;
01836
01837
01838
01839
01840
01841
01842
01843 int numSamples =
01844 (VL_MIN(W, w - xi -1) - VL_MAX(-W, - xi) + 1) *
01845 (VL_MIN(W, h - yi -1) - VL_MAX(-W, - yi) + 1) ;
01846
01847 if(f-> norm_thresh && norm < f-> norm_thresh * numSamples) {
01848 for(bin = 0; bin < NBO*NBP*NBP ; ++ bin)
01849 descr [bin] = 0;
01850 }
01851 else {
01852
01853 for(bin = 0; bin < NBO*NBP*NBP ; ++ bin) {
01854 if (descr [bin] > 0.2) descr [bin] = 0.2;
01855 }
01856
01857
01858 normalize_histogram (descr, descr + NBO*NBP*NBP) ;
01859 }
01860 }
01861 }
01862
01879 VL_EXPORT
01880 void
01881 vl_sift_calc_keypoint_descriptor (VlSiftFilt *f,
01882 vl_sift_pix *descr,
01883 VlSiftKeypoint const* k,
01884 double angle0)
01885 {
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902 double const magnif = f-> magnif ;
01903
01904 double xper = pow (2.0, f->o_cur) ;
01905
01906 int w = f-> octave_width ;
01907 int h = f-> octave_height ;
01908 int const xo = 2 ;
01909 int const yo = 2 * w ;
01910 int const so = 2 * w * h ;
01911 double x = k-> x / xper ;
01912 double y = k-> y / xper ;
01913 double sigma = k-> sigma / xper ;
01914
01915 int xi = (int) (x + 0.5) ;
01916 int yi = (int) (y + 0.5) ;
01917 int si = k-> is ;
01918
01919 double const st0 = sin (angle0) ;
01920 double const ct0 = cos (angle0) ;
01921 double const SBP = magnif * sigma ;
01922 int const W = floor
01923 (sqrt(2.0) * SBP * (NBP + 1) / 2.0 + 0.5) ;
01924
01925 int const binto = 1 ;
01926 int const binyo = NBO * NBP ;
01927 int const binxo = NBO ;
01928
01929 int bin, dxi, dyi ;
01930 vl_sift_pix const *pt ;
01931 vl_sift_pix *dpt ;
01932
01933
01934 if(k->o != f->o_cur ||
01935 xi < 0 ||
01936 xi >= w ||
01937 yi < 0 ||
01938 yi >= h - 1 ||
01939 si < f->s_min + 1 ||
01940 si > f->s_max - 2 )
01941 return ;
01942
01943
01944 update_gradient (f) ;
01945
01946
01947
01948
01949 memset (descr, 0, sizeof(vl_sift_pix) * NBO*NBP*NBP) ;
01950
01951
01952
01953
01954 pt = f->grad + xi*xo + yi*yo + (si - f->s_min - 1)*so ;
01955 dpt = descr + (NBP/2) * binyo + (NBP/2) * binxo ;
01956
01957 #undef atd
01958 #define atd(dbinx,dbiny,dbint) *(dpt + (dbint)*binto + (dbiny)*binyo + (dbinx)*binxo)
01959
01960
01961
01962
01963
01964 for(dyi = VL_MAX (- W, 1 - yi ) ;
01965 dyi <= VL_MIN (+ W, h - yi - 2) ; ++ dyi) {
01966
01967 for(dxi = VL_MAX (- W, 1 - xi ) ;
01968 dxi <= VL_MIN (+ W, w - xi - 2) ; ++ dxi) {
01969
01970
01971 vl_sift_pix mod = *( pt + dxi*xo + dyi*yo + 0 ) ;
01972 vl_sift_pix angle = *( pt + dxi*xo + dyi*yo + 1 ) ;
01973 vl_sift_pix theta = vl_mod_2pi_f (angle - angle0) ;
01974
01975
01976 vl_sift_pix dx = xi + dxi - x;
01977 vl_sift_pix dy = yi + dyi - y;
01978
01979
01980
01981 vl_sift_pix nx = ( ct0 * dx + st0 * dy) / SBP ;
01982 vl_sift_pix ny = (-st0 * dx + ct0 * dy) / SBP ;
01983 vl_sift_pix nt = NBO * theta / (2 * VL_PI) ;
01984
01985
01986
01987
01988
01989 vl_sift_pix const wsigma = f->windowSize ;
01990 vl_sift_pix win = fast_expn
01991 ((nx*nx + ny*ny)/(2.0 * wsigma * wsigma)) ;
01992
01993
01994
01995 int binx = vl_floor_f (nx - 0.5) ;
01996 int biny = vl_floor_f (ny - 0.5) ;
01997 int bint = vl_floor_f (nt) ;
01998 vl_sift_pix rbinx = nx - (binx + 0.5) ;
01999 vl_sift_pix rbiny = ny - (biny + 0.5) ;
02000 vl_sift_pix rbint = nt - bint ;
02001 int dbinx ;
02002 int dbiny ;
02003 int dbint ;
02004
02005
02006 for(dbinx = 0 ; dbinx < 2 ; ++dbinx) {
02007 for(dbiny = 0 ; dbiny < 2 ; ++dbiny) {
02008 for(dbint = 0 ; dbint < 2 ; ++dbint) {
02009
02010 if (binx + dbinx >= - (NBP/2) &&
02011 binx + dbinx < (NBP/2) &&
02012 biny + dbiny >= - (NBP/2) &&
02013 biny + dbiny < (NBP/2) ) {
02014 vl_sift_pix weight = win
02015 * mod
02016 * vl_abs_f (1 - dbinx - rbinx)
02017 * vl_abs_f (1 - dbiny - rbiny)
02018 * vl_abs_f (1 - dbint - rbint) ;
02019
02020 atd(binx+dbinx, biny+dbiny, (bint+dbint) % NBO) += weight ;
02021 }
02022 }
02023 }
02024 }
02025 }
02026 }
02027
02028
02029 if(1) {
02030
02031
02032 vl_sift_pix norm = normalize_histogram (descr, descr + NBO*NBP*NBP) ;
02033
02034
02035 if(f-> norm_thresh && norm < f-> norm_thresh) {
02036 for(bin = 0; bin < NBO*NBP*NBP ; ++ bin)
02037 descr [bin] = 0;
02038 }
02039 else {
02040
02041
02042 for(bin = 0; bin < NBO*NBP*NBP ; ++ bin) {
02043 if (descr [bin] > 0.2) descr [bin] = 0.2;
02044 }
02045
02046
02047 normalize_histogram (descr, descr + NBO*NBP*NBP) ;
02048 }
02049 }
02050
02051 }
02052
02066 VL_EXPORT
02067 void
02068 vl_sift_keypoint_init (VlSiftFilt const *f,
02069 VlSiftKeypoint *k,
02070 double x,
02071 double y,
02072 double sigma)
02073 {
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132 int o, ix, iy, is ;
02133 double s, phi, xper ;
02134
02135 phi = log2 (sigma / f->sigma0) ;
02136 o = vl_floor_d (phi - ((double) f->s_min + 0.5) / f->S) ;
02137 o = VL_MIN (o, f->o_min + f->O - 1) ;
02138 o = VL_MAX (o, f->o_min ) ;
02139 s = f->S * (phi - o) ;
02140
02141 is = (int)(s + 0.5) ;
02142 is = VL_MIN(is, f->s_max - 2) ;
02143 is = VL_MAX(is, f->s_min + 1) ;
02144
02145 xper = pow (2.0, o) ;
02146 ix = (int)(x / xper + 0.5) ;
02147 iy = (int)(y / xper + 0.5) ;
02148
02149 k -> o = o ;
02150
02151 k -> ix = ix ;
02152 k -> iy = iy ;
02153 k -> is = is ;
02154
02155 k -> x = x ;
02156 k -> y = y ;
02157 k -> s = s ;
02158
02159 k->sigma = sigma ;
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171 }