SHOGUN
v3.2.0
|
00001 /* 00002 * This program is free software; you can redistribute it and/or modify 00003 * it under the terms of the GNU General Public License as published by 00004 * the Free Software Foundation; either version 3 of the License, or 00005 * (at your option) any later version. 00006 * 00007 * Written (W) 2010 Vojtech Franc, Soeren Sonnenburg 00008 * Written (W) 2013 Evangelos Anagnostopoulos 00009 * Copyright (C) 2010 Vojtech Franc, xfrancv@cmp.felk.cvut.cz 00010 * Copyright (C) 2010 Berlin Institute of Technology 00011 */ 00012 #include <shogun/features/LBPPyrDotFeatures.h> 00013 00014 using namespace shogun; 00015 00016 #define LIBLBP_INDEX(ROW,COL,NUM_ROWS) ((COL)*(NUM_ROWS)+(ROW)) 00017 00018 CLBPPyrDotFeatures::CLBPPyrDotFeatures() : CDotFeatures() 00019 { 00020 init(NULL, 0, 0); 00021 vec_nDim = 0; 00022 } 00023 00024 CLBPPyrDotFeatures::CLBPPyrDotFeatures(CDenseFeatures<uint32_t>* image_set, int32_t image_w, 00025 int32_t image_h, uint16_t num_pyramids) : CDotFeatures() 00026 { 00027 ASSERT(image_set) 00028 init(image_set, image_w, image_h); 00029 vec_nDim = liblbp_pyr_get_dim(num_pyramids); 00030 } 00031 00032 void CLBPPyrDotFeatures::init(CDenseFeatures<uint32_t>* image_set, int32_t image_w, int32_t image_h) 00033 { 00034 images = image_set; 00035 SG_REF(images); 00036 image_width = image_w; 00037 image_height = image_h; 00038 00039 SG_ADD((CSGObject**) &images, "images", "Set of images", MS_NOT_AVAILABLE); 00040 SG_ADD(&image_width, "image_width", "The image width", MS_NOT_AVAILABLE); 00041 SG_ADD(&image_height, "image_height", "The image height", MS_NOT_AVAILABLE); 00042 SG_ADD(&vec_nDim, "vec_nDim", "The dimension of the pyr", MS_NOT_AVAILABLE); 00043 } 00044 00045 CLBPPyrDotFeatures::~CLBPPyrDotFeatures() 00046 { 00047 SG_UNREF(images); 00048 } 00049 00050 CLBPPyrDotFeatures::CLBPPyrDotFeatures(const CLBPPyrDotFeatures& orig) 00051 { 00052 init(orig.images, orig.image_width, orig.image_height); 00053 vec_nDim = orig.vec_nDim; 00054 } 00055 00056 int32_t CLBPPyrDotFeatures::get_dim_feature_space() const 00057 { 00058 return vec_nDim; 00059 } 00060 00061 int32_t CLBPPyrDotFeatures::get_nnz_features_for_vector(int32_t num) 00062 { 00063 return vec_nDim; 00064 } 00065 00066 EFeatureType CLBPPyrDotFeatures::get_feature_type() const 00067 { 00068 return F_UNKNOWN; 00069 } 00070 00071 EFeatureClass CLBPPyrDotFeatures::get_feature_class() const 00072 { 00073 return C_POLY; 00074 } 00075 00076 int32_t CLBPPyrDotFeatures::get_num_vectors() const 00077 { 00078 return images->get_num_vectors(); 00079 } 00080 00081 void* CLBPPyrDotFeatures::get_feature_iterator(int32_t vector_index) 00082 { 00083 SG_NOTIMPLEMENTED 00084 return NULL; 00085 } 00086 00087 bool CLBPPyrDotFeatures::get_next_feature(int32_t& index, float64_t& value, void* iterator) 00088 { 00089 SG_NOTIMPLEMENTED 00090 return false; 00091 } 00092 00093 void CLBPPyrDotFeatures::free_feature_iterator(void* iterator) 00094 { 00095 SG_NOTIMPLEMENTED 00096 } 00097 00098 float64_t CLBPPyrDotFeatures::dot(int32_t vec_idx1, CDotFeatures* df, int32_t vec_idx2) 00099 { 00100 ASSERT(strcmp(df->get_name(),get_name())==0) 00101 CLBPPyrDotFeatures* lbp_feat = (CLBPPyrDotFeatures* ) df; 00102 ASSERT(get_dim_feature_space() == lbp_feat->get_dim_feature_space()); 00103 00104 SGVector<char> vec1 = get_transformed_image(vec_idx1); 00105 SGVector<char> vec2 = lbp_feat->get_transformed_image(vec_idx2); 00106 00107 return SGVector<char>::dot(vec1.vector, vec2.vector, vec_nDim); 00108 } 00109 00110 SGVector<char> CLBPPyrDotFeatures::get_transformed_image(int32_t index) 00111 { 00112 SGVector<char> vec(vec_nDim); 00113 SGVector<char>::fill_vector(vec, vec_nDim, 0); 00114 00115 int32_t ww; 00116 int32_t hh; 00117 uint32_t* img = get_image(index, ww, hh); 00118 00119 int32_t offset = 0; 00120 while (true) 00121 { 00122 for (int32_t x=1; x<ww-1; x++) 00123 { 00124 for (int32_t y=1; y<hh-1; y++) 00125 { 00126 uint8_t pattern = create_lbp_pattern(img, x, y); 00127 vec[offset+pattern]++; 00128 offset += 256; 00129 } 00130 } 00131 if (vec_nDim <= offset) 00132 break; 00133 00134 00135 if (ww % 2 == 1) 00136 ww--; 00137 if (hh % 2 == 1) 00138 hh--; 00139 00140 ww = ww/2; 00141 for (int32_t x=0; x<ww; x++) 00142 for (int32_t j=0; j<hh; j++) 00143 img[LIBLBP_INDEX(j,x,image_height)] = img[LIBLBP_INDEX(j,2*x,image_height)] + 00144 img[LIBLBP_INDEX(j,2*x+1,image_height)]; 00145 00146 hh = hh/2; 00147 for (int32_t y=0; y<hh; y++) 00148 for (int32_t j=0; j<ww; j++) 00149 img[LIBLBP_INDEX(y,j,image_height)] = img[LIBLBP_INDEX(2*y,j,image_height)] + 00150 img[LIBLBP_INDEX(2*y+1,j,image_height)]; 00151 } 00152 00153 SG_FREE(img); 00154 return vec; 00155 } 00156 00157 uint32_t* CLBPPyrDotFeatures::get_image(int32_t index, int32_t& width, int32_t& height) 00158 { 00159 int32_t len; 00160 bool do_free; 00161 uint32_t* image = images->get_feature_vector(index, len, do_free); 00162 uint32_t* img; 00163 img = SG_MALLOC(uint32_t, len); 00164 memcpy(img, image, len * sizeof(uint32_t)); 00165 images->free_feature_vector(image, index, do_free); 00166 width = image_width; 00167 height = image_height; 00168 return img; 00169 } 00170 00171 float64_t CLBPPyrDotFeatures::dense_dot(int32_t vec_idx1, float64_t* vec2, int32_t vec2_len) 00172 { 00173 if (vec2_len != vec_nDim) 00174 SG_ERROR("Dimensions don't match, vec2_dim=%d, vec_nDim=%d\n", vec2_len, vec_nDim) 00175 00176 int32_t ww; 00177 int32_t hh; 00178 uint32_t* img = get_image(vec_idx1, ww, hh); 00179 00180 float64_t dot_prod = 0; 00181 int32_t offset = 0; 00182 while (true) 00183 { 00184 for (int32_t x=1; x<ww-1; x++) 00185 { 00186 for (int32_t y=1; y<hh-1; y++) 00187 { 00188 uint8_t pattern = create_lbp_pattern(img, x, y); 00189 dot_prod += vec2[offset+pattern]; 00190 offset += 256; 00191 } 00192 } 00193 if (vec_nDim <= offset) 00194 break; 00195 00196 00197 if (ww % 2 == 1) 00198 ww--; 00199 if (hh % 2 == 1) 00200 hh--; 00201 00202 ww = ww/2; 00203 for (int32_t x=0; x<ww; x++) 00204 for (int32_t j=0; j<hh; j++) 00205 img[LIBLBP_INDEX(j,x,image_height)] = img[LIBLBP_INDEX(j,2*x,image_height)] + 00206 img[LIBLBP_INDEX(j,2*x+1,image_height)]; 00207 00208 hh = hh/2; 00209 for (int32_t y=0; y<hh; y++) 00210 for (int32_t j=0; j<ww; j++) 00211 img[LIBLBP_INDEX(y,j,image_height)] = img[LIBLBP_INDEX(2*y,j,image_height)] + 00212 img[LIBLBP_INDEX(2*y+1,j,image_height)]; 00213 } 00214 00215 SG_FREE(img); 00216 return dot_prod; 00217 } 00218 00219 void CLBPPyrDotFeatures::add_to_dense_vec(float64_t alpha, int32_t vec_idx1, float64_t* vec2, int32_t vec2_len, bool abs_val) 00220 { 00221 if (vec2_len != vec_nDim) 00222 SG_ERROR("Dimensions don't match, vec2_dim=%d, vec_nDim=%d\n", vec2_len, vec_nDim) 00223 00224 int32_t ww; 00225 int32_t hh; 00226 uint32_t* img = get_image(vec_idx1, ww, hh); 00227 00228 if (abs_val) 00229 alpha = CMath::abs(alpha); 00230 00231 int32_t offset = 0; 00232 00233 while (true) 00234 { 00235 for (int32_t x=1; x<ww-1; x++) 00236 { 00237 for (int32_t y=1; y<hh-1; y++) 00238 { 00239 uint8_t pattern = create_lbp_pattern(img, x, y); 00240 vec2[offset+pattern] += alpha; 00241 offset += 256; 00242 } 00243 } 00244 if (vec_nDim <= offset) 00245 break; 00246 00247 00248 if (ww % 2 == 1) 00249 ww--; 00250 if (hh % 2 == 1) 00251 hh--; 00252 00253 ww = ww/2; 00254 for (int32_t x=0; x<ww; x++) 00255 for (int32_t j=0; j<hh; j++) 00256 img[LIBLBP_INDEX(j,x,image_height)] = img[LIBLBP_INDEX(j,2*x,image_height)] + 00257 img[LIBLBP_INDEX(j,2*x+1,image_height)]; 00258 00259 hh = hh/2; 00260 for (int32_t y=0; y<hh; y++) 00261 for (int32_t j=0; j<ww; j++) 00262 img[LIBLBP_INDEX(y,j,image_height)] = img[LIBLBP_INDEX(2*y,j,image_height)] + 00263 img[LIBLBP_INDEX(2*y+1,j,image_height)]; 00264 } 00265 SG_FREE(img); 00266 } 00267 00268 uint8_t CLBPPyrDotFeatures::create_lbp_pattern(uint32_t* img, int32_t x, int32_t y) 00269 { 00270 uint8_t pattern = 0; 00271 uint32_t center = img[LIBLBP_INDEX(y,x,image_height)]; 00272 00273 if (img[LIBLBP_INDEX(y-1,x-1,image_height)] < center) 00274 pattern |= 0x01; 00275 if (img[LIBLBP_INDEX(y-1,x,image_height)] < center) 00276 pattern |= 0x02; 00277 if (img[LIBLBP_INDEX(y-1,x+1,image_height)] < center) 00278 pattern |= 0x04; 00279 if (img[LIBLBP_INDEX(y,x-1,image_height)] < center) 00280 pattern |= 0x08; 00281 if (img[LIBLBP_INDEX(y,x+1,image_height)] < center) 00282 pattern |= 0x10; 00283 if (img[LIBLBP_INDEX(y+1,x-1,image_height)] < center) 00284 pattern |= 0x20; 00285 if (img[LIBLBP_INDEX(y+1,x,image_height)] < center) 00286 pattern |= 0x40; 00287 if (img[LIBLBP_INDEX(y+1,x+1,image_height)] < center) 00288 pattern |= 0x80; 00289 00290 return pattern; 00291 } 00292 00293 CFeatures* CLBPPyrDotFeatures::duplicate() const 00294 { 00295 return new CLBPPyrDotFeatures(*this); 00296 } 00297 00298 uint32_t CLBPPyrDotFeatures::liblbp_pyr_get_dim(uint16_t nPyramids) 00299 { 00300 uint32_t N = 0; 00301 uint32_t w = image_width; 00302 uint32_t h = image_height; 00303 00304 for (uint32_t i=0; (i<nPyramids) && (CMath::min(w,h)>=3); i++) 00305 { 00306 N += (w-2)*(h-2); 00307 00308 if (w % 2) 00309 w--; 00310 if (h % 2) 00311 h--; 00312 00313 w = w/2; 00314 h = h/2; 00315 } 00316 return 256*N; 00317 }