libeblearntools
|
00001 /*************************************************************************** 00002 * Copyright (C) 2010 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 PATCH_DATASET_HPP_ 00034 #define PATCH_DATASET_HPP_ 00035 00036 #include <algorithm> 00037 00038 #ifdef __BOOST__ 00039 #define BOOST_FILESYSTEM_VERSION 2 00040 #include "boost/filesystem.hpp" 00041 #include "boost/regex.hpp" 00042 using namespace boost::filesystem; 00043 using namespace boost; 00044 #endif 00045 00046 using namespace std; 00047 00048 namespace ebl { 00049 00051 // constructors & initializations 00052 00053 template <class Tdata> 00054 patch_dataset<Tdata>::patch_dataset(const char *name_, 00055 const char *inroot_, 00056 const char *outdir_, 00057 uint max_folders_) 00058 : dataset<Tdata>(name_, inroot_) { 00059 outdir = outdir_; 00060 cout << "Output directory: " << outdir << endl; 00061 cout << "Saving " << max_folders_ << " patch per image " 00062 << "for each scale at random position. " << endl; 00063 max_folders = max_folders_; 00064 data_cnt = 0; 00065 save_mode = "mat"; 00066 } 00067 00068 template <class Tdata> 00069 patch_dataset<Tdata>::~patch_dataset() { 00070 } 00071 00073 // data extraction 00074 00075 template <class Tdata> 00076 bool patch_dataset<Tdata>:: 00077 add_data(idx<Tdata> &img, const t_label label, 00078 const string *class_name, const char *filename, const rect<int> *r, 00079 pair<int,int> *center, const rect<int> *visr, 00080 const rect<int> *cropr, const vector<object*> *objs, 00081 const jitter *jittforce) { 00082 vector<rect<int> > patch_bboxes; 00083 vector<rect<int> >::iterator ibb; 00084 string cname = "patch"; 00085 ostringstream fname; 00086 vector<idx<Tdata> > patches; 00087 00088 // check for capacity 00089 if (this->full(label)) // reached full capacity 00090 return false; 00091 // for each scale, find patches and save them 00092 for (vector<double>::iterator i = scales.begin(); i != scales.end(); ++i) { 00093 patches.clear(); 00094 patch_bboxes.clear(); 00095 // rescale original bboxes 00096 uint outh = (uint) (outdims.dim(0) * *i); 00097 uint outw = (uint) (outdims.dim(1) * *i); 00098 float ratio = std::max(img.dim(0) / (float) outh, 00099 img.dim(1) / (float) outw); 00100 uint inh = (uint) (img.dim(0) / ratio); 00101 uint inw = (uint) (img.dim(1) / ratio); 00102 // do not upsample to avoid creating artefacts 00103 // and ignore sizes smaller than outdims 00104 if (inh > (uint) img.dim(0) || inw > (uint) img.dim(1) 00105 || inh < (uint) outdims.dim(0) || inw < (uint) outdims.dim(1)) { 00106 cerr << "warning: ignoring scale " << *i << " (" << inh << "x" 00107 << inw << ") to avoid upsampling original (" << img 00108 << ") or downsampling below target (" << outdims << ")." << endl; 00109 continue ; // do nothing for this scale 00110 } 00111 // preprocess image 00112 rect<int> r(0, 0, img.dim(0), img.dim(1)); 00113 rect<int> outr; 00114 midx<Tdata> ims(1); 00115 ims.set(img, 0); 00116 ims = this->preprocess_data(ims, &cname, filename, &r, *i, &outr); 00117 if (ims.dim(0) > 1) eblerror("expected single layer patch"); 00118 idx<Tdata> im = ims.get(0); 00119 ims.clear(); 00120 // extract all non overlapping patches with dimensions outdims that 00121 // do not overlap with bounding boxes 00122 rect<int> patch(0, 0, outdims.dim(0), outdims.dim(1)); 00123 for (patch.h0 = outr.h0; patch.h0 + patch.height <= outr.h0 + outr.height; 00124 patch.h0 += patch.height) { 00125 for (patch.w0 = outr.w0; patch.w0 + patch.width <= outr.w0 + outr.width; 00126 patch.w0 += patch.width) { 00127 // add patch 00128 idx<Tdata> p = im.narrow(0, patch.height, patch.h0); 00129 p = p.narrow(1, patch.width, patch.w0); 00130 patches.push_back(p); 00131 patch_bboxes.push_back(patch); 00132 } 00133 } 00134 #ifdef __GUI__ 00135 if (display_extraction) { 00136 uint h = 63, w = 0; 00137 // disable_window_updates(); 00138 // // draw original image 00139 // draw_matrix(im, h, w, 1.0, 1.0, (Tdata) -1, (Tdata) 1); 00140 // draw patches boxes 00141 for (ibb = patch_bboxes.begin(); ibb != patch_bboxes.end(); ++ibb) 00142 draw_box(h + ibb->h0, w + ibb->w0, 00143 ibb->height, ibb->width, 0, 255, 0); 00144 // enable_window_updates(); 00145 if (sleep_display) 00146 millisleep((long) sleep_delay); 00147 } 00148 #endif 00149 save_patches(patches, outdir, max_folders, filename, *i, label); 00150 } 00151 return true; 00152 } 00153 00155 // save patches 00156 00157 template <class Tdata> 00158 void patch_dataset<Tdata>::save_patches(vector<idx<Tdata> > &patches, 00159 const string &outdir, 00160 uint max_folders, 00161 const string &filename, 00162 double scale, const t_label label) { 00163 ostringstream folder, fname; 00164 try { 00165 mkdir_full(outdir.c_str()); 00166 uint i; 00167 // shuffle randomly vector of patches to avoid taking top left corner 00168 // as first patch every time 00169 random_shuffle(patches.begin(), patches.end()); 00170 // loop on patches 00171 for (i = 0; (i < patches.size()) && (i < max_folders); ++i) { 00172 // create folder if doesn't exist 00173 folder.str(""); 00174 folder << outdir << "/" << "bg" << i+1 << "/"; 00175 mkdir_full(folder.str().c_str()); 00176 // save patch in folder 00177 // switch saving behavior 00178 fname.str(""); 00179 fname << folder.str() << "img_" << setw(5) << setfill('0') << data_cnt 00180 << "_bg" << i+1 << "_scale" << scale; 00181 if (!strcmp(save_mode.c_str(), "mat")) { // lush matrix mode 00182 fname << MATRIX_EXTENSION; 00183 if (!save_matrix(patches[i], fname.str())) 00184 throw fname.str(); 00185 } else { // image file mode 00186 fname << "." << save_mode; 00187 idx<Tdata> tmp = patches[i]; 00188 // // scale image to 0 255 if preprocessed 00189 // if (strcmp(ppconv_type.c_str(), "RGB")) { 00190 // idx_addc(tmp, (Tdata) 1.0, tmp); 00191 // idx_dotc(tmp, (Tdata) 127.5, tmp); 00192 // } 00193 save_image(fname.str(), tmp, save_mode.c_str()); 00194 } 00195 cout << data_cnt << ": saved " << fname.str().c_str() 00196 << "(" << patches[i] << ")" << endl; 00197 // increase global counter 00198 data_cnt++; 00199 // check for capacity 00200 if (this->full(label)) // reached full capacity 00201 break ; 00202 } 00203 // if (i < patches.size()) // reached max_folders, fill-up last one 00204 // for ( ; i < patches.size(); ++i) { 00205 // // save patch in folder 00206 // fname.str(""); 00207 // fname << folder.str() << filename << ".bg" << i+1 << ".mat"; 00208 // if (!save_matrix(patches[i], fname.str())) 00209 // throw fname.str(); 00210 // cout << data_cnt++ << ": saved " << fname.str().c_str() << endl; 00211 // } 00212 } catch (const string &err) { 00213 cerr << "error: failed to save patch in " << err << endl; 00214 } 00215 } 00216 00217 } // end namespace ebl 00218 00219 #endif /* PATCH_DATASET_HPP_ */