libeblearntools
|
00001 /*************************************************************************** 00002 * Copyright (C) 2011 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 FPROP_THREAD_HPP_ 00034 #define FPROP_THREAD_HPP_ 00035 00036 #include <map> 00037 #include <string> 00038 #include <iostream> 00039 #include <algorithm> 00040 #include <vector> 00041 #include <stdlib.h> 00042 #include <sstream> 00043 #include <iomanip> 00044 #include <time.h> 00045 00046 #include "libeblearn.h" 00047 #include "libeblearntools.h" 00048 00049 #ifdef __GUI__ 00050 #include "libeblearngui.h" 00051 #endif 00052 00053 using namespace std; 00054 00055 namespace ebl { 00056 00058 // detection thread 00059 00060 template <typename Tnet> 00061 fprop_thread<Tnet>::fprop_thread(configuration &conf_, 00062 mutex *om, 00063 const char *name_, 00064 const char *arg2_, bool sync, 00065 t_chans tc) 00066 : thread(om, name_, sync), conf(conf_), arg2(arg2_), frame(120, 160, 1), 00067 mutex_in(), mutex_out(), 00068 in_updated(false), out_updated(false), bavailable(false), 00069 frame_name(""), frame_id(0), outdir(""), color_space(tc), 00070 bload_image(false), pdetect(NULL) { 00071 } 00072 00073 template <typename Tnet> 00074 fprop_thread<Tnet>::~fprop_thread() { 00075 } 00076 00077 template <typename Tnet> 00078 void fprop_thread<Tnet>::set_out_updated() { 00079 // lock data 00080 mutex_out.lock(); 00081 // set flag 00082 out_updated = true; 00083 // unlock data 00084 mutex_out.unlock(); 00085 } 00086 00087 template <typename Tnet> 00088 bool fprop_thread<Tnet>::get_data(idx<ubyte> &frame2, 00089 string &frame_name_, 00090 uint &id) { 00091 // lock data 00092 mutex_out.lock(); 00093 // only read data if it has been updated 00094 if (!out_updated) { 00095 // unlock data 00096 mutex_out.unlock(); 00097 return false; 00098 } 00099 // check frame is correctly allocated, if not, allocate. 00100 if (frame2.order() != uframe.order()) 00101 frame2 = idx<ubyte>(uframe.get_idxdim()); 00102 else if (frame2.get_idxdim() != uframe.get_idxdim()) 00103 frame2.resize(uframe.get_idxdim()); 00104 // copy frame 00105 idx_copy(uframe, frame2); 00106 // set frame name 00107 frame_name_ = frame_name; 00108 // set frame id 00109 id = frame_id; 00110 // reset updated flag 00111 out_updated = false; 00112 // declare thread as available 00113 bavailable = true; 00114 // unlock data 00115 mutex_out.unlock(); 00116 // confirm that we copied data. 00117 return true; 00118 } 00119 00120 template <typename Tnet> 00121 bool fprop_thread<Tnet>::set_data(idx<ubyte> &frame2, string &name, 00122 uint id) { 00123 // lock data (non blocking) 00124 if (!mutex_in.trylock()) 00125 return false; 00126 // check frame is correctly allocated, if not, allocate. 00127 if (frame2.order() != uframe.order()) 00128 uframe = idx<ubyte>(frame2.get_idxdim()); 00129 else if (frame2.get_idxdim() != uframe.get_idxdim()) 00130 uframe.resize(frame2.get_idxdim()); 00131 // do not load image, use passed frame instead 00132 bload_image = false; 00133 // copy frame 00134 idx_copy(frame2, uframe); 00135 // copy name 00136 frame_name = name; 00137 // copy frame_id 00138 frame_id = id; 00139 // reset updated flag 00140 in_updated = true; 00141 // unlock data 00142 mutex_in.unlock(); 00143 // declare thread as not available 00144 bavailable = false; 00145 // confirm that we copied data. 00146 return true; 00147 } 00148 00149 template <typename Tnet> 00150 bool fprop_thread<Tnet>::set_dump(string &frame_fname_, 00151 string &dump_fname) { 00152 // lock data (non blocking) 00153 if (!mutex_in.trylock()) 00154 return false; 00155 // set the dump name in detector 00156 if (!pdetect) 00157 eblerror("pdetect shoud be allocated"); 00158 pdetect->set_outputs_dumping(dump_fname.c_str()); 00159 // image file to load and process 00160 frame_name = frame_fname_; 00161 bload_image = true; 00162 // reset updated flag 00163 in_updated = true; 00164 // unlock data 00165 mutex_in.unlock(); 00166 // declare thread as not available 00167 bavailable = false; 00168 // confirm that we copied data. 00169 return true; 00170 } 00171 00172 template <typename Tnet> 00173 bool fprop_thread<Tnet>::dumped() { 00174 // lock data 00175 mutex_out.lock(); 00176 // only read data if it has been updated 00177 if (!out_updated) { 00178 // unlock data 00179 mutex_out.unlock(); 00180 return false; 00181 } 00182 // reset updated flag 00183 out_updated = false; 00184 // declare thread as available 00185 bavailable = true; 00186 // unlock data 00187 mutex_out.unlock(); 00188 // confirm that we copied data. 00189 return true; 00190 } 00191 00192 template <typename Tnet> 00193 bool fprop_thread<Tnet>::available() { 00194 return bavailable; 00195 } 00196 00197 template <typename Tnet> 00198 void fprop_thread<Tnet>::set_output_directory(string &out) { 00199 outdir = out; 00200 } 00201 00202 template <typename Tnet> 00203 void fprop_thread<Tnet>::execute() { 00204 try { 00205 // configuration 00206 bool silent = conf.exists_true("silent"); 00207 Tnet threshold = (Tnet) conf.try_get_double("threshold", 0); 00208 bool display = false; 00209 bool mindisplay = conf.exists_true("minimal_display"); 00210 bool display_states = conf.exists_true("display_states"); 00211 uint display_sleep = conf.try_get_uint("display_sleep", 0); 00212 uint wid = 0; // window id 00213 uint wid_states = 0; // window id 00214 display = conf.exists_true("display_threads"); 00215 // load network and weights in a forward-only parameter 00216 parameter<FPROP_SFUNC(Tnet)> theparam; 00217 idx<ubyte> classes; 00218 vector<string> sclasses; 00219 answer_module<SFUNC2(Tnet)> *ans = NULL; 00220 uint noutputs = 1; 00221 intg thick = -1; 00222 if (conf.exists("classes")) { 00223 classes = load_matrix<ubyte>(conf.get_cstring("classes")); 00224 sclasses = ubyteidx_to_stringvector(classes); 00225 ans = create_answer<SFUNC2(Tnet)>(conf, classes.dim(0)); 00226 noutputs = ans->get_nfeatures(); 00227 } 00228 module_1_1<FPROP_SFUNC(Tnet)> *net = 00229 create_network<FPROP_SFUNC(Tnet)>(theparam, conf, thick, noutputs); 00230 // loading weights 00231 if (!conf.exists("weights")) { // manual weights 00232 merr << "warning: \"weights\" variable not defined, loading manually " 00233 << "if manual_load defined" << endl; 00234 if (conf.exists_true("manual_load")) 00235 manually_load_network(*((layers<FPROP_SFUNC(Tnet)>*)net), conf); 00236 } else { // multiple-file weights 00237 // concatenate weights if multiple ones 00238 vector<string> w = 00239 string_to_stringvector(conf.get_string("weights")); 00240 mout << "Loading weights from: " << w << endl; 00241 theparam.load_x(w); 00242 } 00243 // detector 00244 detector<SFUNC(Tnet)> detect(*net, sclasses, ans, NULL, NULL, 00245 mout, merr); 00246 detection_thread<Tnet>::init_detector(detect, conf, outdir); 00247 pdetect = &detect; 00248 // gui 00249 #ifdef __GUI__ 00250 Tnet display_min = -1.7, display_max = 1.7, display_in_min = 0, 00251 display_in_max = 255; 00252 if (conf.exists("display_min")) 00253 display_min = (Tnet) conf.get_double("display_min"); 00254 if (conf.exists("display_max")) 00255 display_max = (Tnet) conf.get_double("display_max"); 00256 if (conf.exists("display_in_max")) 00257 display_in_max = (Tnet) conf.get_double("display_in_max"); 00258 if (conf.exists("display_in_min")) 00259 display_in_min = (Tnet) conf.get_double("display_in_min"); 00260 module_1_1_gui netgui; 00261 wid_states = display_states ? new_window("network states"):0; 00262 night_mode(); 00263 string title = "eblearn fprop: "; 00264 title += _name; 00265 if (display) { 00266 wid = new_window(title.c_str()); 00267 mout << "displaying in window " << wid << endl; 00268 night_mode(); 00269 } 00270 float zoom = 1; 00271 if (conf.exists("display_zoom")) zoom = conf.get_float("display_zoom"); 00272 detector_gui<FPROP_SFUNC(Tnet)> dgui; 00273 #endif 00274 // timing variables 00275 timer tpass, toverall; 00276 long ms; 00277 // loop 00278 toverall.start(); 00279 // we're ready 00280 bavailable = true; 00281 while(!this->_stop) { 00282 tpass.restart(); 00283 // wait until a new image is made available 00284 while (!in_updated && !_stop) { 00285 millisleep(1); 00286 } 00287 if (_stop) break ; 00288 // we got a new frame, reset new frame flag 00289 in_updated = false; // no need to lock mutex 00290 if (!silent) mout << "processing " << frame_name; 00291 // prepare image 00292 if (bload_image) { // load image directly 00293 frame = load_image<Tnet>(frame_name); 00294 } else { // used passed image 00295 // check frame is correctly allocated, if not, allocate. 00296 if (frame.order() != uframe.order()) 00297 frame = idx<Tnet>(uframe.get_idxdim()); 00298 else if (frame.get_idxdim() != uframe.get_idxdim()) 00299 frame.resize(uframe.get_idxdim()); 00300 // copy frame 00301 idx_copy(uframe, frame); 00302 } 00303 if (!silent) mout << " (min: " << idx_min(frame) 00304 << ", max: " << idx_max(frame) << ")" << endl; 00305 00306 // run detector 00307 if (!display) { // fprop without display 00308 detect.fprop(frame, frame_name.c_str()); 00309 } 00310 #ifdef __GUI__ 00311 else { // fprop and display 00312 disable_window_updates(); 00313 select_window(wid); 00314 clear_window(); 00315 string title = _name; 00316 title << ": " << frame_name; 00317 set_window_title(title.c_str()); 00318 // clear_resize_window(); 00319 if (mindisplay) { 00320 dgui.display(detect, frame, threshold, frame_name.c_str(), 00321 0, 0, zoom, display_min, display_max, 00322 wid, _name.c_str()); 00323 } else { 00324 dgui.display_inputs_outputs(detect, frame, threshold, 00325 frame_name.c_str(), 0, 0, zoom, 00326 display_min, display_max, wid, 00327 _name.c_str(), 00328 display_in_min, display_in_max); 00329 } 00330 enable_window_updates(); 00331 } 00332 if (display_states) { 00333 dgui.display_current(detect, frame, wid_states, NULL, zoom); 00334 select_window(wid); 00335 } 00336 // if (save_video && display) { 00337 // string fname = viddir; 00338 // fname += frame_name; 00339 // save_window(fname.c_str()); 00340 // if (!silent) mout << "saved " << fname << endl; 00341 // } 00342 #endif 00343 ms = tpass.elapsed_milliseconds(); 00344 if (!silent) { 00345 mout << "processing=" << ms << " ms (" 00346 << tpass.elapsed() << ")" << endl; 00347 } 00348 #ifdef __DEBUGMEM__ 00349 pretty_memory(); 00350 #endif 00351 // switch 'updated' flag on to warn we just added new data 00352 set_out_updated(); 00353 // display sleep 00354 if (display_sleep > 0) { 00355 mout << "sleeping for " << display_sleep << "ms." << endl; 00356 millisleep(display_sleep); 00357 } 00358 } 00359 mout << "fprop finished. Execution time: " << toverall.elapsed() 00360 << endl; 00361 // free variables 00362 if (net) delete net; 00363 } catch(string &err) { eblerror(err.c_str()); } 00364 } 00365 00366 } // end namespace ebl 00367 00368 #endif /* FPROP_THREAD_HPP_ */