00001
00007
00008
00009 #include "dhog.h"
00010 #include "pgm.h"
00011 #include "mathop.h"
00012 #include "imopv.h"
00013 #include <math.h>
00014 #include <string.h>
00015
00016 int const NBP = 4 ;
00017 int const NBO = 8 ;
00018
00019
00105 VL_INLINE float
00106 normalize_histogram
00107 (float *begin, float *end)
00108 {
00109 float* iter ;
00110 float norm = 0.0 ;
00111
00112 for (iter = begin ; iter != end ; ++ iter)
00113 norm += (*iter) * (*iter) ;
00114
00115 norm = vl_fast_sqrt_f (norm) + VL_EPSILON_F ;
00116
00117 for (iter = begin; iter != end ; ++ iter)
00118 *iter /= norm ;
00119
00120 return norm;
00121 }
00122
00133 VL_EXPORT
00134 VlDhogFilter*
00135 vl_dhog_new (int width, int height, int sampling_step, int bin_size)
00136 {
00137 int t ;
00138 VlDhogFilter* f = vl_malloc (sizeof(VlDhogFilter)) ;
00139
00140 f-> width = width ;
00141 f-> height = height ;
00142 f-> dwidth = (width - 1 - (NBP - 1)*bin_size) / sampling_step + 1;
00143 f-> dheight = (height - 1 - (NBP - 1)*bin_size) / sampling_step + 1;
00144 f-> nkeys = f->dwidth * f->dheight ;
00145 f-> sampling_step = sampling_step ;
00146 f-> bin_size = bin_size ;
00147
00148 f-> descr = vl_malloc (sizeof(float) * 128 * f->nkeys) ;
00149 f-> keys = vl_malloc (sizeof(VlDhogKeypoint) * f->nkeys) ;
00150 f-> tmp = vl_malloc (sizeof(float) * f->width * f->height) ;
00151 f-> tmp2 = vl_malloc (sizeof(float) * f->width * f->height) ;
00152 f-> hist = vl_malloc (sizeof(float*) * NBO) ;
00153 for (t = 0 ; t < NBO ; ++t) {
00154 f->hist [t] = vl_malloc (sizeof(float) * f->width * f->height) ;
00155 }
00156 return f ;
00157 }
00158
00164 VL_EXPORT
00165 void
00166 vl_dhog_delete (VlDhogFilter *f)
00167 {
00168 if (f) {
00169 int t ;
00170 if (f->hist) {
00171 for (t = 0 ; t < NBO ; ++t)
00172 if (f->hist[t]) vl_free (f->hist[t]) ;
00173 vl_free (f->hist) ;
00174 }
00175 if (f->tmp2) vl_free (f->tmp2) ;
00176 if (f->tmp) vl_free (f->tmp) ;
00177 if (f->descr) vl_free (f->keys) ;
00178 if (f->descr) vl_free (f->descr) ;
00179 vl_free(f) ;
00180 }
00181 }
00182
00190 float * _vl_dhog_new_kernel (VlDhogFilter *f, int i)
00191 {
00192 int filt_len = 2*f->bin_size - 1 ;
00193 float * ker = vl_malloc (sizeof(float) * filt_len) ;
00194 float delta = f->bin_size * (NBP / 2.0f - (i + 0.5)) ;
00195 float * kerit = ker ;
00196 float sigma = (NBP * f->bin_size) / 2.0f ;
00197 int k ;
00198
00199 for (k = - f->bin_size + 1 ;
00200 k <= + f->bin_size - 1 ;
00201 ++ k) {
00202 float z = (k - delta) / sigma ;
00203 *kerit++ = (1.0f - fabsf(k) / f->bin_size) *
00204 ((i >= 0) ? expf(-0.5f * z*z) : 1.0f) ;
00205 }
00206 return ker ;
00207 }
00208
00214 VL_INLINE
00215 void _vl_dhog_with_gaussian_window (VlDhogFilter* f)
00216 {
00217 int binx, biny, bint, centx, centy ;
00218 float *xker, *yker ;
00219 int W = f->bin_size - 1 ;
00220
00221 for (biny = 0 ; biny < NBP ; ++biny) {
00222 yker = _vl_dhog_new_kernel(f, biny) ;
00223
00224 for (binx = 0 ; binx < NBP ; ++binx) {
00225 xker = _vl_dhog_new_kernel(f, binx) ;
00226
00227 for (bint = 0 ; bint < NBO ; ++bint) {
00228 float *dst = f->descr + binx * NBO + biny * (NBP*NBO) + bint ;
00229 float *src = f->tmp ;
00230
00231 vl_imconvcol_vf (f->tmp2, f->height,
00232 f->hist [bint], f->width, f->height, f->width,
00233 yker, -W, +W, 1,
00234 VL_PAD_BY_CONTINUITY|VL_TRANSPOSE) ;
00235
00236 vl_imconvcol_vf (f->tmp, f->width,
00237 f->tmp2, f->height, f->width, f->height,
00238 xker, -W, +W, 1,
00239 VL_PAD_BY_CONTINUITY|VL_TRANSPOSE) ;
00240
00241 {
00242 int A = f->bin_size * (NBP - 1) ;
00243 int d = f->sampling_step ;
00244
00245 for (centy = 0 ;
00246 centy <= (f->height - 1 - A) / d ;
00247 ++ centy) {
00248 for (centx = 0 ;
00249 centx <= (f->width - 1 - A) / d ;
00250 ++ centx) {
00251 *dst = src [(centx + f->width*centy)*d +
00252 (binx + f->width*biny)*f->bin_size] ;
00253 dst += NBP*NBP*NBO ;
00254 }
00255 }
00256 }
00257 }
00258 vl_free (xker) ;
00259 }
00260 vl_free (yker) ;
00261 }
00262 }
00263
00269 VL_INLINE
00270 void _vl_dhog_with_flat_window (VlDhogFilter* f)
00271 {
00272 int binx, biny, bint, centx, centy ;
00273
00274 int W = f->bin_size - 1 ;
00275
00276 for (bint = 0 ; bint < NBO ; ++bint) {
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 vl_imconvcoltri_vf (f->tmp2, f->height,
00291 f->hist [bint], f->width, f->height, f->width,
00292 W, 1,
00293 VL_PAD_BY_CONTINUITY|VL_TRANSPOSE) ;
00294
00295 vl_imconvcoltri_vf (f->tmp, f->width,
00296 f->tmp2, f->height, f->width, f->height,
00297 W, 1,
00298 VL_PAD_BY_CONTINUITY|VL_TRANSPOSE) ;
00299
00300
00301 for (biny = 0 ; biny < NBP ; ++biny) {
00302 for (binx = 0 ; binx < NBP ; ++binx) {
00303
00304 float *dst = f->descr + binx * NBO + biny * (NBP*NBO) + bint ;
00305 float *src = f->tmp ;
00306 int A = f->bin_size * (NBP - 1) ;
00307 int d = f->sampling_step ;
00308
00309 for (centy = 0 ;
00310 centy <= (f->height - 1 - A) / d ;
00311 ++ centy) {
00312 for (centx = 0 ;
00313 centx <= (f->width - 1 - A) / d ;
00314 ++ centx) {
00315 *dst = src [(centx + f->width*centy)*d +
00316 (binx + f->width*biny)*f->bin_size] ;
00317 dst += NBP*NBP*NBO ;
00318 }
00319 }
00320 }
00321 }
00322 }
00323
00324 }
00325
00335 void vl_dhog_process (VlDhogFilter* f, float const* im, vl_bool fast)
00336 {
00337 int t, x, y ;
00338
00339
00340 for (t = 0 ; t < NBO ; ++t)
00341 memset (f->hist[t], 0, f->width*f->height*sizeof(float)) ;
00342
00343 #undef at
00344 #define at(u,v) (im[(v)*f->width+(u)])
00345
00346
00347 for (y = 0 ; y < f->height ; ++y) {
00348 for (x = 0 ; x < f->width ; ++x) {
00349 float gx, gy ;
00350 float angle, mod, nt, rbint ;
00351 int bint ;
00352
00353
00354 if (y == 0) {
00355 gy = at(x,y+1) - at(x,y) ;
00356 } else if (y == f->height-1) {
00357 gy = at(x,y) - at(x,y-1) ;
00358 } else {
00359 gy = 0.5f*(at(x,y+1) - at(x,y-1)) ;
00360 }
00361
00362
00363 if (x == 0) {
00364 gx = at(x+1,y) - at(x,y) ;
00365 } else if (x == f->width-1) {
00366 gx = at(x,y) - at(x-1,y) ;
00367 } else {
00368 gx = 0.5f*(at(x+1,y) - at(x-1,y)) ;
00369 }
00370
00371
00372 angle = vl_fast_atan2_f (gy,gx) ;
00373 mod = vl_fast_sqrt_f (gx*gx + gy*gy) ;
00374
00375
00376 nt = vl_mod_2pi_f (angle) * (NBO / (2*VL_PI)) ;
00377 bint = vl_floor_f (nt) ;
00378 rbint = nt - bint ;
00379
00380
00381 f->hist[bint%NBO] [x + y * f->width] += (1 - rbint) * mod ;
00382 f->hist[(bint+1)%NBO][x + y * f->width] += rbint * mod ;
00383 }
00384 }
00385
00386 if (fast) {
00387 _vl_dhog_with_flat_window(f) ;
00388 } else {
00389 _vl_dhog_with_gaussian_window(f) ;
00390 }
00391
00392 {
00393 VlDhogKeypoint* k = f->keys ;
00394 int centx, centy, bint ;
00395 int A = f->bin_size * (NBP - 1) ;
00396 double A_ = f->bin_size * (NBP - 1) / 2.0f ;
00397 int d = f->sampling_step ;
00398 float *dpt = f->descr ;
00399
00400 for (centy = 0 ;
00401 centy <= (f->height - 1 - A) / d ;
00402 ++ centy) {
00403 for (centx = 0 ;
00404 centx <= (f->width - 1 - A) / d ;
00405 ++ centx) {
00406 k->x = centx*d + A_ ;
00407 k->y = centy*d + A_ ;
00408
00409 k->norm = normalize_histogram (dpt, dpt + NBP*NBP*NBO) ;
00410 for(bint = 0; bint < NBO*NBP*NBP ; ++ bint) {
00411 if (dpt[bint] > 0.2f) dpt[bint] = 0.2f ;
00412 }
00413 k->norm *= normalize_histogram (dpt, dpt + NBP*NBP*NBO) ;
00414 ++ k ;
00415 dpt += NBP*NBP*NBO ;
00416 }
00417 }
00418 }
00419 }
00420