lbp.c
Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 2013 Andrea Vedaldi.
00008 Copyright (C) 2007-12 Andrea Vedaldi and Brian Fulkerson.
00009 All rights reserved.
00010 
00011 This file is part of the VLFeat library and is made available under
00012 the terms of the BSD license (see the COPYING file).
00013 */
00014 
00112 #include "lbp.h"
00113 #include "mathop.h"
00114 #include "string.h"
00115 
00116 /* ---------------------------------------------------------------- */
00117 /*                                           Initialization helpers */
00118 /* ---------------------------------------------------------------- */
00119 
00120 /*
00121  This function creates the LBP quantization table for the uniform LBP
00122  patterns. The purpose of this lookup table is to map a 8-bit LBP
00123  strings to one of 58 uniform pattern codes.
00124 
00125  Pixels in the 8-neighbourhoods are read in counterclockwise order
00126  starting from the east direction, as follows:
00127 
00128  NW(5)  N(6) NE(7)
00129  W(4)         E(0)  -> b0 b1 b2 b3 b4 b5 b6 b7
00130  SW(3)  S(2) SE(1)
00131 
00132  There are 256 such strings, indexing the lookup table. The table
00133  contains the corresponding code, effectively quantizing the 256
00134  patterns into 58. There is one bin for constant patterns (all zeros
00135  or ones), 8*7 for the uniform ones, and one for all other.
00136 
00137  A uniform pattern is a circular sequence of bit b0b1...b7 such that
00138  there is exactly one switch from 0 to 1 and one from 1 to 0.  These
00139  uniform patterns are enumerated as follows. The slowest varying index
00140  i (0...7) points to the first bit that is on and the slowest varying
00141  index j (1...7) to the length of the run of bits equal to one,
00142  resulting in the sequence:
00143 
00144  0:  1000 0000
00145  1:  1100 0000
00146  ...
00147  7:  1111 1110
00148  8:  0100 0000
00149  9:  0110 0000
00150  ...
00151  56: 1111 1101
00152 
00153  The function also accounts for when the image is stored in transposed
00154  format. The sampling function is unchanged, so that the first bit to
00155  be read is not the one to the east, but the one to the south, and
00156  overall the following sequence is read:
00157 
00158  NW(5)  W(4) SW(3)
00159  N(6)         S(2)  -> b2 b1 b0 b7 b6 b5 b4 b3
00160  NE(7)  E(0) SE(1)
00161 
00162  In enumerating the uniform patterns, the index j is unchanged as it
00163  encodes the runlenght. On the contrary, the index i changes to
00164  account for the transposition and for the fact that the beginning and
00165  ending of the run are swapped. With modular arithmetic, the i must be
00166  transformed as
00167 
00168  ip = - i + 2 - (j - 1)
00169  */
00170 
00171 static void
00172 _vl_lbp_init_uniform(VlLbp * self)
00173 {
00174   int i, j ;
00175 
00176   /* overall number of quantized LBPs */
00177   self->dimension = 58 ;
00178 
00179   /* all but selected patterns map to bin 57 (the first bin has index 0) */
00180   for (i = 0 ; i < 256 ; ++i) {
00181     self->mapping[i] = 57 ;
00182   }
00183 
00184   /* the uniform (all zeros or ones) patterns map to bin 56 */
00185   self->mapping[0x00] = 56 ;
00186   self->mapping[0xff] = 56 ;
00187 
00188   /* 56 uniform patterns */
00189   for (i = 0 ; i < 8 ; ++i) {
00190     for (j = 1 ; j <= 7 ; ++j) {
00191       int ip ;
00192       int unsigned string ;
00193       if (self->transposed) {
00194         ip = (- i + 2 - (j - 1) + 16) % 8 ;
00195       } else {
00196         ip = i ;
00197       }
00198 
00199       /* string starting with j ones */
00200       string = (1 << j) - 1 ;
00201       string <<= ip ;
00202       string = (string | (string >> 8)) & 0xff ;
00203 
00204       self->mapping[string] = i * 7 + (j-1) ;
00205     }
00206   }
00207 }
00208 
00209 /* ---------------------------------------------------------------- */
00210 
00217 VlLbp *
00218 vl_lbp_new(VlLbpMappingType type, vl_bool transposed)
00219 {
00220   VlLbp * self = vl_malloc(sizeof(VlLbp)) ;
00221   if (self == NULL) {
00222     vl_set_last_error(VL_ERR_ALLOC, NULL) ;
00223     return NULL ;
00224   }
00225   self->transposed = transposed ;
00226   switch (type) {
00227     case VlLbpUniform: _vl_lbp_init_uniform(self) ; break ;
00228     default: exit(1) ;
00229   }
00230   return self ;
00231 }
00232 
00237 void
00238 vl_lbp_delete(VlLbp * self) {
00239   vl_free(self) ;
00240 }
00241 
00248 VL_EXPORT vl_size vl_lbp_get_dimension(VlLbp * self)
00249 {
00250   return self->dimension ;
00251 }
00252 
00253 /* ---------------------------------------------------------------- */
00254 
00269 VL_EXPORT void
00270 vl_lbp_process (VlLbp * self,
00271                 float * features,
00272                 float * image, vl_size width, vl_size height,
00273                 vl_size cellSize)
00274 {
00275   vl_size cwidth = width / cellSize;
00276   vl_size cheight = height / cellSize ;
00277   vl_size cstride = cwidth * cheight ;
00278   vl_size cdimension = vl_lbp_get_dimension(self) ;
00279   vl_index x,y,cx,cy,k,bin ;
00280 
00281 #define at(u,v) (*(image + width * (v) + (u)))
00282 #define to(u,v,w) (*(features + cstride * (w) + cwidth * (v) + (u)))
00283 
00284   /* clear the output buffer */
00285   memset(features, 0, sizeof(float)*cdimension*cstride) ;
00286 
00287   /* accumulate pixel-level measurements into cells */
00288   for (y = 1 ; y < (signed)height - 1 ; ++y) {
00289     float wy1 = (y + 0.5f) / (float)cellSize - 0.5f ;
00290     int cy1 = (int) vl_floor_f(wy1) ;
00291     int cy2 = cy1 + 1 ;
00292     float wy2 = wy1 - (float)cy1 ;
00293     wy1 = 1.0f - wy2 ;
00294     if (cy1 >= (signed)cheight) continue ;
00295 
00296     for (x = 1 ; x < (signed)width - 1; ++x) {
00297       float wx1 = (x + 0.5f) / (float)cellSize - 0.5f ;
00298       int cx1 = (int) vl_floor_f(wx1) ;
00299       int cx2 = cx1 + 1 ;
00300       float wx2 = wx1 - (float)cx1 ;
00301       wx1 = 1.0f - wx2 ;
00302       if (cx1 >= (signed)cwidth) continue ;
00303 
00304       {
00305         int unsigned bitString = 0 ;
00306         float center = at(x,y) ;
00307         if(at(x+1,y+0) > center) bitString |= 0x1 << 0; /*  E */
00308         if(at(x+1,y+1) > center) bitString |= 0x1 << 1; /* SE */
00309         if(at(x+0,y+1) > center) bitString |= 0x1 << 2; /* S  */
00310         if(at(x-1,y+1) > center) bitString |= 0x1 << 3; /* SW */
00311         if(at(x-1,y+0) > center) bitString |= 0x1 << 4; /*  W */
00312         if(at(x-1,y-1) > center) bitString |= 0x1 << 5; /* NW */
00313         if(at(x+0,y-1) > center) bitString |= 0x1 << 6; /* N  */
00314         if(at(x+1,y-1) > center) bitString |= 0x1 << 7; /* NE */
00315         bin = self->mapping[bitString] ;
00316       }
00317 
00318       if ((cx1 >= 0) & (cy1 >=0)) {
00319         to(cx1,cy1,bin) += wx1 * wy1;
00320       }
00321       if ((cx2 < (signed)cwidth)  & (cy1 >=0)) {
00322         to(cx2,cy1,bin) += wx2 * wy1 ;
00323       }
00324       if ((cx1 >= 0) & (cy2 < (signed)cheight)) {
00325         to(cx1,cy2,bin) += wx1 * wy2 ;
00326       }
00327       if ((cx2 < (signed)cwidth) & (cy2 < (signed)cheight)) {
00328         to(cx2,cy2,bin) += wx2 * wy2 ;
00329       }
00330     } /* x */
00331   } /* y */
00332 
00333   /* normalize cells */
00334   for (cy = 0 ; cy < (signed)cheight ; ++cy) {
00335     for (cx = 0 ; cx < (signed)cwidth ; ++ cx) {
00336       float norm = 0 ;
00337       for (k = 0 ; k < (signed)cdimension ; ++k) {
00338         norm += features[k * cstride] ;
00339       }
00340       norm = sqrtf(norm) + 1e-10f; ;
00341       for (k = 0 ; k < (signed)cdimension ; ++k) {
00342         features[k * cstride] = sqrtf(features[k * cstride]) / norm  ;
00343       }
00344       features += 1 ;
00345     }
00346   } /* next cell to normalize */
00347 }


libvlfeat
Author(s): Andrea Vedaldi
autogenerated on Thu Jun 6 2019 20:25:51