libeblearntools
|
00001 /*************************************************************************** 00002 * Copyright (C) 2009 by Pierre Sermanet * 00003 * pierre.sermanet@gmail.com * 00004 * All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions are met: 00008 * * Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * * Redistribution under a license not approved by the Open Source 00014 * Initiative (http://www.opensource.org) must display the 00015 * following acknowledgement in all advertising material: 00016 * This product includes software developed at the Courant 00017 * Institute of Mathematical Sciences (http://cims.nyu.edu). 00018 * * The names of the authors may not be used to endorse or promote products 00019 * derived from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 00022 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00023 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00024 * DISCLAIMED. IN NO EVENT SHALL ThE AUTHORS BE LIABLE FOR ANY 00025 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00026 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00027 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00028 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00029 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 ***************************************************************************/ 00032 00033 #ifndef DATASET_HPP_ 00034 #define DATASET_HPP_ 00035 00036 #include <algorithm> 00037 #include <sys/stat.h> 00038 #include <sys/types.h> 00039 #include <limits> 00040 #include <typeinfo> 00041 00042 #ifdef __GUI__ 00043 #include "libidxgui.h" 00044 #endif 00045 00046 #include "defines_tools.h" 00047 #include "sort.h" 00048 #include "tools_utils.h" 00049 00050 #ifdef __BOOST__ 00051 #define BOOST_FILESYSTEM_VERSION 2 00052 #include "boost/filesystem.hpp" 00053 #include "boost/regex.hpp" 00054 using namespace boost::filesystem; 00055 using namespace boost; 00056 #endif 00057 00058 using namespace std; 00059 00060 namespace ebl { 00061 00063 // jitter methods 00064 00065 template <typename T> 00066 rect<T> jitter::get_rect(const rect<T> &r, float ratio) { 00067 rect<T> j = r; // jittered box 00068 j.scale_centered(s, s); // apply scale jitter 00069 j.h0 += (T) (h * ratio); // apply height offset jitter 00070 j.w0 += (T) (w * ratio); // apply width offset jitter 00071 // EDEBUG("jittering rect " << r << " with spatial jitter " << h << "x" << w 00072 // << " and spatial jitter ratio " << ratio << ": " << j); 00073 return j; 00074 } 00075 00077 // constructors & initializations 00078 00079 template <class Tdata> 00080 dataset<Tdata>::dataset(const char *name_, const char *inroot_) { 00081 // initialize members 00082 allocated = false; 00083 string bname = ebl::basename(name_); 00084 set_name(bname); 00085 if (inroot_) { 00086 inroot = inroot_; 00087 inroot += "/"; 00088 } else inroot = ebl::dirname(name_); 00089 no_outdims = true; 00090 outdims = idxdim(96, 96, 1); 00091 height = outdims.dim(0); 00092 width = outdims.dim(1); 00093 mindims = idxdim(1, 1); 00094 maxdims = idxdim(1, 1); 00095 maxdims_set = false; 00096 max_data = 0; 00097 max_data_set = false; 00098 total_samples = 0; 00099 display_extraction = false; 00100 display_result = false; 00101 bsave_display = false; 00102 // preprocessing 00103 extension = IMAGE_PATTERN_MAT; 00104 sleep_display = false; 00105 sleep_delay = 0; 00106 // assuming already processed data, but the user can still require 00107 // processing via the set_preprocessing method. 00108 do_preprocessing = false; 00109 scale_mode = false; 00110 scales.push_back(1); // initialize with scale 1 00111 data_cnt = 0; 00112 interleaved_input = true; 00113 load_planar = false; 00114 max_per_class_set = false; 00115 mpc = (numeric_limits<intg>::max)(); 00116 dynamic_init_drand(); // initialize random seed 00117 usepose = false; 00118 useparts = false; 00119 usepartsonly = false; 00120 save_mode = DYNSET_SAVE; 00121 individual_save = true; // save individual files by default. 00122 separate_layers_save = false; // save layers in separate files or not. 00123 bbox_woverh = 0.0; // 0.0 means not set 00124 force_label = ""; 00125 nclasses = 0; 00126 add_errors = 0; 00127 nopadded = false; 00128 wmirror = false; 00129 // jitter 00130 tjitter_step = 0; 00131 tjitter_hmin = 0; 00132 tjitter_hmax = 0; 00133 tjitter_wmin = 0; 00134 tjitter_wmax = 0; 00135 sjitter_steps = 0; 00136 sjitter_min = 0; 00137 sjitter_max = 0; 00138 rjitter_steps = 0; 00139 rjitter = 0; 00140 njitter = 0; 00141 minvisibility = 0; 00142 bjitter = false; 00143 nlayers = 1; 00144 //videobox 00145 do_videobox = false; 00146 videobox_nframes = 0; 00147 videobox_stride = 0; 00148 load_img = midx<Tdata>(1); 00149 #ifndef __BOOST__ 00150 eblerror(BOOST_LIB_ERROR); 00151 #endif 00152 } 00153 00154 template <class Tdata> 00155 dataset<Tdata>::~dataset() { 00156 for (uint i = 0; i < ppmods.size(); ++i) 00157 delete ppmods[i]; 00158 } 00159 00160 template <class Tdata> 00161 bool dataset<Tdata>::alloc(intg max) { 00162 // save maximum number of samples if specified 00163 if (max > 0) { 00164 max_data = max; 00165 max_data_set = true; 00166 cout << "Limiting dataset to " << max << " samples." << endl; 00167 } 00168 if (classes.size() == 0) 00169 eblerror("found 0 class"); 00170 cout << "Found: "; print_classes(); cout << "." << endl; 00171 // (re)init max per class, knowing number of classes 00172 intg m = (numeric_limits<intg>::max)(); 00173 if (max_per_class_set) { // mpc has already been set 00174 m = mpc; 00175 set_max_per_class(m); 00176 } 00177 // allocate 00178 if (!allocate(total_samples, outdims)) 00179 eblerror("allocation failed"); 00180 // alloc tallies 00181 add_tally = idx<intg>(classes.size()); 00182 idx_clear(add_tally); 00183 return true; 00184 } 00185 00187 // data extraction 00188 00189 template <class Tdata> 00190 bool dataset<Tdata>::extract() { 00191 // extract 00192 #ifdef __BOOST__ 00193 if (!allocated && !scale_mode && !strcmp(save_mode.c_str(), DATASET_SAVE)) 00194 return false; 00195 cmatch what; 00196 regex hidden_dir(".svn"); 00197 bool found = false; 00198 xtimer.start(); // start timing extraction 00199 processed_cnt = 0; 00200 directory_iterator end_itr; // default construction yields past-the-end 00201 for (directory_iterator itr(inroot); itr != end_itr; itr++) { 00202 #if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 00203 if (is_directory(itr->status()) 00204 && !regex_match(itr->leaf().c_str(), what, hidden_dir)) { 00205 process_dir(itr->path().string(), extension, itr->leaf()); 00206 #else 00207 if (is_directory(itr->status()) 00208 && !regex_match(itr->path().filename().c_str(), what, hidden_dir)) { 00209 process_dir(itr->path().string(), extension, itr->path().filename()); 00210 #endif 00211 found = true; 00212 }} 00213 if (found) { 00214 cerr << "Samples adding failures: " << add_errors << endl; 00215 } else { 00216 cerr << "No class found in " << inroot 00217 << ", extracting images in local directory with name \"unknown\"" 00218 << endl; 00219 process_dir(inroot, extension, "unknown"); 00220 return true; 00221 } 00222 cout << "Extraction time: " << xtimer.elapsed() << endl; 00223 #endif /* __BOOST__ */ 00224 return true; 00225 } 00226 00227 template <class Tdata> 00228 void dataset<Tdata>::extract_statistics() { 00229 eblerror("not implemented"); 00230 } 00231 00233 // data 00234 00235 template <class Tdata> 00236 bool dataset<Tdata>::split_max_and_save(const char *name1, const char *name2, 00237 intg max, const string &outroot) { 00238 dataset<Tdata> ds1(name1); 00239 dataset<Tdata> ds2(name2); 00240 ds1.set_outdims(outdims); 00241 ds2.set_outdims(outdims); 00242 // if excluded classes exist, set them in ds1 and ds2 00243 if (exclude.size() > 0) { 00244 ds1.set_exclude(exclude); 00245 ds2.set_exclude(exclude); 00246 } 00247 split_max(ds1, ds2, max); 00248 bool ret1 = ds1.save(outroot); 00249 bool ret2 = ds2.save(outroot); 00250 return ret1 || ret2; 00251 } 00252 00253 template <class Tdata> 00254 void dataset<Tdata>::split_max(dataset<Tdata> &ds1, dataset<Tdata> &ds2, 00255 intg max) { 00256 cout << "Splitting \"" << name << "\" into datasets \""; 00257 cout << ds1.name << "\" and \"" << ds2.name << "\", limiting dataset \""; 00258 cout << ds1.name << "\" to " << max << " samples per class, the rest "; 00259 cout << "going to \"" << ds2.name << "\"." << endl; 00260 00261 // copy classes strings 00262 if (classes.size() > 0) { 00263 idx<ubyte> classidx = build_classes_idx(classes); 00264 ds1.set_classes(classidx); 00265 ds2.set_classes(classidx); 00266 } 00267 ds1.nclasses = nclasses; 00268 ds2.nclasses = nclasses; 00269 // set max samples per class for dataset 1 (ds2 takes whatever is left) 00270 ds1.set_max_per_class(max); 00271 // split 00272 split(ds1, ds2); 00273 } 00274 00275 template <class Tdata> 00276 void dataset<Tdata>::shuffle() { 00277 cout << "Shuffling dataset \"" << name << "\"." << endl; 00278 dynamic_init_drand(); // initialize random seed 00279 idx_shuffle_together(data, labels, 0); 00280 } 00281 00283 // data preprocessing 00284 00285 template <class Tdata> 00286 void dataset<Tdata>::set_planar_loading() { 00287 cout << "Inputs are loaded as planar." << endl; 00288 load_planar = true; 00289 } 00290 00292 // accessors 00293 00294 template <class Tdata> 00295 const idxdim& dataset<Tdata>::get_sample_outdim() { 00296 return outdims; 00297 } 00298 00299 template <class Tdata> 00300 intg dataset<Tdata>::size() { 00301 return data_cnt; 00302 } 00303 00304 template <class Tdata> 00305 t_label dataset<Tdata>::get_label_from_class(const string &class_name) { 00306 t_label label = 0; 00307 vector<string>::iterator res; 00308 res = find(classes.begin(), classes.end(), class_name); 00309 if (res == classes.end()) { // not found 00310 return -42; // excluded class 00311 } 00312 // found 00313 label = res - classes.begin(); 00314 return label; 00315 } 00316 00317 template <class Tdata> 00318 void dataset<Tdata>::set_display(bool display_) { 00319 #ifdef __GUI__ 00320 if (display_) { 00321 cout << "Enabling display." << endl; 00322 new_window("Dataset compiler"); 00323 display_extraction = display_; 00324 } 00325 #endif /* __GUI__ */ 00326 } 00327 00328 template <class Tdata> 00329 void dataset<Tdata>::set_sleepdisplay(uint delay) { 00330 if (delay > 0) { 00331 cout << "Enabling sleeping display for " << delay << "ms." << endl; 00332 sleep_display = true; 00333 sleep_delay = delay; 00334 } 00335 } 00336 00337 template <class Tdata> 00338 void dataset<Tdata>:: 00339 set_preprocessing(vector<resizepp_module<fs(Tdata)>*> &p){ 00340 if (p.size() == 0) { 00341 cout << "No preprocessing." << endl; 00342 return ; 00343 } 00344 pp_names = ""; 00345 nlayers = 0; 00346 for (uint i = 0; i < p.size(); ++i) { 00347 ppmods.push_back(p[i]); 00348 pp_names << p[i]->name(); 00349 if (i + 1 != p.size()) pp_names << ","; 00350 nlayers += p[i]->nlayers(); 00351 if (p[i]->nlayers() == 0) 00352 eblerror("expected at least 1 layer in output of preprocessing module " 00353 << p[i]->name()); 00354 } 00355 cout << "Setting preprocessing to: " << pp_names << endl; 00356 cout << "Preprocessing produces " << nlayers << " layers per sample." 00357 << endl; 00358 cout << "Preprocessing modules:" << endl; 00359 for (uint i = 0; i < p.size(); ++i) 00360 cout << i << ": " << ppmods[i]->describe() << endl; 00361 do_preprocessing = true; 00362 } 00363 00364 template <class Tdata> 00365 bool dataset<Tdata>::full(t_label label) { 00366 if (!total_samples) // we did not count samples, no opinion 00367 return false; 00368 if ((max_data_set && (data_cnt >= max_data)) || 00369 ((data.order() > 0) && (data_cnt >= data.dim(0)))) 00370 return true; 00371 if (!scale_mode) { 00372 if (label == -42) // excluded class 00373 return true; 00374 if (max_per_class_set && (label >= 0) && 00375 (add_tally.get(label) >= max_per_class.get(label))) 00376 return true; 00377 } 00378 return false; 00379 } 00380 00382 // print methods 00383 00384 template <class Tdata> 00385 void dataset<Tdata>::print_classes() { 00386 cout << nclasses << " classe"; 00387 if (nclasses > 1) cout << "s"; 00388 if (classes.size() > 0) { 00389 cout << " ("; 00390 uint i; 00391 for (i = 0; i < classes.size() - 1; ++i) 00392 cout << classes[i] << ", "; 00393 cout << classes[i] << ")"; 00394 } 00395 } 00396 00397 template <class Tdata> 00398 void dataset<Tdata>::print_stats() { 00399 compute_stats(); 00400 // print stats 00401 cout << "Dataset \"" << name << "\" contains " << data_cnt; 00402 cout << " samples (of dimensions " << outdims << " and "; 00403 cout << typeid(Tdata).name() << " precision)"; 00404 cout << ", distributed in " << nclasses << " classes"; 00405 if (classes.size() > 0) { 00406 uint i; 00407 cout << ": "; 00408 for (i = 0; i < classes.size() - 1; ++i) 00409 cout << class_tally.get(i) << " \"" << classes[i] << "\", "; 00410 cout << class_tally.get(i) << " " << classes[i] << "\"."; 00411 } 00412 cout << endl; 00413 } 00414 00416 // I/O 00417 00418 template <class Tdata> 00419 bool dataset<Tdata>::load(const string &root) { 00420 string fname; 00421 string root1 = root; 00422 root1 += "/"; 00423 cout << "Loading dataset " << name << " from " << root1; 00424 cout << name << "_*" << MATRIX_EXTENSION << endl; 00425 // load data 00426 data = midx<Tdata>(1,1); 00427 fname = root1; fname += data_fname; 00428 loading_error(data, fname); 00429 // load labels 00430 labels = idx<t_label>(1); 00431 fname = root1; fname += labels_fname; 00432 loading_error(labels, fname); 00433 // load ids 00434 ids = idx<intg>(1); 00435 fname = ""; fname << root1 << "/" << ids_fname; 00436 loading_warning<intg>(ids, fname); 00437 // load jitter 00438 fname = root1; fname += jitters_fname; 00439 loading_warning<t_jitter>(jitters, fname); 00440 // load classes 00441 idx<ubyte> classidx; 00442 classidx = idx<ubyte>(1,1); 00443 fname = root1; fname += classes_fname; 00444 if (loading_warning(classidx, fname)) 00445 set_classes(classidx); 00446 else 00447 nclasses = idx_max(labels) + 1; 00448 // load classpairs 00449 classpairs = idx<t_label>(1,1); 00450 fname = root1; fname += classpairs_fname; 00451 loading_nowarning(classpairs, fname); 00452 // load deformation pairs 00453 deformpairs = idx<t_label>(1,1); 00454 fname = root1; fname += deformpairs_fname; 00455 loading_nowarning(deformpairs, fname); 00456 // initialize some members 00457 data_cnt = data.dim(0); 00458 allocated = true; 00459 idx<Tdata> sample; 00460 if (data.order() == 2) 00461 sample = data.get(0, 0); 00462 else 00463 sample = data.get(0); 00464 outdims = sample.get_idxdim(); 00465 print_stats(); 00466 return true; 00467 } 00468 00469 template <class Tdata> 00470 bool dataset<Tdata>::save(const string &root, bool save_data) { 00471 if (!allocated && !strcmp(save_mode.c_str(), DATASET_SAVE)) 00472 return false; 00473 string root1 = root; 00474 root1 += "/"; 00475 cout << "Saving " << name << " in " << save_mode << " mode." << endl; 00476 // if force label is on, replace labels by force_label 00477 if (strcmp(force_label.c_str(), "")) { 00478 cout << "Forcing all labels to: " << force_label << endl; 00479 classes.clear(); 00480 add_class(force_label); 00481 idx_clear(labels); // setting all labels to 0 00482 idx_clear(ids); 00483 } 00484 // return false if no samples 00485 if (data_cnt <= 0) { 00486 cerr << "Warning: No samples were added to the dataset, nothing to save."; 00487 cerr << endl; 00488 return false; 00489 } 00490 // creating directory 00491 mkdir_full(root1); 00492 // remove for empty slots 00493 midx<Tdata> dat = data; 00494 idx<t_label> labs = labels; 00495 idx<intg> scals = ids; 00496 midx<t_jitter> jitts = jitters; 00497 bool bjitts = (jitters.order() >= 1 && idx_max(jitters) > 0); 00498 if (data_cnt < total_samples) { 00499 cerr << "Warning: not all samples were added to dataset ("; 00500 cerr << total_samples - data_cnt << " missing out of " << total_samples; 00501 cerr << ")" << endl; 00502 cout << "Downsizing dataset to igore missing samples." << endl; 00503 if (!strcmp(save_mode.c_str(), DATASET_SAVE)) 00504 dat = dat.narrow(0, data_cnt, 0); 00505 labs = labs.narrow(0, data_cnt, 0); 00506 scals = scals.narrow(0, data_cnt, 0); 00507 if (bjitts) 00508 jitts = jitts.narrow(0, data_cnt, 0); 00509 } 00510 // switch between saving modes 00511 if (!strcmp(save_mode.c_str(), DATASET_SAVE) || 00512 !strcmp(save_mode.c_str(), DYNSET_SAVE)) { // dataset mode 00513 cout << "Saving dataset " << name << " in " << root << "/"; 00514 cout << name << "_*" << MATRIX_EXTENSION << endl; 00515 // save data 00516 string fname; 00517 if (save_data) { 00518 fname = ""; fname << root1 << data_fname; 00519 cout << "Saving " << fname << " (" << dat << ")" << endl; 00520 if (!strcmp(save_mode.c_str(), DATASET_SAVE)) { // save data matrix 00521 // // make sure dat can be transformed into a single idx 00522 // idx<Tdata> single = dat.pack(); 00523 // if (!save_matrix(single, fname)) { 00524 if (!save_matrix<Tdata>(images_list, fname)) { 00525 cerr << "error: failed to save " << fname << endl; 00526 return false; 00527 } else cout << "Saved " << fname << endl; 00528 } else if (!strcmp(save_mode.c_str(), DYNSET_SAVE)) { // compile data file from existing files 00529 if (images_list.size() > 0) { 00530 cout << "Saving dynamic dataset from a list of " 00531 << images_list.size() << " samples." << endl; 00532 if (!save_matrices<Tdata>(images_list, fname)) { 00533 cerr << "error: failed to save " << fname << endl; 00534 return false; 00535 } 00536 } else { 00537 cout << "Saving dynamic dataset from internal data matrix " 00538 << data << endl; 00539 if (!save_matrices<Tdata>(data, fname)) { 00540 cerr << "error: failed to save " << fname << endl; 00541 return false; 00542 } 00543 } 00544 cout << "Saved " << fname << endl; 00545 } 00546 } 00547 // save labels 00548 fname = ""; fname << root1 << labels_fname; 00549 cout << "Saving " << fname << " (" << labs << ")" << endl; 00550 if (!save_matrix(labs, fname)) { 00551 cerr << "error: failed to save labels into " << fname << endl; 00552 return false; 00553 } else cout << "Saved " << fname << endl; 00554 // save jitters 00555 if (bjitts) { 00556 fname = ""; fname << root1 << jitters_fname; 00557 cout << "Saving " << fname << " (" << jitts << ")" << endl; 00558 if (!save_matrices(jitts, fname)) { 00559 cerr << "error: failed to save labels into " << fname << endl; 00560 return false; 00561 } else cout << "Saved " << fname << endl; 00562 } 00563 // save ids 00564 fname = ""; fname << root1 << ids_fname; 00565 cout << "Saving " << fname << " (" << scals << ")" << endl; 00566 if (!save_matrix(scals, fname)) { 00567 cerr << "error: failed to save ids into " << fname << endl; 00568 return false; 00569 } else cout << "Saved " << fname << endl; 00570 // save classes 00571 if (classes.size() > 0) { 00572 fname = ""; fname << root1 << classes_fname; 00573 idx<ubyte> classes_idx = build_classes_idx(classes); 00574 cout << "Saving " << fname << " (" << classes_idx << ")" << endl; 00575 if (!save_matrix(classes_idx, fname)) { 00576 cerr << "error: failed to save classes into " << fname << endl; 00577 return false; 00578 } else cout << "Saved " << fname << endl; 00579 } 00580 } else { // single file mode, use save as image extensions 00581 // root1 += name; root1 += "/"; 00582 // mkdir_full(root1); 00583 // // save all images 00584 // ostringstream fname; 00585 // intg id = 0; 00586 // idx<Tdata> tmp; 00587 // idx_bloop2(dat, data, Tdata, lab, labs, t_label) { 00588 // // make class directory if necessary 00589 // fname.str(""); 00590 // fname << root1 << "/" << get_class_string(lab.get()) << "/"; 00591 // mkdir_full(fname.str().c_str()); 00592 // // save image 00593 // fname << get_class_string(lab.get()) << "_" << id++ << "." << save_mode; 00594 // tmp = dat.shift_dim(0, 2); // shift from planar to interleaved 00595 // // scale image to 0 255 if preprocessed 00596 // if (strcmp(ppconv_type.c_str(), "RGB")) { 00597 // idx_addc(tmp, (Tdata) 1.0, tmp); 00598 // idx_dotc(tmp, (Tdata) 127.5, tmp); 00599 // } 00600 // if (save_image(fname.str(), tmp, save_mode.c_str())) 00601 // cout << id << ": saved " << fname.str() << endl; 00602 // } 00603 } 00604 return true; 00605 } 00606 00608 // allocation 00609 00610 template <class Tdata> 00611 bool dataset<Tdata>::allocate(intg n, idxdim &d) { 00612 // allocate only once 00613 //if (allocated) 00614 // return false; 00615 // initialize members 00616 outdims = d; 00617 data_cnt = 0; 00618 // if max_data has been set, max n with max_data 00619 if (max_data_set) 00620 n = MIN(n, max_data); 00621 cout << "Dataset \"" << name << "\" will have " << n; 00622 cout << " samples of size " << d << endl; 00623 // max with max_per_class 00624 if (max_per_class_set) 00625 n = (std::max)((intg) 0, MIN(n, idx_sum(max_per_class))); 00626 if (n <= 0) { 00627 cerr << "Cannot allocate " << n << " samples." << endl; 00628 return false; 00629 } 00630 // allocate data buffer (only in dataset_save mode) 00631 if (!strcmp(save_mode.c_str(), DATASET_SAVE)) { 00632 cout << "Allocating dataset \"" << name << "\" with " << n; 00633 cout << " samples of size " << d << " (" 00634 << (n * d.nelements() * sizeof (Tdata)) / (1024 * 1024) 00635 << " Mb) ..." << endl; 00636 // uint c = 0, h = 1, w = 2; 00637 // if (interleaved_input) { 00638 // c = 2; h = 0; w = 1; 00639 // } 00640 // idxdim datadims(outdims.dim(c), outdims.dim(h), outdims.dim(w)); 00641 data = midx<Tdata>(n, nlayers); 00642 datadims = data.get_idxdim(); 00643 } 00644 // allocate labels buffer 00645 labels = idx<t_label>(n); 00646 ids = idx<intg>(n); 00647 // allocate jitter buffer 00648 if (bjitter) 00649 jitters = midx<t_jitter>(n); 00650 allocated = true; 00651 // alloc tally 00652 if (nclasses > 0) { 00653 add_tally = idx<intg>(nclasses); 00654 idx_clear(add_tally); 00655 } 00656 cout << "data matrix is " << data << endl; 00657 total_samples = n; 00658 return true; 00659 } 00660 00662 // data 00663 00664 template <class Tdata> 00665 bool dataset<Tdata>::add_data(midx<Tdata> &original_sample, 00666 const t_label label, 00667 const string *class_name, 00668 const char *filename, const rect<int> *r, 00669 pair<int,int> *center, 00670 const rect<int> *visr, 00671 const rect<int> *cropr, 00672 const vector<object*> *objs, 00673 const jitter *jittforce) { 00674 idx<Tdata> dat = original_sample.get(0); 00675 #ifdef __DEBUG__ 00676 cout << "Adding image " << dat << " with label " << label; 00677 if (class_name) cout << ", class name " << *class_name; 00678 if (r) cout << ", ROI " << *r; 00679 if (center) cout << ", center " << center->first << "," << center->second; 00680 cout << " from " << (filename?filename:"") << endl; 00681 #endif 00682 try { 00683 // check for errors 00684 if (!allocated && !strcmp(save_mode.c_str(), DATASET_SAVE)) 00685 eblthrow("dataset has not been allocated, cannot add data."); 00686 // check that input is bigger than minimum dimensions allowed 00687 if ((dat.dim(0) < mindims.dim(0)) 00688 || (r && (r->height < mindims.dim(0))) 00689 || (dat.dim(1) < mindims.dim(1)) 00690 || (r && (r->width < mindims.dim(1)))) { 00691 string err; 00692 err << "not adding " << *class_name << " from " 00693 << (filename?filename:"") 00694 << ": smaller than minimum dimensions (" << dat; 00695 if (r) 00696 err << " or " << *r; 00697 err << " is smaller than " << mindims << ")"; 00698 eblthrow(err); 00699 } 00700 // check that input is smaller than maximum dimensions allowed 00701 if (maxdims_set && r && (r->height > maxdims.dim(0) 00702 || r->width > maxdims.dim(1))) { 00703 string err; 00704 err << "not adding " << *class_name << " from " 00705 << (filename?filename:"") 00706 << ": bigger than maximum dimensions (" << *r 00707 << " is bigger than " << maxdims << ")"; 00708 eblthrow(err); 00709 } 00710 // check that class exists (may not exist if excluded) 00711 if (classes.size() > 0 && 00712 find(classes.begin(), classes.end(), *class_name) == classes.end()) 00713 eblthrow("not adding " << *class_name << " from " 00714 << (filename?filename:"") << ", this class is excluded."); 00715 // check that this class is included 00716 if (class_name && !included(*class_name)) 00717 eblthrow("not adding " << *class_name << " from " 00718 << (filename?filename:"") << ", this class is excluded."); 00719 00720 // do cropr if preprocessing is enabled. 00721 // you have to do this outside the jitter loop. 00722 if(do_preprocessing){ 00723 // crop it if cropr is defined 00724 if (cropr) { 00725 // input region 00726 idx<Tdata> dat_cropped = dat; 00727 dat_cropped = dat_cropped.narrow(0, cropr->height, cropr->h0); 00728 dat_cropped = dat_cropped.narrow(1, cropr->width, cropr->w0); 00729 dat = dat_cropped; 00730 original_sample.set(dat,0); 00731 } 00732 } 00733 // draw random jitter 00734 vector<jitter> jitt; 00735 if (njitter > 0 && !jittforce) { 00736 // draw last n random pairs 00737 for (uint i = 0; i < njitter; ++i) { 00738 if (random_jitter.size() == 0) // refill vector of random jitters 00739 this->compute_random_jitter(); 00740 if (random_jitter.size() == 0) // no jitter possible in this image 00741 break ; 00742 jitt.push_back(random_jitter.back()); 00743 random_jitter.pop_back(); 00744 } 00745 } else // no jitter 00746 // if (jitt.size() == 0) 00747 jitt.push_back(jitter(0,0,1.0,0.0)); // no jitter 00748 // add all jittered samples 00749 vector<jitter>::iterator ijit; 00750 for (ijit = jitt.begin(); ijit != jitt.end(); ++ijit) { 00751 // check for capacity 00752 if (full(label)) 00753 // if (!strcmp(save_mode.c_str(), DATASET_SAVE) && full(label)) 00754 // reached full capacity 00755 eblthrow("not adding " << *class_name << " from " 00756 << (filename?filename:"") 00757 << ", reached full capacity for this class."); 00758 // copy data into target type 00759 idxdim d(dat); 00760 rect<int> inr; 00761 // 00762 // do preprocessing 00763 midx<Tdata> sample; 00764 if (do_preprocessing) 00765 sample = preprocess_data(original_sample, class_name, filename, r, 0, 00766 NULL, center, &(*ijit), visr, cropr, &inr); 00767 else sample = original_sample; 00768 dat = original_sample.get(0); 00769 // ignore this sample if it is not visibile enough 00770 if (r && r->overlap_ratio(inr) < minvisibility) 00771 continue ; 00772 // remember all overlapping objects with current region 00773 idx<t_jitter> *js = NULL; 00774 rect<float> finr(inr.h0, inr.w0, inr.height, inr.width); 00775 finr = finr * (height / (float) inr.height); 00776 for (uint i = 0; objs && i < objs->size(); ++i) { 00777 const object &o = *(*objs)[i]; 00778 if (o.min_overlap(inr) >= minvisibility) { // overlaps, add box 00779 // scale box into sample's scale 00780 rect<float> fo(o.h0, o.w0, o.height, o.width); 00781 fo = fo * (height / (float) inr.height); 00782 // convert box to jitter in sample's coordinate system 00783 jitter jj(finr, fo, height); 00784 const idx<t_jitter> &tjj = jj.get_jitter_vector(); 00785 // add jitter 00786 if (!js) // allocate first time 00787 js = new idx<t_jitter>(1, tjj.dim(0)); 00788 else // increase size by 1 00789 js->resize1(0, js->dim(0) + 1); 00790 idx<t_jitter> e = js->select(0, js->dim(0) - 1); 00791 idx_copy(tjj, e); 00792 } 00793 } 00794 // add mirrors 00795 if (wmirror) { 00796 // flip data using vertical axis 00797 midx<Tdata> flipped = idx_flip(sample, 1); 00798 // flip horizontal jitter 00799 ijit->w = -ijit->w; 00800 idx<t_jitter> *jsmirr = NULL; 00801 if (js) { 00802 jsmirr = new idx<t_jitter>(js->get_idxdim()); 00803 idx_copy(*js, *jsmirr); 00804 idx<t_jitter> wj = jsmirr->select(1, 2); // select width component 00805 idx_minus(wj, wj); // negate all width components 00806 } 00807 cout << "(vertical-axis mirror) "; 00808 add_data2(flipped, label, class_name, filename, 00809 jittforce ? jittforce : &(*ijit), jsmirr); 00810 // display 00811 if (do_preprocessing) 00812 display_added(flipped, dat, class_name, filename, &inr, r, 00813 true, center, visr, cropr, objs, 00814 jittforce ? jittforce : &(*ijit), jsmirr); 00815 // put horizontal jitter back 00816 ijit->w = -ijit->w; 00817 // TEMPORARY MEMORY LEAK FIX (use smart srg pointer to clear 00818 // automatically on object deletion) 00819 flipped.clear(); 00820 } 00821 // add/save sample 00822 add_data2(sample, label, class_name, filename, 00823 jittforce ? jittforce : &(*ijit), js); 00824 // display 00825 if (do_preprocessing) 00826 display_added(sample, dat, class_name, filename, &inr, r, 00827 true, center, visr, cropr, objs, 00828 jittforce ? jittforce : &(*ijit), js); 00829 // delete temp objs 00830 if (js) delete js; 00831 // TEMPORARY MEMORY LEAK FIX (use smart srg pointer to clear 00832 // automatically on object deletion) 00833 sample.clear(); 00834 } 00835 return true; 00836 } catch(eblexception &e) { 00837 cerr << "warning: " << e << endl; 00838 return false; 00839 } 00840 } 00841 00842 template <class Tdata> 00843 void dataset<Tdata>::add_data2(midx<Tdata> &sample, t_label label, 00844 const string *class_name, 00845 const char *filename, const jitter *jitt, 00846 idx<t_jitter> *js) { 00847 add_label(label, class_name, filename, jitt, js); 00848 cout << endl; 00849 // check for dimensions 00850 idx<Tdata> sample0 = sample.get(0); 00851 if (!sample0.same_dim(outdims) && !no_outdims) { 00852 idxdim d2(sample0); 00853 d2.setdim(2, outdims.dim(2)); // try with same # of channels 00854 if (d2 == outdims) { 00855 // same size except for the channel dimension, replicate it 00856 cout << "duplicating image channel (" << sample0; 00857 cout << ") to fit target (" << outdims << ")." << endl; 00858 idx<Tdata> sample2(d2); 00859 idx_bloop2(samp2, sample2, Tdata, samp, sample0, Tdata) { 00860 idx_bloop2(s2, samp2, Tdata, s, samp, Tdata) { 00861 for (intg i = 0, j = 0; i < sample2.dim(2); ++i, ++j) { 00862 if (j >= sample0.dim(2)) 00863 j = 0; 00864 s2.set(s.get(j), i); 00865 } 00866 } 00867 } 00868 sample.set(sample2, 0); 00869 // TODO: apply replication to all layers of sample, not just 0 00870 } 00871 // else 00872 // eblthrow("expected data with dimensions " << outdims << " but found " 00873 // << sample0.get_idxdim() << " in " << filename); 00874 } 00875 // put sample's channels dimensions first, if interleaved. 00876 if (interleaved_input) 00877 sample.shift_dim_internal(2, 0); 00878 // if save_mode is dataset, cpy to dataset, otherwise save individual file 00879 // if (!strcmp(save_mode.c_str(), DATASET_SAVE)) { // dataset mode 00880 // // assign sample to big matrix 00881 // midx<Tdata> tgt = data.select(0, data_cnt); 00882 // for (uint i = 0; i < sample.dim(0); ++i) { 00883 // idx<Tdata> tmp = sample.get(i); 00884 // tgt.set(tmp, i); 00885 // } 00886 // // copy label 00887 // labels.set(label, data_cnt); 00888 // // copy jitt if present 00889 // if (jitters.order() > 0 && js) 00890 // jitters.set(*js, data_cnt); 00891 // } else { 00892 string format = save_mode; 00893 if (!strcmp(save_mode.c_str(), DYNSET_SAVE) 00894 || !strcmp(save_mode.c_str(), DATASET_SAVE)) 00895 format = "mat"; // force mat format for dynamic set 00896 string fname_tmp, fname; 00897 fname_tmp << outtmp << "/" << get_class_string(label) << "/"; 00898 if (individual_save) mkdir_full(fname_tmp.c_str()); 00899 // save image 00900 fname_tmp << get_class_string(label) << "_" << data_cnt; 00901 fname << fname_tmp << "." << format; 00902 // // scale image to 0 255 if preprocessed 00903 // if (strcmp(ppconv_type.c_str(), "RGB")) { 00904 // idx_addc(tmp, (Tdata) 1.0, tmp); 00905 // idx_dotc(tmp, (Tdata) 127.5, tmp); 00906 // } 00907 if (individual_save) { 00908 if (separate_layers_save && sample.dim(0) > 1) { 00909 for (uint i = 0; i < sample.dim(0); ++i) { 00910 string fname2; 00911 idx<Tdata> sample2 = sample.get(i); 00912 fname2 << fname_tmp << "_" << i << "." << format; 00913 save_image(fname2, sample2, format.c_str()); 00914 cout << " saved " << fname2 << " (" << sample2 << ")" << endl; 00915 } 00916 } else if (sample.dim(0) == 1) { 00917 idx<Tdata> tmp = sample.get(0); 00918 if (!strcmp(format.c_str(), "mat")) 00919 save_matrix(tmp, fname); 00920 else { 00921 tmp = tmp.shift_dim(0, 2); 00922 save_image(fname, tmp, format.c_str()); 00923 } 00924 cout << " saved " << fname << " (" << sample << ")" << endl; 00925 } else { 00926 if (!strcmp(format.c_str(), "mat")) { 00927 save_matrices(sample, fname); 00928 cout << " saved " << fname << " (" << sample << ")" << endl; 00929 } else 00930 eblerror("cannot save multi-layer image into format " << format); 00931 } 00932 } 00933 // if (!strcmp(save_mode.c_str(), DYNSET_SAVE)) { 00934 if (individual_save) // keep new path 00935 images_list.push_back(fname); // add image to files list 00936 else // keep original path 00937 images_list.push_back(filename); // add image to files list 00938 // } 00939 //} 00940 } 00941 00942 template <class Tdata> 00943 void dataset<Tdata>::add_label(t_label label, const string *class_name, 00944 const char *filename, const jitter *jitt, 00945 idx<t_jitter> *js) { 00946 string err; 00947 err << "not adding " << (class_name?*class_name:"sample") 00948 << " from " << (filename?filename:""); 00949 // check for capacity 00950 // if (!strcmp(save_mode.c_str(), DATASET_SAVE) && full(label)) 00951 if (full(label)) 00952 eblthrow(err << ", reached full capacity for this class."); 00953 if (!included(label)) 00954 eblthrow(err << ", class not included"); 00955 // increase counter for that class 00956 add_tally.set(add_tally.get(label) + 1, label); 00957 // print info 00958 cout << data_cnt+1 << " / " << total_samples << ": add "; 00959 cout << (filename ? filename : "sample" ); 00960 if (class_name) 00961 cout << " as " << *class_name; 00962 cout << " (" << label << ")"; 00963 // cout << " eta: " << xtimer.eta(processed_cnt, total_samples); 00964 cout << " eta: " << xtimer.eta(data_cnt+1, total_samples); 00965 cout << " elapsed: " << xtimer.elapsed(); 00966 if (jitt) 00967 cout << " (jitter " << jitt->h << "," << jitt->w << "," << jitt->s << "," 00968 << jitt->r << ")"; 00969 // copy label 00970 if (labels.dim(0) > data_cnt) 00971 labels.set(label, data_cnt); 00972 // increment data count 00973 data_cnt++; 00974 } 00975 00976 template <class Tdata> 00977 void dataset<Tdata>::display_added(midx<Tdata> &added, idx<Tdata> &original, 00978 const string *class_name, 00979 const char *filename, 00980 const rect<int> *inr, 00981 const rect<int> *origr, 00982 bool active_sleepd, 00983 pair<int,int> *center, 00984 const rect<int> *visr, 00985 const rect<int> *cropr, 00986 const vector<object*> *objs, 00987 const jitter *jitt, 00988 idx<t_jitter> *js, 00989 uint *woriginal) { 00990 // display each step 00991 #ifdef __GUI__ 00992 if (display_extraction) { 00993 disable_window_updates(); 00994 clear_window(); 00995 uint h = 0, w = 0; 00996 uint dh = 0, dw = 1; 00997 ostringstream oss; 00998 // display resized 00999 oss.str(""); 01000 h = 16; 01001 gui << gui_only() << black_on_white(); 01002 // // print output sizes 01003 // string ssizes; 01004 // for (uint i = 0; i < added.dim(0); ++i) { 01005 // idx<Tdata> tmp = added.get(i); 01006 // ssizes << tmp << " "; 01007 // } 01008 // gui << at(h, w) << ssizes; 01009 // h += 16; 01010 // // draw original output before channel formatting in RGB 01011 // oss.str(""); 01012 // oss << "RGB"; 01013 // draw_matrix(original, oss.str().c_str(), h, w); 01014 // h += original.dim(dh) + 5; 01015 Tdata minval, maxval; 01016 ppmods[0]->get_display_range(minval, maxval); 01017 // draw output in RGB 01018 // gui << at(h, w) << pp_names; h += 15; 01019 idx<Tdata> added0 = added.get(0); 01020 if ((added0.dim(0) == 3 || added0.dim(0) == 1) && fovea.size() == 0) { 01021 idx<Tdata> tmp = added0.shift_dim(0, 2); 01022 draw_matrix(tmp, h, w, 1, 1, minval, maxval); 01023 // draw crossing arrows at center 01024 draw_cross(h + tmp.dim(dh)/(float)2, w + tmp.dim(dw)/(float)2,10,0,0,0); 01025 // draw jitter boxes 01026 if (js) { 01027 idx_bloop1(jj, *js, t_jitter) { 01028 rect<float> jr(h + jj.get(1) * height, w + jj.get(2) * height, 01029 height, width); 01030 float scale = jj.get(0); 01031 scale = 1 / scale; 01032 jr.scale_centered(scale, scale); 01033 draw_box(jr.h0, jr.w0, jr.height, jr.width, 0, 0, 255); 01034 } 01035 } 01036 h += tmp.dim(dh) + 5; 01037 } 01038 // display all channels 01039 uint wtmp = w, maxw = 0, layers = 0, ppi = 0; 01040 for (uint i = 0; i < added.dim(0); ++i, layers++) { 01041 w = wtmp; 01042 string name; 01043 if (layers == ppmods[ppi]->nlayers()) { 01044 if (ppi < ppmods.size() - 1) 01045 ppi++; 01046 layers = 0; 01047 } 01048 if (layers == 0) { 01049 gui << at(h, w) << ppmods[ppi]->name(); 01050 h += 16; 01051 ppmods[ppi]->get_display_range(minval, maxval); 01052 } 01053 idx<Tdata> addedi = added.get(i); 01054 gui << at(h, w) << addedi; 01055 idx<Tdata> tmp = addedi.shift_dim(0, 2); 01056 w += 100; 01057 draw_matrix(tmp, h, w, 1, 1, minval, maxval); 01058 idx_bloop1(chan, addedi, Tdata) { 01059 w += addedi.dim(dw + 1) + 5; 01060 draw_matrix(chan, h, w, 1, 1, minval, maxval); 01061 // // display channel's center 01062 // draw_box(h + chan.dim(0) / 2 - 5, w + chan.dim(1) / 2 - 5, 10, 10, 01063 // 0, 0, 255); 01064 } 01065 w += addedi.dim(dw + 1) + 5; 01066 h += addedi.dim(dh + 1) + 5; 01067 maxw = std::max(maxw, w); 01068 } 01069 h = 0; 01070 w = maxw + 5; 01071 if (woriginal) 01072 *woriginal = w; 01073 // display original 01074 gui << gui_only() << black_on_white(); 01075 oss.str(""); 01076 if (filename) { 01077 oss << "file: " << filename; 01078 gui << gui_only() << black_on_white(); 01079 gui << at(h, w) << oss.str(); 01080 } 01081 h += 16; 01082 oss.str(""); 01083 oss << "adding sample #" << data_cnt+1 << " / " << total_samples; 01084 gui << at(h, w) << oss.str(); h += 16; 01085 string desc; 01086 desc << "input: " << original; 01087 if (jitt) 01088 desc << " jitter: spatial " << jitt->h << "x" << jitt->w 01089 << " scale " << jitt->s << " rot " << jitt->r; 01090 gui << at(h, w) << desc; h += 16; 01091 // if image was cropped, shift everything by cropping offsets 01092 if (cropr) { 01093 h += cropr->h0; 01094 w += cropr->w0; 01095 } 01096 // draw image 01097 draw_matrix(original, h, w); 01098 // draw object's center 01099 if (center) 01100 draw_cross(h + center->second, w + center->first, 10, 0, 0, 255); 01101 // draw all objects in picture 01102 if (objs) { 01103 for (uint i = 0; i < objs->size(); ++i) { 01104 const object &o = *(*objs)[i]; 01105 if (o.ignored) // ignored object 01106 draw_box(h + o.h0, w + o.w0, o.height, o.width, 255, 255, 0); 01107 else // used object 01108 draw_box(h + o.h0, w + o.w0, o.height, o.width, 0, 255, 255); 01109 } 01110 } 01111 // draw object's original box 01112 if (origr) { 01113 draw_box(h + origr->h0, w + origr->w0, origr->height, origr->width, 01114 255, 0, 0); 01115 draw_cross(h + origr->hcenter(), w + origr->wcenter(), 20, 255, 0, 0); 01116 } 01117 // draw object's factored box if factor != 1.0 01118 if (inr) { 01119 draw_box(h + inr->h0, w + inr->w0, inr->height, inr->width, 0, 255, 0); 01120 draw_cross(h + inr->hcenter(), w + inr->wcenter(), 20, 0, 255, 0); 01121 } 01122 // draw all 01123 for (uint i = 0; i < ppmods.size(); ++i) { 01124 resizepp_module<fs(Tdata)> *resizepp = ppmods[i]; 01125 const vector<rect<int> > &boxes = resizepp->get_input_bboxes(); 01126 for (uint i = 0; i < boxes.size(); ++i) { 01127 const rect<int> &b = boxes[i]; 01128 draw_box(h + b.h0, w + b.w0, b.height, b.width, 255, 0, 255); 01129 } 01130 } 01131 // draw object's label 01132 if (class_name && inr) 01133 gui << white_on_transparent() << at(h + inr->h0, w + inr->w0) 01134 << *class_name; 01135 // draw object's visible area if presnet 01136 if (visr) 01137 draw_box(h + visr->h0, w + visr->w0, visr->height, visr->width, 01138 0, 0, 255); 01139 //h += dat.dim(dh) + 5; 01140 w += original.dim(dw) + 5; 01141 oss.str(""); 01142 // display object 01143 if (inr) { 01144 idx<Tdata> obj = original; 01145 int offh = std::max((int)0, inr->h0); 01146 int offw = std::max((int)0, inr->w0); 01147 obj = obj.narrow(dh, std::min((int)obj.dim(0) - offh, inr->height), offh); 01148 obj = obj.narrow(dw, std::min((int)obj.dim(1) - offw, inr->width), offw); 01149 // display object 01150 if (class_name) 01151 oss << *class_name << " "; 01152 oss << obj; 01153 draw_matrix(obj, oss.str().c_str(), h, w); 01154 // draw crossing arrows at center 01155 // draw_box(h + inr.height/2, w + inr.width/2, inr.height/2, 01156 // inr.width/2, 0,0,0); 01157 // gui << black_on_white() << at(h + inr.height, w) << oss.str(); 01158 } 01159 // paint 01160 enable_window_updates(); 01161 if (sleep_display && active_sleepd) 01162 millisleep((long) sleep_delay); 01163 if (bsave_display) { 01164 ostringstream oss(""); 01165 oss << save_display_dir << "frame" << setw(6) << setfill('0') 01166 << data_cnt; 01167 save_window(oss.str().c_str()); 01168 } 01169 } 01170 #endif 01171 } 01172 01173 template <class Tdata> 01174 void dataset<Tdata>::set_unique_label(const string &class_name) { 01175 // allocate labels matrix based on images list size 01176 if (labels.order() != 1 && images_list.size() > 0) 01177 labels = idx<t_label>(images_list.size()); 01178 idx_clear(labels); 01179 clear_classes(); 01180 add_class(class_name); 01181 } 01182 01183 template <class Tdata> 01184 void dataset<Tdata>::clear_classes() { 01185 nclasses = 0; 01186 classes.clear(); 01187 } 01188 01189 template <class Tdata> 01190 bool dataset<Tdata>::add_class(const string &class_name) { 01191 vector<string>::iterator res; 01192 string name = class_name; 01193 res = find(classes.begin(), classes.end(), name); 01194 if (res == classes.end()) {// not found 01195 classes.push_back(name); 01196 nclasses++; 01197 } else { // found 01198 //t_label i = res - classes.begin(); 01199 // cout << "found class " << name << " at index " << i << endl; 01200 } 01201 // sort all classes 01202 std::sort(classes.begin(), classes.end(), natural_compare_less); 01203 return true; 01204 } 01205 01206 template <class Tdata> 01207 void dataset<Tdata>::set_classes(idx<ubyte> &classidx) { 01208 // add classes to each dataset 01209 string s; 01210 idx_bloop1(classe, classidx, ubyte) { 01211 s = (const char *) classe.idx_ptr(); 01212 add_class(s); 01213 } 01214 // init max_per_class 01215 max_per_class = idx<intg>(classes.size()); 01216 max_per_class_set = false; 01217 idx_fill(max_per_class, (numeric_limits<intg>::max)()); 01218 } 01219 01220 template <class Tdata> 01221 void dataset<Tdata>::set_outdims(const idxdim &d) { 01222 no_outdims = false; 01223 outdims = d; 01224 uint featdims = 0; 01225 if (interleaved_input || (outdims.order() == 2)) { 01226 height = outdims.dim(0); 01227 width = outdims.dim(1); 01228 featdims = 2; 01229 } else { 01230 height = outdims.dim(1); 01231 width = outdims.dim(2); 01232 featdims = 0; 01233 } 01234 // update outdims' feature size with fovea factor 01235 if (outdims.order() > 0 && fovea.size() > 0) 01236 outdims.setdim(featdims, outdims.dim(featdims) * fovea.size()); 01237 cout << "Setting target dimensions to " << outdims << endl; 01238 } 01239 01240 template <class Tdata> 01241 void dataset<Tdata>::set_outdir(const char *s, const char *tmp) { 01242 outdir = s; 01243 if (tmp) 01244 outtmp = tmp; 01245 if (outtmp.empty()) 01246 outtmp = outdir; 01247 cout << "Setting output directory to " << outdir << endl; 01248 cout << "Setting temporary output directory to " << outtmp << endl; 01249 } 01250 01251 template <class Tdata> 01252 void dataset<Tdata>::set_mindims(const idxdim &d) { 01253 cout << "Setting minimum input dimensions to " << d << endl; 01254 mindims = d; 01255 } 01256 01257 template <class Tdata> 01258 void dataset<Tdata>::set_maxdims(const idxdim &d) { 01259 cout << "Setting maximum input dimensions to " << d << endl; 01260 maxdims = d; 01261 maxdims_set = true; 01262 } 01263 01264 template <class Tdata> 01265 void dataset<Tdata>::set_scales(const vector<double> &sc, const string &od) { 01266 scales = sc; 01267 scale_mode = true; 01268 outtmp = od; 01269 cout << "Enabling scaling mode. Scales: "; 01270 for (vector<double>::iterator i = scales.begin(); i != scales.end(); ++i) 01271 cout << *i << " "; 01272 cout << endl; 01273 } 01274 01275 template <class Tdata> 01276 void dataset<Tdata>::set_fovea(const vector<double> &sc) { 01277 fovea = sc; 01278 cout << "Enabling fovea mode with scales: " << fovea << endl; 01279 // set the number of layers the pyramid will produce 01280 //HERE 01281 nlayers = fovea.size(); 01282 // update outdims' feature size 01283 set_outdims(outdims); 01284 } 01285 01286 template <class Tdata> 01287 void dataset<Tdata>::set_max_per_class(intg max) { 01288 if (max < 0) 01289 eblerror("cannot set max_per_class to < 0"); 01290 if (max > 0) { 01291 mpc = max; 01292 max_per_class_set = true; 01293 max_per_class = idx<intg>(nclasses); 01294 idx_fill(max_per_class, mpc); 01295 cout << "Max number of samples per class: " << max << endl; 01296 } 01297 } 01298 01299 template <class Tdata> 01300 void dataset<Tdata>::set_max_data(intg max) { 01301 if (max < 0) 01302 eblerror("cannot set max_data to < 0"); 01303 if (max > 0) { 01304 max_data = max; 01305 max_data_set = true; 01306 cout << "Max number of samples: " << max << endl; 01307 } 01308 } 01309 01310 template <class Tdata> 01311 void dataset<Tdata>::set_image_pattern(const string &p) { 01312 extension = p; 01313 cout << "Setting image pattern to " << extension << endl; 01314 } 01315 01316 template <class Tdata> 01317 void dataset<Tdata>::set_exclude(const vector<string> &ex) { 01318 if (ex.size()) { 01319 cout << "Excluded class(es): "; 01320 for (vector<string>::const_iterator i = ex.begin(); i != ex.end(); ++i) { 01321 exclude.push_back(*i); 01322 if (i != ex.begin()) cout << ","; 01323 cout << " " << *i; 01324 } 01325 cout << endl; 01326 } 01327 } 01328 01329 template <class Tdata> 01330 void dataset<Tdata>::set_include(const vector<string> &inc) { 01331 if (inc.size()) { 01332 cout << "Included class(es): "; 01333 for (vector<string>::const_iterator i = inc.begin(); i != inc.end(); ++i){ 01334 include.push_back(*i); 01335 if (i != inc.begin()) cout << ","; 01336 cout << " " << *i; 01337 } 01338 cout << endl; 01339 } 01340 } 01341 01342 template <class Tdata> 01343 void dataset<Tdata>::set_save(const string &s) { 01344 save_mode = s; 01345 cout << "Setting saving mode to: " << save_mode << endl; 01346 } 01347 01348 template <class Tdata> 01349 void dataset<Tdata>::set_individual_save(bool b) { 01350 individual_save = b; 01351 cout << (individual_save ? "Enabling" : "Disabling") 01352 << " individual sample saving." << endl; 01353 } 01354 01355 template <class Tdata> 01356 void dataset<Tdata>::set_separate_layers_save(bool b) { 01357 separate_layers_save = b; 01358 cout << (separate_layers_save ? "Enabling" : "Disabling") 01359 << " saving sample layers separately." << endl; 01360 } 01361 01362 template <class Tdata> 01363 void dataset<Tdata>::set_name(const string &s) { 01364 name = s; 01365 build_fname(name, DATA_NAME, data_fname); 01366 build_fname(name, LABELS_NAME, labels_fname); 01367 build_fname(name, SCALES_NAME, ids_fname); 01368 build_fname(name, JITTERS_NAME, jitters_fname); 01369 build_fname(name, CLASSES_NAME, classes_fname); 01370 build_fname(name, CLASSPAIRS_NAME, classpairs_fname); 01371 build_fname(name, DEFORMPAIRS_NAME, deformpairs_fname); 01372 cout << "Setting dataset name to: " << name << endl; 01373 } 01374 01375 template <class Tdata> 01376 void dataset<Tdata>::set_label(const string &s) { 01377 force_label = s; 01378 //add_class(force_label); 01379 cout << "Forcing label for all samples to: " << s << endl; 01380 } 01381 01382 template <class Tdata> 01383 void dataset<Tdata>::set_bbox_woverh(float factor) { 01384 bbox_woverh = factor; 01385 cout << "Forcing width to be h * " << bbox_woverh << endl; 01386 } 01387 01388 template <class Tdata> 01389 void dataset<Tdata>::set_nopadded(bool nopadded_) { 01390 nopadded = nopadded_; 01391 if (nopadded) 01392 cout << "Ignoring samples that have padding areas, i.e. too" 01393 << " small for target size." << endl; 01394 } 01395 template <class Tdata> 01396 void dataset<Tdata>::set_videobox(uint nframes, uint stride) { 01397 do_videobox = true; 01398 videobox_nframes = nframes; 01399 videobox_stride = stride; 01400 } 01401 01402 template <class Tdata> 01403 void dataset<Tdata>:: 01404 set_jitter(uint tjitter_step_, uint tjitter_hmin_, uint tjitter_hmax_, 01405 uint tjitter_wmin_, uint tjitter_wmax_, uint scale_steps, 01406 float scale_min, float scale_max, uint rotation_steps, 01407 float rotation_range, uint n) { 01408 bjitter = true; 01409 tjitter_step = (int) tjitter_step_; 01410 tjitter_hmin = (int) tjitter_hmin_; 01411 tjitter_hmax = (int) tjitter_hmax_; 01412 tjitter_wmin = (int) tjitter_wmin_; 01413 tjitter_wmax = (int) tjitter_wmax_; 01414 sjitter_steps = (int) scale_steps; 01415 sjitter_min = scale_min; 01416 sjitter_max = scale_max; 01417 if (sjitter_min > sjitter_max) 01418 eblerror("expected max > min but got " << sjitter_max << " < " 01419 << sjitter_min); 01420 rjitter_steps = (int) rotation_steps; 01421 rjitter = rotation_range; 01422 njitter = n; 01423 cout << "Adding " << n << " samples randomly jittered in a neighborhood " 01424 << " with height range (" << tjitter_hmin 01425 << "," << tjitter_hmax << "), width range (" << tjitter_wmin 01426 << "," << tjitter_wmax << ") and step " << tjitter_step << ", over " 01427 << scale_steps << " scales" 01428 << " within a [" << scale_min << "," << scale_max 01429 << "] scale range and " 01430 << rjitter_steps << " rotations within a " << rjitter 01431 << " degrees rotation range around original location" 01432 << "/scale/orientation" << endl; 01433 } 01434 01435 template <class Tdata> 01436 void dataset<Tdata>::set_minvisibility(float minvis) { 01437 cout << "Setting minimum visibility ratio (visible bbox overlap with " 01438 << "original bbox) to " << minvis << endl; 01439 minvisibility = minvis; 01440 } 01441 01442 template <class Tdata> 01443 void dataset<Tdata>::set_wmirror() { 01444 wmirror = true; 01445 cout << "Adding vertical-axis mirror." << endl; 01446 } 01447 01448 template <class Tdata> 01449 void dataset<Tdata>::save_display(const string &dir, uint h, uint w) { 01450 #ifdef __GUI__ 01451 bsave_display = true; 01452 save_display_dir = dir; 01453 save_display_dir << "/"; 01454 mkdir_full(dir.c_str()); 01455 cout << "Saving display frames "; 01456 if (h != 0 && w != 0) { 01457 freeze_window_size(h, w); 01458 cout << "(fixed size: " << h << "x" << w << ") "; 01459 } 01460 cout << "to " << dir << endl; 01461 #endif 01462 } 01463 01464 template <class Tdata> 01465 void dataset<Tdata>::use_pose() { 01466 usepose = true; 01467 cout << "Using pose to separate classes." << endl; 01468 } 01469 01470 template <class Tdata> 01471 void dataset<Tdata>::use_parts() { 01472 useparts = true; 01473 cout << "Extracting parts." << endl; 01474 } 01475 01476 template <class Tdata> 01477 void dataset<Tdata>::use_parts_only() { 01478 usepartsonly = true; 01479 cout << "Extracting parts only." << endl; 01480 } 01481 01482 template <class Tdata> 01483 intg dataset<Tdata>::count_total() { 01484 // count samples 01485 this->count_samples(); 01486 cout << "Found: " << total_samples << " total samples." << endl; 01487 if (!total_samples) eblerror("no samples found"); 01488 if (njitter > 0) { 01489 total_samples *= njitter; 01490 cout << "Jitter is on with " << njitter << " jitters per sample, " 01491 << "bringing total samples to " << total_samples << endl; 01492 } 01493 if (wmirror) { 01494 total_samples *= 2; 01495 cout << "Vertical-axis mirroring is on, " 01496 << "bringing total samples to " << total_samples << endl; 01497 } 01498 return total_samples; 01499 } 01500 01501 template <class Tdata> 01502 intg dataset<Tdata>::count_samples() { 01503 #ifdef __BOOST__ 01504 cout << "Counting number of samples in " << inroot << " ..." << endl; 01505 total_samples = 0; 01506 regex hidden_dir(".svn"); 01507 cmatch what; 01508 directory_iterator end_itr; // default construction yields past-the-end 01509 path p(inroot); 01510 if (!exists(p)) eblthrow("path " << inroot << " does not exist."); 01511 // loop over all directories 01512 std::vector<std::string> dirs; 01513 for (directory_iterator itr(inroot); itr != end_itr; itr++) { 01514 #if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 01515 if (is_directory(itr->status()) 01516 && !regex_match(itr->leaf().c_str(), what, hidden_dir)) { 01517 // ignore excluded classes and use included if defined 01518 if (included(itr->leaf())) { 01519 dirs.push_back(itr->leaf()); 01520 #else 01521 if (is_directory(itr->status()) 01522 && !regex_match(itr->path().filename().c_str(), what, hidden_dir)) { 01523 // ignore excluded classes and use included if defined 01524 if (included(itr->path().filename())) { 01525 dirs.push_back(itr->path().filename().c_str()); 01526 #endif 01527 // recursively search each directory 01528 total_samples += count_matches(itr->path().string(), extension); 01529 } 01530 } 01531 } 01532 // sort directories 01533 std::sort(dirs.begin(), dirs.end(), natural_compare_less); 01534 // process subdirs to extract images into the single image idx 01535 for (uint i = 0; i < dirs.size(); ++i) { 01536 // add directory as new class 01537 add_class(dirs[i]); 01538 } 01539 #endif /* __BOOST__ */ 01540 return total_samples; 01541 } 01542 01543 template <class Tdata> 01544 void dataset<Tdata>::split(dataset<Tdata> &ds1, dataset<Tdata> &ds2) { 01545 // data already preprocessed 01546 ds1.do_preprocessing = false; 01547 ds2.do_preprocessing = false; 01548 ds1.interleaved_input = false; 01549 ds2.interleaved_input = false; 01550 // enable jitter in target if present here 01551 bjitter = (jitters.order() > 0); 01552 if (bjitter) { 01553 ds1.bjitter = true; 01554 ds2.bjitter = true; 01555 } 01556 cout << "Input data samples: " << data << endl; 01557 // alloc each dataset 01558 if (!ds1.allocate(data.dim(0), outdims) || 01559 !ds2.allocate(data.dim(0), outdims)) 01560 eblerror("Failed to allocate new datasets"); 01561 // add samples 1st dataset, if not add to 2nd. 01562 // if 1st has reached max per class, it will return false upon addition 01563 cout << "Adding data to \"" << ds1.name << "\" and \"" << ds2.name << "\"."; 01564 cout << endl; 01565 // using the shuffle() method is a problem with big datasets because 01566 // it requires allocation of an extra dataset. 01567 // instead, we use a random list of indices to assign the first random 01568 // samples to dataset 1 and the remaining to dataset 2. 01569 vector<intg> ids; 01570 idx<t_jitter> jitt; 01571 t_label label; 01572 // prepare offset matrices 01573 idx<int64> offsets = data.get_offsets(); 01574 idx<int64> off1(offsets.get_idxdim()), off2(offsets.get_idxdim()); 01575 idx_clear(off1); 01576 idx_clear(off2); 01577 // init timers 01578 ds1.xtimer.start(); 01579 ds2.xtimer.start(); 01580 // loop on all samples 01581 for (intg i = 0; i < data.dim(0); ++i) ids.push_back(i); 01582 random_shuffle(ids.begin(), ids.end()); 01583 for (vector<intg>::iterator i = ids.begin(); i != ids.end(); ++i) { 01584 label = labels.get(*i); 01585 string &class_name = classes[(size_t)label]; 01586 cout << "(original index " << *i << ") "; 01587 // adding to ds1 01588 try { 01589 intg cnt = ds1.data_cnt; 01590 ds1.add_label(label, &class_name, NULL, NULL, NULL); 01591 cout << " (dataset 1)" << endl; 01592 // copy offsets 01593 idx<int64> offs = offsets[*i]; 01594 idx<int64> offss = off1[cnt]; 01595 idx_copy(offs, offss); 01596 if (bjitter && jitters.exists(*i)) { 01597 jitt = jitters.get(*i); 01598 ds1.jitters.set(jitt, cnt); 01599 } 01600 } catch(eblexception &e) { // adding to ds2 01601 try { 01602 intg cnt = ds2.data_cnt; 01603 ds2.add_label(label, &class_name, NULL, NULL, NULL); 01604 cout << " (dataset 2), not 1:" << e << endl; 01605 // copy offsets 01606 idx<int64> offs = offsets[*i]; 01607 idx<int64> offss = off2[cnt]; 01608 idx_copy(offs, offss); 01609 if (bjitter && jitters.exists(*i)) { 01610 jitt = jitters.get(*i); 01611 ds2.jitters.set(jitt, cnt); 01612 } 01613 } catch(eblexception &e) { 01614 cerr << "failed adding sample: " << e << endl; 01615 } 01616 } 01617 } 01618 // set data matrices from original data and offset matrices 01619 // ds1.data_cnt = idx_sum(ds1.add_tally); 01620 // ds2.data_cnt = idx_sum(ds2.add_tally); 01621 if (off1.order() == 1) { 01622 off1.resize(ds1.data_cnt); 01623 off2.resize(ds2.data_cnt); 01624 } 01625 else { 01626 off1.resize(ds1.data_cnt, off1.dim(1)); 01627 off2.resize(ds2.data_cnt, off2.dim(1)); 01628 } 01629 ds1.data = midx<Tdata>(off1.get_idxdim(), data.get_file_pointer(), &off1); 01630 ds2.data = midx<Tdata>(off2.get_idxdim(), data.get_file_pointer(), &off2); 01631 01632 print_stats(); 01633 ds1.print_stats(); 01634 ds2.print_stats(); 01635 } 01636 01637 template <class Tdata> 01638 void dataset<Tdata>::merge_and_save(const char *name1, const char *name2, 01639 const string &outroot) { 01640 dataset<Tdata> ds1(name1), ds2(name2); 01641 string inroot1 = ebl::dirname(name1); 01642 string inroot2 = ebl::dirname(name2); 01643 // load 2 datasets 01644 ds1.load(inroot1); 01645 ds2.load(inroot2); 01646 if (ds1.jitters.order() > 0 || ds2.jitters.order() > 0) { 01647 njitter = 1; // enable jitter allocation/saving 01648 bjitter = true; 01649 } 01650 interleaved_input = false; 01651 intg newsz = ds1.size() + ds2.size(); 01652 idxdim d1 = ds1.get_sample_outdim(), d2 = ds2.get_sample_outdim(); 01653 if (!(d1 == d2)) 01654 eblwarn("sample sizes for dataset 1 and 2 are different: " 01655 << d1 << " and " << d2); 01656 // allocate new dataset 01657 allocate(newsz, d1); 01658 idx<t_label> labelsnew; 01659 idx<intg> idsnew; 01660 midx<t_jitter> jittnew; 01661 // clear jitters, in case a dataset doesn't have any 01662 idx_clear(jitters); 01663 // update classes 01664 idx<ubyte> classidx = ds1.build_classes_idx(ds1.classes); 01665 set_classes(classidx); // initialize with ds1's class names 01666 cout << "Added all classes to new dataset from " << ds1.name << endl; 01667 // for each ds2 class name, push on new class names vector if not found 01668 vector<string>::iterator res, i; 01669 for (i = ds2.classes.begin(); i != ds2.classes.end(); ++i){ 01670 res = find(classes.begin(), classes.end(), *i); 01671 if (res == classes.end()) { // not found 01672 classes.push_back(*i); // add new class name 01673 nclasses++; 01674 cout << "Adding class " << *i << " from dataset " << ds2.name << endl; 01675 } 01676 } 01677 // update each ds2 label based on new class numbering 01678 idx_bloop1(lab, ds2.labels, t_label) { 01679 string s = ds2.get_class_string(lab.get()); 01680 lab.set(get_class_id(s)); 01681 } 01682 // copy data 1 into new dataset 01683 labelsnew = labels.narrow(0, ds1.size(), 0); 01684 idx_copy(ds1.labels, labelsnew); 01685 idsnew = ids.narrow(0, ds1.size(), 0); 01686 idx_copy(ds1.ids, idsnew); 01687 if (bjitter) 01688 jittnew = jitters.narrow(0, ds1.size(), 0); 01689 if (ds1.jitters.order() > 0) 01690 for (uint i = 0; i < ds1.jitters.dim(0); ++i) { 01691 if (ds1.jitters.exists(i)) { 01692 idx<t_jitter> tmp = ds1.jitters.get(i); 01693 jittnew.set(tmp, i); 01694 } 01695 } 01696 // copy data 2 into new dataset 01697 labelsnew = labels.narrow(0, ds2.size(), ds1.size()); 01698 idx_copy(ds2.labels, labelsnew); 01699 idsnew = ids.narrow(0, ds2.size(), ds1.size()); 01700 idx_copy(ds2.ids, idsnew); 01701 if (bjitter) 01702 jittnew = jitters.narrow(0, ds2.size(), ds1.size()); 01703 if (ds2.jitters.order() > 0) 01704 for (uint i = 0; i < ds2.jitters.dim(0); ++i) { 01705 if (ds2.jitters.exists(i)) { 01706 idx<t_jitter> tmp = ds2.jitters.get(i); 01707 jittnew.set(tmp, i); 01708 } 01709 } 01710 // update counter 01711 data_cnt = newsz; 01712 cout << "Copied data from " << ds1.name << " and " << ds2.name; 01713 cout << " into new dataset." << endl; 01714 // print info 01715 print_stats(); 01716 // save data 01717 string fname, fname_tmp; 01718 fname << outroot << "/" << data_fname; 01719 fname_tmp << fname << "_tmp"; 01720 mkdir_full(outroot.c_str()); 01721 cout << "Saving " << fname << endl; 01722 save_matrices(ds1.data, ds2.data, fname_tmp); 01723 if (!mv_file(fname_tmp.c_str(), fname.c_str())) 01724 eblerror("failed to move " << fname_tmp << " to " << fname); 01725 // move from tmp to target name 01726 cout << "Saving dataset in " << outroot << endl; 01727 // save rest 01728 save(outroot, false); 01729 } 01730 01731 template <class Tdata> template <class Toriginal> 01732 bool dataset<Tdata>::save_scales(idx<Toriginal> &dat, const string &filename){ 01733 // copy data into target type 01734 idxdim d(dat); 01735 idx<Tdata> sample(d); 01736 idx_copy(dat, sample); 01737 // do preprocessing for each scale, then save image 01738 ostringstream base_name, ofname; 01739 base_name << outtmp << "/" << filename << "_scale"; 01740 string class_name = "noclass"; 01741 for (vector<double>::iterator i = scales.begin(); i != scales.end(); ++i) { 01742 idx<Tdata> s = preprocess_data(sample, &class_name, 01743 filename.c_str(), NULL, *i); 01744 // put sample's channels dimensions first, if defined. 01745 //s = s.shift_dim(2, 0); 01746 // save image 01747 ofname.str(""); ofname << base_name.str() << *i << ".mat"; 01748 if (save_matrix(s, ofname.str())) { 01749 cout << data_cnt++ << ": saved " << ofname.str(); 01750 cout << "(" << s << ")" << endl; 01751 } 01752 } 01753 return true; 01754 } 01755 01756 template <class Tdata> 01757 bool dataset<Tdata>::included(t_label &lab) { 01758 if (classes.size() == 0) return false; 01759 if ((size_t) lab >= classes.size()) return false; 01760 string &class_name = classes[(size_t)lab]; 01761 if (!included(class_name)) return false; 01762 return true; 01763 } 01764 01765 template <class Tdata> 01766 bool dataset<Tdata>::included(const string &class_name) { 01767 return // is not excluded 01768 find(exclude.begin(), exclude.end(), class_name) == exclude.end() 01769 // and is included 01770 && ((find(include.begin(), include.end(), class_name) != include.end()) 01771 // or everything is included 01772 || (include.size() == 0)); 01773 } 01774 01776 // data preprocessing 01777 01778 template <class Tdata> 01779 midx<Tdata> dataset<Tdata>:: 01780 preprocess_data(midx<Tdata> &dat, const string *class_name, 01781 const char *filename, const rect<int> *r, double scale, 01782 rect<int> *outr, 01783 pair<int,int> *center, jitter *jitt, 01784 const rect<int> *visr, 01785 const rect<int> *cropr, 01786 rect<int> *inr_out) { 01787 // input region 01788 idx<Tdata> dat0 = dat.get(0); 01789 01790 rect<int> inr(0, 0, dat0.dim(0), dat0.dim(1)); 01791 if (r) inr = *r; 01792 // force width to be h * bbox_woverh 01793 if (bbox_woverh > 0) 01794 inr.scale_width(bbox_woverh); 01795 // resize image to target dims 01796 rect<int> out_region, cropped; 01797 idxdim d(outdims); 01798 // input data 01799 idx<Tdata> tmp = dat0.shift_dim(2, 0); 01800 fstate_idx<Tdata> in(tmp.get_idxdim()); 01801 // allocate sample with videobox options in mind 01802 midx<Tdata> sample(nlayers * (1 + videobox_nframes)); 01803 uint nadded = 0; 01804 string next_file = filename; 01805 for(uint i = 0; i < videobox_nframes + 1; ++i) { 01806 //copy the current image into in.x 01807 idx_copy(tmp, in.x); 01808 // loop on all preprocessing modules 01809 for (uint i = 0; i < ppmods.size(); ++i) { 01810 resizepp_module<fs(Tdata)> *resizepp = ppmods[i]; 01811 midx<Tdata> sampletmp(resizepp->nlayers()); 01812 // add jitter 01813 if (jitt) 01814 resizepp->set_jitter((int)jitt->h, (int)jitt->w, jitt->s, jitt->r); 01815 if (scale > 0) // resize entire image at specific scale 01816 resizepp->set_dimensions((uint) (outdims.dim(0) * scale), 01817 (uint) (outdims.dim(1) * scale)); 01818 resizepp->set_input_region(inr); 01819 // actual preprocessing 01820 resizepp->fprop(in, sampletmp); 01821 // remember bbox of original image in resized image 01822 original_bbox = resizepp->get_original_bbox(); 01823 if (outr) 01824 *outr = original_bbox; 01825 if (inr_out) 01826 *inr_out = resizepp->get_input_bbox(); 01827 for (uint j = 0; j < sampletmp.dim(0); ++j) { 01828 idx<Tdata> stmp = sampletmp.get(j); 01829 sample.set(stmp, j + nadded); 01830 } 01831 nadded += resizepp->nlayers(); 01832 } 01833 if (do_videobox) { 01834 // Load the next image into tmp 01835 load_img.clear(); 01836 // if file doesn't exist, load_data automatically throws exception 01837 // which makes the sample to be not added 01838 next_file = ebl::increment_filename(next_file.c_str(), videobox_stride); 01839 load_data(next_file); 01840 dat0 = load_img.get(0); 01841 if (cropr) { 01842 dat0 = dat0.narrow(0, cropr->height, cropr->h0); 01843 dat0 = dat0.narrow(1, cropr->width, cropr->w0); 01844 } 01845 dat0.shift_dim(2, 0); 01846 tmp = dat0.shift_dim(2, 0); 01847 } 01848 } 01849 sample.shift_dim_internal(0, 2); 01850 // return preprocessed image 01851 return sample; 01852 } 01853 01855 // Helper functions 01856 01857 template <class Tdata> 01858 void dataset<Tdata>::compute_stats() { 01859 // collect stats 01860 if (nclasses > 0) { 01861 class_tally = idx<intg>(nclasses); 01862 idx_clear(class_tally); 01863 for (intg i = 0; i < data_cnt && i < labels.dim(0); ++i) { 01864 class_tally.set(class_tally.get(labels.get(i)) + 1, 01865 (intg) labels.get(i)); 01866 } 01867 } 01868 } 01869 01870 template <class Tdata> 01871 idx<ubyte> dataset<Tdata>::build_classes_idx(vector<string> &classes) { 01872 // determine max length of strings 01873 uint max = 0; 01874 vector<string>::iterator i = classes.begin(); 01875 for ( ; i != classes.end(); ++i) 01876 max = (std::max)((size_t) max, i->length()); 01877 // allocate classes idx 01878 idx<ubyte> classes_idx(classes.size(), max + 1); 01879 // copy classes strings 01880 idx_clear(classes_idx); 01881 idx<ubyte> tmp; 01882 for (i = classes.begin(); i != classes.end(); ++i) { 01883 tmp = classes_idx.select(0, i - classes.begin()); 01884 memcpy(tmp.idx_ptr(), i->c_str(), i->length() * sizeof (ubyte)); 01885 } 01886 return classes_idx; 01887 } 01888 01889 template <class Tdata> 01890 string& dataset<Tdata>::get_class_string(t_label id) { 01891 if (((int) id < 0) || ((uint) id >= classes.size())) 01892 eblerror("trying to access a class with wrong id."); 01893 return classes[id]; 01894 } 01895 01896 template <class Tdata> 01897 t_label dataset<Tdata>::get_class_id(const string &name) { 01898 vector<string>::iterator res; 01899 res = find(classes.begin(), classes.end(), name); 01900 if (res == classes.end()) // not found 01901 eblerror("class not found"); 01902 return (t_label) (res - classes.begin()); 01903 } 01904 01905 // Recursively goes through dir, looking for files matching extension ext. 01906 template <class Tdata> 01907 uint dataset<Tdata>::count_matches(const string &dir, const string &pattern) { 01908 uint total = 0; 01909 #ifdef __BOOST__ 01910 regex eExt(pattern); 01911 cmatch what; 01912 path p(dir); 01913 if (!exists(p)) 01914 return 0; 01915 directory_iterator end_itr; // default construction yields past-the-end 01916 for (directory_iterator itr(p); itr != end_itr; ++itr) { 01917 if (is_directory(itr->status())) 01918 total += count_matches(itr->path().string(), pattern); 01919 #if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 01920 else if (regex_match(itr->leaf().c_str(), what, eExt)) 01921 #else 01922 else if (regex_match(itr->path().filename().c_str(), what, eExt)) 01923 #endif 01924 total++; 01925 } 01926 #endif /* __BOOST__ */ 01927 return total; 01928 } 01929 01930 template <class Tdata> 01931 void dataset<Tdata>::process_dir(const string &dir, const string &ext, 01932 const string &class_name_) { 01933 #ifdef __BOOST__ 01934 string class_name = class_name_; 01935 t_label label = get_label_from_class(class_name); 01936 cmatch what; 01937 regex r(ext); 01938 path p(dir); 01939 if (!exists(p)) 01940 return ; 01941 directory_iterator end_itr; // default construction yields past-the-end 01942 for (directory_iterator itr(p); itr != end_itr; ++itr) { 01943 if (is_directory(itr->status())) 01944 process_dir(itr->path().string(), ext, class_name); 01945 #if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 01946 else if (regex_match(itr->leaf().c_str(), what, r)) { 01947 #else 01948 else if (regex_match(itr->path().filename().c_str(), what, r)) { 01949 #endif 01950 try { 01951 processed_cnt++; 01952 // if full for this class, skip this directory 01953 if ((full(get_label_from_class(class_name)) || !included(class_name))) 01954 break ; 01955 // load data 01956 load_data(itr->path().string()); 01957 // add sample data 01958 // if (scale_mode) // saving image at different scales 01959 // save_scales(load_img, itr->leaf()); 01960 // else // adding data to dataset 01961 this->add_data(load_img, label, &class_name, 01962 itr->path().string().c_str()); 01963 load_img.clear(); 01964 } catch(const char *err) { 01965 cerr << "error: failed to add " << itr->path().string(); 01966 cerr << ": " << endl << err << endl; 01967 add_errors++; 01968 } catch(string &err) { 01969 cerr << "error: failed to add " << itr->path().string(); 01970 cerr << ": " << endl << err << endl; 01971 add_errors++; 01972 } 01973 }} 01974 #endif /* __BOOST__ */ 01975 } 01976 01977 template <class Tdata> 01978 void dataset<Tdata>::load_data(const string &fname) { 01979 load_img.clear(); 01980 if (has_multiple_matrices(fname.c_str())) { 01981 load_img = load_matrices<Tdata>(fname.c_str()); 01982 } else { 01983 load_img.clear(); 01984 idx<Tdata> tmp = load_image<Tdata>(fname.c_str()); 01985 load_img.set(tmp, 0); 01986 } 01987 if (load_planar) 01988 load_img.shift_dim_internal(0, 2); 01989 } 01990 01991 template <class Tdata> 01992 void dataset<Tdata>::compute_random_jitter() { 01993 // compute all possible jitters 01994 random_jitter.clear(); 01995 // scale step 01996 float sstep = (sjitter_max - sjitter_min) 01997 / std::max((int) 0, (int) sjitter_steps - 1); 01998 // min/max rotation jitter 01999 float min_rjitt = 0.0 - rjitter / 2; 02000 float max_rjitt = 0.0 + rjitter / 2; 02001 // rotation step 02002 float rstep = rjitter / std::max((int) 0, (int) rjitter_steps - 1); 02003 // loop over possible rotations 02004 for (float rj = min_rjitt; rj <= max_rjitt; rj += rstep) { 02005 // loop over possible scales 02006 for (float sj = sjitter_min; sj <= sjitter_max; sj += sstep) { 02007 // loop over possible heights 02008 for (int hj = -tjitter_hmax; hj <= tjitter_hmax; hj += tjitter_step) { 02009 // loop over possible width 02010 for (int wj = -tjitter_wmax; wj <= tjitter_wmax; wj +=tjitter_step){ 02011 if (abs(hj) >= tjitter_hmin || abs(wj) >= tjitter_wmin) { 02012 // add jitter 02013 // multiply by scale when > 1, to compensate for object being 02014 // smaller and thus not reaching the same extent. 02015 random_jitter.push_back(jitter(hj * std::max((float)1.0, sj), 02016 wj * std::max((float)1.0, sj), 02017 sj, rj, height)); 02018 } 02019 } 02020 } 02021 } 02022 } 02023 // randomize possibilities 02024 random_shuffle(random_jitter.begin(), random_jitter.end()); 02025 EDEBUG("computed " << random_jitter.size() << " random jitters"); 02026 } 02027 02029 // loading errors 02030 02032 template <typename T> 02033 bool loading_error(idx<T> &mat, string &fname) { 02034 try { 02035 mat = load_matrix<T>(fname); 02036 } catch (const string &err) { 02037 cerr << "error: " << err << endl; 02038 cerr << "error: failed to load dataset file " << fname << endl; 02039 eblerror("failed to load dataset file"); 02040 return false; 02041 } 02042 cout << "Loaded " << fname << " (" << mat << ")" << endl; 02043 return true; 02044 } 02045 02047 template <typename T> 02048 bool loading_error(midx<T> &mat, string &fname) { 02049 try { 02050 mat = load_matrices<T>(fname); 02051 } catch (const string &err) { 02052 cerr << "error: " << err << endl; 02053 cerr << "error: failed to load dataset file " << fname << endl; 02054 eblerror("failed to load dataset file"); 02055 return false; 02056 } 02057 cout << "Loaded " << fname << " (" << mat << ")" << endl; 02058 return true; 02059 } 02060 02062 template <typename T> 02063 bool loading_warning(idx<T> &mat, string &fname) { 02064 try { 02065 mat = load_matrix<T>(fname); 02066 } catch (const string &err) { 02067 cerr << "warning: failed to load dataset file " << fname << endl; 02068 return false; 02069 } 02070 cout << "Loaded " << fname << " (" << mat << ")" << endl; 02071 return true; 02072 } 02073 02075 template <typename T> 02076 bool loading_warning(midx<T> &mat, string &fname) { 02077 try { 02078 mat = load_matrices<T>(fname); 02079 } catch (const string &err) { 02080 cerr << "warning: failed to load dataset file " << fname << endl; 02081 return false; 02082 } 02083 cout << "Loaded " << fname << " (" << mat << ")" << endl; 02084 return true; 02085 } 02086 02088 template <typename T> 02089 bool loading_nowarning(idx<T> &mat, string &fname) { 02090 try { 02091 mat = load_matrix<T>(fname); 02092 } catch (const string &err) { 02093 return false; 02094 } 02095 cout << "Loaded " << fname << " (" << mat << ")" << endl; 02096 return true; 02097 } 02098 02099 } // end namespace ebl 02100 02101 #endif /* DATASET_HPP_ */