diff options
author | leochanj105 <leochanj@live.unc.edu> | 2020-10-19 23:09:30 -0400 |
---|---|---|
committer | leochanj105 <leochanj@live.unc.edu> | 2020-10-20 02:40:39 -0400 |
commit | f618466c25d43f3bae9e40920273bf77de1e1149 (patch) | |
tree | 460e739e2165b8a9c37a9c7ab1b60f5874903543 /SD-VBS/benchmarks/sift/src/matlab/siftdescriptor.c | |
parent | 47ced4e96bbb782b9e780e8f2cfc637b2c21ff44 (diff) |
initial sd-vbs
initial sd-vbs
add sd-vbs
sd-vbs
Diffstat (limited to 'SD-VBS/benchmarks/sift/src/matlab/siftdescriptor.c')
-rw-r--r-- | SD-VBS/benchmarks/sift/src/matlab/siftdescriptor.c | 524 |
1 files changed, 524 insertions, 0 deletions
diff --git a/SD-VBS/benchmarks/sift/src/matlab/siftdescriptor.c b/SD-VBS/benchmarks/sift/src/matlab/siftdescriptor.c new file mode 100644 index 0000000..63f4830 --- /dev/null +++ b/SD-VBS/benchmarks/sift/src/matlab/siftdescriptor.c | |||
@@ -0,0 +1,524 @@ | |||
1 | /* file: siftdescriptor | ||
2 | ** author: Andrea Vedaldi | ||
3 | ** description: Compute SIFT descriptors | ||
4 | **/ | ||
5 | |||
6 | /* AUTORIGHTS | ||
7 | Copyright (c) 2006 The Regents of the University of California. | ||
8 | All Rights Reserved. | ||
9 | |||
10 | Created by Andrea Vedaldi | ||
11 | UCLA Vision Lab - Department of Computer Science | ||
12 | |||
13 | Permission to use, copy, modify, and distribute this software and its | ||
14 | documentation for educational, research and non-profit purposes, | ||
15 | without fee, and without a written agreement is hereby granted, | ||
16 | provided that the above copyright notice, this paragraph and the | ||
17 | following three paragraphs appear in all copies. | ||
18 | |||
19 | This software program and documentation are copyrighted by The Regents | ||
20 | of the University of California. The software program and | ||
21 | documentation are supplied "as is", without any accompanying services | ||
22 | from The Regents. The Regents does not warrant that the operation of | ||
23 | the program will be uninterrupted or error-free. The end-user | ||
24 | understands that the program was developed for research purposes and | ||
25 | is advised not to rely exclusively on the program for any reason. | ||
26 | |||
27 | This software embodies a method for which the following patent has | ||
28 | been issued: "Method and apparatus for identifying scale invariant | ||
29 | features in an image and use of same for locating an object in an | ||
30 | image," David G. Lowe, US Patent 6,711,293 (March 23, | ||
31 | 2004). Provisional application filed March 8, 1999. Asignee: The | ||
32 | University of British Columbia. | ||
33 | |||
34 | IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY | ||
35 | FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, | ||
36 | INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND | ||
37 | ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN | ||
38 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF | ||
39 | CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT | ||
40 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
41 | A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" | ||
42 | BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE | ||
43 | MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | ||
44 | */ | ||
45 | |||
46 | /* | ||
47 | REMARKS. The use of strcasecmp makes the function POSIX but not ANSI | ||
48 | compliant. When compling with Altivec, GCC Altivec extensions are | ||
49 | supported. | ||
50 | */ | ||
51 | |||
52 | #define LOWE_COMPATIBLE | ||
53 | |||
54 | #include"mexutils.c" | ||
55 | #include<stdlib.h> | ||
56 | #include<math.h> | ||
57 | |||
58 | #ifdef WINDOWS | ||
59 | #include<string.h> | ||
60 | #ifndef __cplusplus | ||
61 | #define sqrtf(x) ((float)sqrt((double)(x))) | ||
62 | #define powf(x,y) ((float)pow((double)(x),(double)(y))) | ||
63 | #define fabsf(x) ((float)fabs((double)(x))) | ||
64 | #define sinf(x) ((float)sin((double)(x))) | ||
65 | #define cosf(x) ((float)cos((double)(x))) | ||
66 | #define expf(x) ((float)exp((double)(x))) | ||
67 | #define atan2f(x,y) ((float)atan2((double)(x),(double)(y))) | ||
68 | #endif | ||
69 | #else | ||
70 | #include<strings.h> | ||
71 | #endif | ||
72 | |||
73 | /* Altivec and Accelerate support. | ||
74 | * Very crude at this time. | ||
75 | */ | ||
76 | #if defined( MACOSX ) && defined( __ALTIVEC__ ) | ||
77 | #include<Accelerate/Accelerate.h> | ||
78 | typedef union | ||
79 | { | ||
80 | float x[4] ; | ||
81 | vFloat vec ; | ||
82 | } float4 ; | ||
83 | #endif | ||
84 | |||
85 | #define greater(a,b) a > b | ||
86 | #define min(a,b) (((a)<(b))?(a):(b)) | ||
87 | #define max(a,b) (((a)>(b))?(a):(b)) | ||
88 | |||
89 | |||
90 | enum {SCALESPACE, NOSCALESPACE} ; | ||
91 | |||
92 | enum {PROP_MAGNIF=0, | ||
93 | PROP_NBP, | ||
94 | PROP_NBO, | ||
95 | PROP_UNKNOWN} ; | ||
96 | |||
97 | char const * properties [4] = | ||
98 | { "Magnif", | ||
99 | "NumSpatialBins", | ||
100 | "NumOrientBins", | ||
101 | 0L | ||
102 | } ; | ||
103 | |||
104 | /** Fast fmodf for 2*PI | ||
105 | **/ | ||
106 | /*inline*/ | ||
107 | float fast_mod(float th) | ||
108 | { | ||
109 | while(th < 0) th += 2*M_PI ; | ||
110 | while(th > 2*M_PI) th -= 2*M_PI ; | ||
111 | return th ; | ||
112 | } | ||
113 | |||
114 | /** Fast floor. Equivalent to (int) floor(x) | ||
115 | **/ | ||
116 | /*inline*/ | ||
117 | int fast_floor(float x) | ||
118 | { | ||
119 | return (int)( x - ((x>=0)?0:1) ) ; | ||
120 | } | ||
121 | |||
122 | /** Normalizes in norm L_2 a descriptor. | ||
123 | **/ | ||
124 | void | ||
125 | normalize_histogram(float* L_begin, float* L_end) | ||
126 | { | ||
127 | float* L_iter ; | ||
128 | float norm=0.0 ; | ||
129 | |||
130 | for(L_iter = L_begin; L_iter != L_end ; ++L_iter) | ||
131 | norm += (*L_iter) * (*L_iter) ; | ||
132 | |||
133 | norm = sqrtf(norm) ; | ||
134 | /* mexPrintf("%f\n",norm) ;*/ | ||
135 | |||
136 | for(L_iter = L_begin; L_iter != L_end ; ++L_iter) | ||
137 | *L_iter /= norm ; | ||
138 | } | ||
139 | |||
140 | /** @brief MATLAB Driver. | ||
141 | **/ | ||
142 | void | ||
143 | mexFunction(int nout, mxArray *out[], | ||
144 | int nin, const mxArray *in[]) | ||
145 | { | ||
146 | int M,N,S=0,smin=0,K,num_levels=0 ; | ||
147 | const int* dimensions ; | ||
148 | const double* P_pt ; | ||
149 | const double* G_pt ; | ||
150 | float* descr_pt ; | ||
151 | float* buffer_pt ; | ||
152 | float sigma0 ; | ||
153 | float magnif = 3.0f ; /* Spatial bin extension factor. */ | ||
154 | int NBP = 4 ; /* Number of bins for one spatial direction (even). */ | ||
155 | int NBO = 8 ; /* Number of bins for the ortientation. */ | ||
156 | int mode = NOSCALESPACE ; | ||
157 | int buffer_size=0; | ||
158 | |||
159 | enum {IN_G=0,IN_P,IN_SIGMA0,IN_S,IN_SMIN} ; | ||
160 | enum {OUT_L=0} ; | ||
161 | |||
162 | /* ------------------------------------------------------------------ | ||
163 | ** Check the arguments | ||
164 | ** --------------------------------------------------------------- */ | ||
165 | |||
166 | if (nin < 3) { | ||
167 | mexErrMsgTxt("At least three arguments are required") ; | ||
168 | } else if (nout > 1) { | ||
169 | mexErrMsgTxt("Too many output arguments."); | ||
170 | } | ||
171 | |||
172 | if( !uIsRealScalar(in[IN_SIGMA0]) ) { | ||
173 | mexErrMsgTxt("SIGMA0 should be a real scalar") ; | ||
174 | } | ||
175 | |||
176 | if(!mxIsDouble(in[IN_G]) || | ||
177 | mxGetNumberOfDimensions(in[IN_G]) > 3) { | ||
178 | mexErrMsgTxt("G should be a real matrix or 3-D array") ; | ||
179 | } | ||
180 | |||
181 | sigma0 = (float) *mxGetPr(in[IN_SIGMA0]) ; | ||
182 | |||
183 | dimensions = mxGetDimensions(in[IN_G]) ; | ||
184 | M = dimensions[0] ; | ||
185 | N = dimensions[1] ; | ||
186 | G_pt = mxGetPr(in[IN_G]) ; | ||
187 | |||
188 | P_pt = mxGetPr(in[IN_P]) ; | ||
189 | K = mxGetN(in[IN_P]) ; | ||
190 | |||
191 | if( !uIsRealMatrix(in[IN_P],-1,-1)) { | ||
192 | mexErrMsgTxt("P should be a real matrix") ; | ||
193 | } | ||
194 | |||
195 | if ( mxGetM(in[IN_P]) == 4) { | ||
196 | /* Standard (scale space) mode */ | ||
197 | mode = SCALESPACE ; | ||
198 | num_levels = dimensions[2] ; | ||
199 | |||
200 | if(nin < 5) { | ||
201 | mexErrMsgTxt("Five arguments are required in standard mode") ; | ||
202 | } | ||
203 | |||
204 | if( !uIsRealScalar(in[IN_S]) ) { | ||
205 | mexErrMsgTxt("S should be a real scalar") ; | ||
206 | } | ||
207 | |||
208 | if( !uIsRealScalar(in[IN_SMIN]) ) { | ||
209 | mexErrMsgTxt("SMIN should be a real scalar") ; | ||
210 | } | ||
211 | |||
212 | if( !uIsRealMatrix(in[IN_P],4,-1)) { | ||
213 | mexErrMsgTxt("When the e mode P should be a 4xK matrix.") ; | ||
214 | } | ||
215 | |||
216 | S = (int)(*mxGetPr(in[IN_S])) ; | ||
217 | smin = (int)(*mxGetPr(in[IN_SMIN])) ; | ||
218 | |||
219 | } else if ( mxGetM(in[IN_P]) == 3 ) { | ||
220 | mode = NOSCALESPACE ; | ||
221 | num_levels = 1 ; | ||
222 | S = 1 ; | ||
223 | smin = 0 ; | ||
224 | } else { | ||
225 | mexErrMsgTxt("P should be either a 3xK or a 4xK matrix.") ; | ||
226 | } | ||
227 | |||
228 | /* Parse the property-value pairs */ | ||
229 | { | ||
230 | char str [80] ; | ||
231 | int arg = (mode == SCALESPACE) ? IN_SMIN + 1 : IN_SIGMA0 + 1 ; | ||
232 | |||
233 | while(arg < nin) { | ||
234 | int k ; | ||
235 | |||
236 | if( !uIsString(in[arg],-1) ) { | ||
237 | mexErrMsgTxt("The first argument in a property-value pair" | ||
238 | " should be a string") ; | ||
239 | } | ||
240 | mxGetString(in[arg], str, 80) ; | ||
241 | |||
242 | #ifdef WINDOWS | ||
243 | for(k = 0 ; properties[k] && strcmpi(str, properties[k]) ; ++k) ; | ||
244 | #else | ||
245 | for(k = 0 ; properties[k] && strcasecmp(str, properties[k]) ; ++k) ; | ||
246 | #endif | ||
247 | |||
248 | switch (k) { | ||
249 | case PROP_NBP: | ||
250 | if( !uIsRealScalar(in[arg+1]) ) { | ||
251 | mexErrMsgTxt("'NumSpatialBins' should be real scalar") ; | ||
252 | } | ||
253 | NBP = (int) *mxGetPr(in[arg+1]) ; | ||
254 | if( NBP <= 0 || (NBP & 0x1) ) { | ||
255 | mexErrMsgTxt("'NumSpatialBins' must be positive and even") ; | ||
256 | } | ||
257 | break ; | ||
258 | |||
259 | case PROP_NBO: | ||
260 | if( !uIsRealScalar(in[arg+1]) ) { | ||
261 | mexErrMsgTxt("'NumOrientBins' should be a real scalar") ; | ||
262 | } | ||
263 | NBO = (int) *mxGetPr(in[arg+1]) ; | ||
264 | if( NBO <= 0 ) { | ||
265 | mexErrMsgTxt("'NumOrientlBins' must be positive") ; | ||
266 | } | ||
267 | break ; | ||
268 | |||
269 | case PROP_MAGNIF: | ||
270 | if( !uIsRealScalar(in[arg+1]) ) { | ||
271 | mexErrMsgTxt("'Magnif' should be a real scalar") ; | ||
272 | } | ||
273 | magnif = (float) *mxGetPr(in[arg+1]) ; | ||
274 | if( magnif <= 0 ) { | ||
275 | mexErrMsgTxt("'Magnif' must be positive") ; | ||
276 | } | ||
277 | break ; | ||
278 | |||
279 | case PROP_UNKNOWN: | ||
280 | mexErrMsgTxt("Property unknown.") ; | ||
281 | break ; | ||
282 | } | ||
283 | arg += 2 ; | ||
284 | } | ||
285 | } | ||
286 | |||
287 | /* ----------------------------------------------------------------- | ||
288 | * Pre-compute gradient and angles | ||
289 | * -------------------------------------------------------------- */ | ||
290 | /* Alloc two buffers and make sure their size is multiple of 128 for | ||
291 | * better alignment (used also by the Altivec code below.) | ||
292 | */ | ||
293 | buffer_size = (M*N*num_levels + 0x7f) & (~ 0x7f) ; | ||
294 | buffer_pt = (float*) mxMalloc( sizeof(float) * 2 * buffer_size ) ; | ||
295 | descr_pt = (float*) mxCalloc( NBP*NBP*NBO*K, sizeof(float) ) ; | ||
296 | |||
297 | { | ||
298 | /* Offsets to move in the scale space. */ | ||
299 | const int yo = 1 ; | ||
300 | const int xo = M ; | ||
301 | const int so = M*N ; | ||
302 | int x,y,s ; | ||
303 | |||
304 | #define at(x,y) (*(pt + (x)*xo + (y)*yo)) | ||
305 | |||
306 | /* Compute the gradient */ | ||
307 | for(s = 0 ; s < num_levels ; ++s) { | ||
308 | const double* pt = G_pt + s*so ; | ||
309 | for(x = 1 ; x < N-1 ; ++x) { | ||
310 | for(y = 1 ; y < M-1 ; ++y) { | ||
311 | float Dx = 0.5 * ( at(x+1,y) - at(x-1,y) ) ; | ||
312 | float Dy = 0.5 * ( at(x,y+1) - at(x,y-1) ) ; | ||
313 | buffer_pt[(x*xo+y*yo+s*so) + 0 ] = Dx ; | ||
314 | buffer_pt[(x*xo+y*yo+s*so) + buffer_size] = Dy ; | ||
315 | } | ||
316 | } | ||
317 | } | ||
318 | |||
319 | /* Compute angles and modules */ | ||
320 | { | ||
321 | float* pt = buffer_pt ; | ||
322 | int j = 0 ; | ||
323 | while (j < N*M*num_levels) { | ||
324 | |||
325 | #if defined( MACOSX ) && defined( __ALTIVEC__ ) | ||
326 | if( ((unsigned int)pt & 0x7) == 0 && j+3 < N*M*num_levels ) { | ||
327 | /* If aligned to 128 bit and there are at least 4 pixels left */ | ||
328 | float4 a, b, c, d ; | ||
329 | a.vec = vec_ld(0,(vector float*)(pt )) ; | ||
330 | b.vec = vec_ld(0,(vector float*)(pt + buffer_size)) ; | ||
331 | c.vec = vatan2f(b.vec,a.vec) ; | ||
332 | a.x[0] = a.x[0]*a.x[0]+b.x[0]*b.x[0] ; | ||
333 | a.x[1] = a.x[1]*a.x[1]+b.x[1]*b.x[1] ; | ||
334 | a.x[2] = a.x[2]*a.x[2]+b.x[2]*b.x[2] ; | ||
335 | a.x[3] = a.x[3]*a.x[3]+b.x[3]*b.x[3] ; | ||
336 | d.vec = vsqrtf(a.vec) ; | ||
337 | vec_st(c.vec,0,(vector float*)(pt + buffer_size)) ; | ||
338 | vec_st(d.vec,0,(vector float*)(pt )) ; | ||
339 | j += 4 ; | ||
340 | pt += 4 ; | ||
341 | } else { | ||
342 | #endif | ||
343 | float Dx = *(pt ) ; | ||
344 | float Dy = *(pt + buffer_size) ; | ||
345 | *(pt ) = sqrtf(Dx*Dx + Dy*Dy) ; | ||
346 | *(pt + buffer_size) = atan2f(Dy, Dx) ; | ||
347 | j += 1 ; | ||
348 | pt += 1 ; | ||
349 | #if defined( MACOSX ) && defined( __ALTIVEC__ ) | ||
350 | } | ||
351 | #endif | ||
352 | |||
353 | } | ||
354 | } | ||
355 | } | ||
356 | |||
357 | /* ----------------------------------------------------------------- | ||
358 | * Do the job | ||
359 | * -------------------------------------------------------------- */ | ||
360 | if(K > 0) { | ||
361 | int p ; | ||
362 | |||
363 | /* Offsets to move in the buffer */ | ||
364 | const int yo = 1 ; | ||
365 | const int xo = M ; | ||
366 | const int so = M*N ; | ||
367 | |||
368 | /* Offsets to move in the descriptor. */ | ||
369 | /* Use Lowe's convention. */ | ||
370 | const int binto = 1 ; | ||
371 | const int binyo = NBO * NBP ; | ||
372 | const int binxo = NBO ; | ||
373 | const int bino = NBO * NBP * NBP ; | ||
374 | |||
375 | for(p = 0 ; p < K ; ++p, descr_pt += bino) { | ||
376 | /* The SIFT descriptor is a three dimensional histogram of the position | ||
377 | * and orientation of the gradient. There are NBP bins for each spatial | ||
378 | * dimesions and NBO bins for the orientation dimesion, for a total of | ||
379 | * NBP x NBP x NBO bins. | ||
380 | * | ||
381 | * The support of each spatial bin has an extension of SBP = 3sigma | ||
382 | * pixels, where sigma is the scale of the keypoint. Thus all the bins | ||
383 | * together have a support SBP x NBP pixels wide . Since weighting and | ||
384 | * interpolation of pixel is used, another half bin is needed at both | ||
385 | * ends of the extension. Therefore, we need a square window of SBP x | ||
386 | * (NBP + 1) pixels. Finally, since the patch can be arbitrarly rotated, | ||
387 | * we need to consider a window 2W += sqrt(2) x SBP x (NBP + 1) pixels | ||
388 | * wide. | ||
389 | */ | ||
390 | const float x = (float) *P_pt++ ; | ||
391 | const float y = (float) *P_pt++ ; | ||
392 | const float s = (float) (mode == SCALESPACE) ? (*P_pt++) : 0.0 ; | ||
393 | const float theta0 = (float) *P_pt++ ; | ||
394 | |||
395 | const float st0 = sinf(theta0) ; | ||
396 | const float ct0 = cosf(theta0) ; | ||
397 | const int xi = (int) floor(x+0.5) ; /* Round-off */ | ||
398 | const int yi = (int) floor(y+0.5) ; | ||
399 | const int si = (int) floor(s+0.5) - smin ; | ||
400 | const float sigma = sigma0 * powf(2, s / S) ; | ||
401 | const float SBP = magnif * sigma ; | ||
402 | const int W = (int) floor( sqrt(2.0) * SBP * (NBP + 1) / 2.0 + 0.5) ; | ||
403 | int bin ; | ||
404 | int dxi ; | ||
405 | int dyi ; | ||
406 | const float* pt ; | ||
407 | float* dpt ; | ||
408 | |||
409 | /* Check that keypoints are within bounds . */ | ||
410 | |||
411 | if(xi < 0 || | ||
412 | xi > N-1 || | ||
413 | yi < 0 || | ||
414 | yi > M-1 || | ||
415 | ((mode==SCALESPACE) && | ||
416 | (si < 0 || | ||
417 | si > dimensions[2]-1) ) ) | ||
418 | continue ; | ||
419 | |||
420 | /* Center the scale space and the descriptor on the current keypoint. | ||
421 | * Note that dpt is pointing to the bin of center (SBP/2,SBP/2,0). | ||
422 | */ | ||
423 | pt = buffer_pt + xi*xo + yi*yo + si*so ; | ||
424 | dpt = descr_pt + (NBP/2) * binyo + (NBP/2) * binxo ; | ||
425 | |||
426 | #define atd(dbinx,dbiny,dbint) (*(dpt + (dbint)*binto + (dbiny)*binyo + (dbinx)*binxo)) | ||
427 | |||
428 | /* | ||
429 | * Process each pixel in the window and in the (1,1)-(M-1,N-1) | ||
430 | * rectangle. | ||
431 | */ | ||
432 | for(dxi = max(-W, 1-xi) ; dxi <= min(+W, N-2-xi) ; ++dxi) { | ||
433 | for(dyi = max(-W, 1-yi) ; dyi <= min(+W, M-2-yi) ; ++dyi) { | ||
434 | |||
435 | /* Compute the gradient. */ | ||
436 | float mod = *(pt + dxi*xo + dyi*yo + 0 ) ; | ||
437 | float angle = *(pt + dxi*xo + dyi*yo + buffer_size ) ; | ||
438 | #ifdef LOWE_COMPATIBLE | ||
439 | float theta = fast_mod(-angle + theta0) ; | ||
440 | #else | ||
441 | float theta = fast_mod(angle - theta0) ; | ||
442 | #endif | ||
443 | /* Get the fractional displacement. */ | ||
444 | float dx = ((float)(xi+dxi)) - x; | ||
445 | float dy = ((float)(yi+dyi)) - y; | ||
446 | |||
447 | /* Get the displacement normalized w.r.t. the keypoint orientation | ||
448 | * and extension. */ | ||
449 | float nx = ( ct0 * dx + st0 * dy) / SBP ; | ||
450 | float ny = (-st0 * dx + ct0 * dy) / SBP ; | ||
451 | float nt = NBO * theta / (2*M_PI) ; | ||
452 | |||
453 | /* Get the gaussian weight of the sample. The gaussian window | ||
454 | * has a standard deviation of NBP/2. Note that dx and dy are in | ||
455 | * the normalized frame, so that -NBP/2 <= dx <= NBP/2. */ | ||
456 | const float wsigma = NBP/2 ; | ||
457 | float win = expf(-(nx*nx + ny*ny)/(2.0 * wsigma * wsigma)) ; | ||
458 | |||
459 | /* The sample will be distributed in 8 adijacient bins. | ||
460 | * Now we get the ``lower-left'' bin. */ | ||
461 | int binx = fast_floor( nx - 0.5 ) ; | ||
462 | int biny = fast_floor( ny - 0.5 ) ; | ||
463 | int bint = fast_floor( nt ) ; | ||
464 | float rbinx = nx - (binx+0.5) ; | ||
465 | float rbiny = ny - (biny+0.5) ; | ||
466 | float rbint = nt - bint ; | ||
467 | int dbinx ; | ||
468 | int dbiny ; | ||
469 | int dbint ; | ||
470 | |||
471 | /* Distribute the current sample into the 8 adijacient bins. */ | ||
472 | for(dbinx = 0 ; dbinx < 2 ; ++dbinx) { | ||
473 | for(dbiny = 0 ; dbiny < 2 ; ++dbiny) { | ||
474 | for(dbint = 0 ; dbint < 2 ; ++dbint) { | ||
475 | |||
476 | if( binx+dbinx >= -(NBP/2) && | ||
477 | binx+dbinx < (NBP/2) && | ||
478 | biny+dbiny >= -(NBP/2) && | ||
479 | biny+dbiny < (NBP/2) ) { | ||
480 | float weight = win | ||
481 | * mod | ||
482 | * fabsf(1 - dbinx - rbinx) | ||
483 | * fabsf(1 - dbiny - rbiny) | ||
484 | * fabsf(1 - dbint - rbint) ; | ||
485 | |||
486 | atd(binx+dbinx, biny+dbiny, (bint+dbint) % NBO) += weight ; | ||
487 | } | ||
488 | } | ||
489 | } | ||
490 | } | ||
491 | } | ||
492 | } | ||
493 | |||
494 | { | ||
495 | /* Normalize the histogram to L2 unit length. */ | ||
496 | normalize_histogram(descr_pt, descr_pt + NBO*NBP*NBP) ; | ||
497 | |||
498 | /* Truncate at 0.2. */ | ||
499 | for(bin = 0; bin < NBO*NBP*NBP ; ++bin) { | ||
500 | if (descr_pt[bin] > 0.2) descr_pt[bin] = 0.2; | ||
501 | } | ||
502 | |||
503 | /* Normalize again. */ | ||
504 | normalize_histogram(descr_pt, descr_pt + NBO*NBP*NBP) ; | ||
505 | } | ||
506 | } | ||
507 | } | ||
508 | |||
509 | /* Restore pointer to the beginning of the descriptors. */ | ||
510 | descr_pt -= NBO*NBP*NBP*K ; | ||
511 | |||
512 | { | ||
513 | int k ; | ||
514 | double* L_pt ; | ||
515 | out[OUT_L] = mxCreateDoubleMatrix(NBP*NBP*NBO, K, mxREAL) ; | ||
516 | L_pt = mxGetPr(out[OUT_L]) ; | ||
517 | for(k = 0 ; k < NBP*NBP*NBO*K ; ++k) { | ||
518 | L_pt[k] = descr_pt[k] ; | ||
519 | } | ||
520 | } | ||
521 | |||
522 | mxFree(descr_pt) ; | ||
523 | mxFree(buffer_pt) ; | ||
524 | } | ||