libeblearntools
|
00001 /*************************************************************************** 00002 * Copyright (C) 2012 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 DETECTION_THREAD_HPP_ 00034 #define DETECTION_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 #include "pascal_xml.h" 00049 00050 #ifdef __GUI__ 00051 #include "libeblearngui.h" 00052 #endif 00053 00054 using namespace std; 00055 00056 namespace ebl { 00057 00059 // detection thread 00060 00061 template <typename Tnet> 00062 detection_thread<Tnet>:: 00063 detection_thread(configuration &conf_, mutex *om, const char *name_, 00064 const char *arg2_, bool sync, t_chans tc) 00065 : thread(om, name_, sync), conf(conf_), arg2(arg2_), frame(120, 160, 1), 00066 mutex_in(), mutex_out(), 00067 in_updated(false), out_updated(false), bavailable(false), bfed(false), 00068 frame_name(""), frame_id(0), outdir(""), total_saved(0), color_space(tc), 00069 silent(false), boot(conf), frame_skipped(false), 00070 frame_loaded(false), pdetect(NULL) { 00071 silent = conf.exists_true("silent"); 00072 outdir = get_output_directory(conf); 00073 mout << "Saving outputs to " << outdir << endl; 00074 } 00075 00076 template <typename Tnet> 00077 detection_thread<Tnet>::~detection_thread() { 00078 } 00079 00080 template <typename Tnet> 00081 void detection_thread<Tnet>::execute() { 00082 try { 00083 //bool color = conf.exists_true("color"); 00084 uint norm_size = conf.get_uint("normalization_size"); 00085 idxdim dnorm = idxdim(norm_size, norm_size); 00086 Tnet threshold = (Tnet) conf.get_double("threshold"); 00087 bool display = false; 00088 #ifdef __GUI__ 00089 display = conf.exists_true("display") 00090 && conf.exists_true("display_threads"); 00091 bool mindisplay = conf.exists_true("minimal_display"); 00092 bool save_video = conf.exists_true("save_video"); 00093 bool display_states = conf.exists_true("display_states"); 00094 uint wid = 0; // window id 00095 uint wid_states = 0; // window id 00096 #endif 00097 uint display_sleep = conf.get_uint("display_sleep"); 00098 // if (!display && save_video) { 00099 // // we still want to output images but not show them 00100 // display = true; 00101 // #ifdef __GUI__ 00102 // set_gui_silent(); 00103 // #endif 00104 // } 00105 // load network and weights in a forward-only parameter 00106 parameter<SFUNC(Tnet)> theparam; 00107 idx<ubyte> classes(1,1); 00108 //try { // try loading classes names but do not stop upon failure 00109 load_matrix<ubyte>(classes, conf.get_cstring("classes")); 00110 // } catch(string &err) { 00111 // merr << "warning: " << err; 00112 // merr << endl; 00113 // } 00114 vector<string> sclasses = ubyteidx_to_stringvector(classes); 00115 answer_module<SFUNC2(Tnet)> *ans = 00116 create_answer<SFUNC2(Tnet)>(conf, classes.dim(0)); 00117 uint noutputs = ans->get_nfeatures(); 00118 intg thick = -1; 00119 module_1_1<SFUNC(Tnet)> *net = 00120 create_network<SFUNC(Tnet)>(theparam, conf, thick, noutputs); 00121 // loading weights 00122 if (conf.exists("weights")) { // manual weights 00123 // concatenate weights if multiple ones 00124 vector<string> w = 00125 string_to_stringvector(conf.get_string("weights")); 00126 mout << "Loading weights from: " << w << endl; 00127 theparam.load_x(w); 00128 } else { 00129 if (conf.exists_true("manual_load")) { // manual load 00130 eblwarn("\"weights\" variable not defined, loading manually " 00131 << "if manual_load defined"); 00132 manually_load_network(*((layers<SFUNC(Tnet)>*)net), conf); 00133 } else { // random weights 00134 eblwarn("No weights to load, randomizing weights"); 00135 forget_param_linear fgp(1, 0.5); 00136 net->forget(fgp); 00137 } 00138 } 00139 DEBUGMEM_PRETTY("before detection"); 00140 // detector 00141 detector<SFUNC(Tnet)> detect(*net, sclasses, ans, NULL, NULL, mout, merr); 00142 init_detector(detect, conf, outdir); 00143 // keep pointer to detector 00144 pdetect = &detect; 00145 bootstrapping<SFUNC(Tnet)> boot(conf); 00146 00147 // when a bbox file is given, ignore the processing, load the pre-computed 00148 // bboxes and feed them to the nms (non-maximum suppression). 00149 bboxes boxes(bbox_all, NULL, mout, merr); 00150 boxes.print_saving_type(); // inform user how we save boxes 00151 bool precomputed_boxes = false; 00152 if (conf.exists("bbox_file")) { 00153 precomputed_boxes = true; 00154 string bbfile = conf.get_string("bbox_file"); 00155 boxes.load_eblearn(bbfile); 00156 } 00157 bool bmask_class = false; 00158 if (conf.exists("mask_class")) 00159 bmask_class = detect.set_mask_class(conf.get_cstring("mask_class")); 00160 00161 string viddir = outdir; 00162 viddir += "video/"; 00163 mkdir_full(viddir); 00164 // gui 00165 #ifdef __GUI__ 00166 Tnet display_min = -1.7, display_max = 1.7, display_in_min = 0, 00167 display_in_max = 255; 00168 uint display_wmax = conf.try_get_uint("display_max_width", 3000); 00169 if (conf.exists("display_min")) 00170 display_min = (Tnet) conf.get_double("display_min"); 00171 if (conf.exists("display_max")) 00172 display_max = (Tnet) conf.get_double("display_max"); 00173 if (conf.exists("display_in_max")) 00174 display_in_max = (Tnet) conf.get_double("display_in_max"); 00175 if (conf.exists("display_in_min")) 00176 display_in_min = (Tnet) conf.get_double("display_in_min"); 00177 float display_transp = 0.0; 00178 if (conf.exists("display_bb_transparency")) 00179 display_transp = conf.get_float("display_bb_transparency"); 00180 uint qstep1 = 0, qheight1 = 0, qwidth1 = 0, 00181 qheight2 = 0, qwidth2 = 0, qstep2 = 0; 00182 if (conf.exists_bool("queue1")) { 00183 qstep1 = conf.get_uint("qstep1"); 00184 qheight1 = conf.get_uint("qheight1"); 00185 qwidth1 = conf.get_uint("qwidth1"); 00186 } 00187 if (conf.exists_bool("queue2")) { 00188 qstep2 = conf.get_uint("qstep2"); 00189 qheight2 = conf.get_uint("qheight2"); 00190 qwidth2 = conf.get_uint("qwidth2"); 00191 } 00192 module_1_1_gui netgui; 00193 wid_states = display_states ? new_window("network states"):0; 00194 night_mode(); 00195 string title = "eblearn object recognition: "; 00196 title += _name; 00197 if (display) { 00198 wid = new_window(title.c_str()); 00199 mout << "displaying in window " << wid << endl; 00200 night_mode(); 00201 } 00202 float zoom = 1; 00203 if (conf.exists("display_zoom")) zoom = conf.get_float("display_zoom"); 00204 bool bbox_show_conf = !conf.exists_false("bbox_show_conf"); 00205 bool bbox_show_class = !conf.exists_false("bbox_show_class"); 00206 detector_gui<SFUNC(Tnet)> 00207 dgui((conf.exists("show_extracted") ? conf.get_uint("show_extracted"):0), 00208 conf.exists_bool("queue1"), qstep1, qheight1, 00209 qwidth1, conf.exists_bool("queue2"), qstep2, qheight2, qwidth2, 00210 bbox_show_class, bbox_show_conf); 00211 if (bmask_class) 00212 dgui.set_mask_class(conf.get_cstring("mask_class"), 00213 (Tnet) conf.get_double("mask_threshold")); 00214 #endif 00215 // timing variables 00216 timer tpass, toverall; 00217 long ms; 00218 // loop 00219 toverall.start(); 00220 // we're ready 00221 bavailable = true; 00222 while(!this->_stop) { 00223 // wait until a new image is made available 00224 while (!in_updated && !_stop) { 00225 millisleep(1); 00226 } 00227 tpass.restart(); 00228 if (_stop) break ; 00229 // we got a new frame, reset new frame flag 00230 in_updated = false; // no need to lock mutex 00231 // check if this frame should be skipped 00232 if (boot.skip_frame(frame_name)) { 00233 skip_frame(); 00234 continue ; 00235 } else if (!frame_loaded) { 00236 uframe = load_image<ubyte>(frame_fullname); 00237 mout << "loaded image " << frame_fullname << endl; 00238 } 00239 if (!silent) mout << "processing " << frame_name << endl; 00240 // check frame is correctly allocated, if not, allocate. 00241 if (frame.order() != uframe.order()) 00242 frame = idx<Tnet>(uframe.get_idxdim()); 00243 else if (frame.get_idxdim() != uframe.get_idxdim()) 00244 frame.resize(uframe.get_idxdim()); 00245 // copy frame 00246 idx_copy(uframe, frame); 00247 // run detector 00248 if (!display) { // fprop without display 00249 if (precomputed_boxes) { 00250 try { 00251 bboxes *bb = boxes.get_group(frame_name); 00252 idxdim d = boxes.get_group_dims(frame_name); 00253 d.insert_dim(0, 1); 00254 bboxes pruned; 00255 detect.init(d); 00256 detect.fprop_nms(*bb, pruned); 00257 copy_bboxes(pruned); // make a copy of bounding boxes 00258 // resize frame so that caller knows the size of the frame 00259 idxdim framedim = frame.get_idxdim(); 00260 if (d.dim(1) == -1 || d.dim(2) == -1) 00261 eblerror("pre-computed boxes must contain full image size, " 00262 << "but found: " << d); 00263 framedim.setdim(0, d.dim(1)); 00264 framedim.setdim(1, d.dim(2)); 00265 frame.resize(framedim); 00266 } catch(eblexception &e) { 00267 merr << e << endl; 00268 } 00269 } else { 00270 try { 00271 mout << "starting processing of frame " << frame_name << endl; 00272 bboxes &bb = detect.fprop(frame, frame_name.c_str()); 00273 copy_bboxes(bb); // make a copy of bounding boxes 00274 } catch(ebl::eblexception &e) { // detection failed 00275 eblwarn("detection failed: " << e); 00276 clear_bboxes(); 00277 } 00278 } 00279 } 00280 #ifdef __GUI__ 00281 else { // fprop and display 00282 if (precomputed_boxes) eblerror("not implemented for nms only (TODO)"); 00283 disable_window_updates(); 00284 select_window(wid); 00285 clear_window(); 00286 string title = _name; 00287 title << ": " << frame_name; 00288 set_window_title(title.c_str()); 00289 // clear_resize_window(); 00290 try { 00291 if (mindisplay) { 00292 bboxes &bb = 00293 dgui.display(detect, frame, threshold, frame_name.c_str(), 00294 0, 0, zoom, display_min, display_max, 00295 wid, _name.c_str(), display_transp); 00296 copy_bboxes(bb); // make a copy of bounding boxes 00297 } else { 00298 // extract & display boxes 00299 bboxes &bb = 00300 dgui.display_inputs_outputs(detect, frame, threshold, 00301 frame_name.c_str(), 0, 0, zoom, 00302 display_min, display_max, wid, 00303 _name.c_str(), 00304 display_in_min, display_in_max, 00305 display_transp, display_wmax); 00306 // make a copy of bounding boxes 00307 copy_bboxes(bb); 00308 } 00309 } catch(ebl::eblexception &e) { // detection failed 00310 eblwarn("detection failed: " << e); 00311 clear_bboxes(); 00312 } 00313 enable_window_updates(); 00314 } 00315 if (display_states) { 00316 dgui.display_current(detect, frame, wid_states, NULL, zoom); 00317 select_window(wid); 00318 } 00319 if (save_video && display) { 00320 string fname = viddir; 00321 fname += frame_name; 00322 save_window(fname.c_str()); 00323 if (!silent) mout << "saved " << fname << endl; 00324 } 00325 #endif 00326 mout << "processing done for frame " << frame_name << endl; 00327 // bootstrapping 00328 if (conf.exists_true("bootstrapping")) { 00329 boot.fprop(detect, frame_name); 00330 // add multiple scales if positives and scales are defined 00331 if (conf.exists("gt_scales") && boot.extract_positives()) { 00332 vector<double> scales = 00333 string_to_doublevector(conf.get_cstring("gt_scales")); 00334 for (uint s = 0; s < scales.size(); ++s) { 00335 double f = scales[s]; 00336 // downsample input by f 00337 detect.set_resolution(f); 00338 detect.init(frame.get_idxdim(), frame_name.c_str()); 00339 detect.fprop(frame, frame_name.c_str()); 00340 boot.fprop(detect, frame_name, false, f); 00341 } 00342 detect.set_scaling_original(); 00343 detect.init(frame.get_idxdim(), frame_name.c_str()); 00344 } 00345 copy_bootstrapping(boot.get_all(), boot.get_bball()); 00346 #ifdef __GUI__ 00347 // display groundtruth 00348 if (conf.exists_true("display_bootstrapping")) 00349 dgui.display_groundtruth(detect, frame, boot.get_gtall(), 00350 boot.get_gtclean(), boot.get_gtrest(), 00351 boot.get_bbpos(), boot.get_bbneg(), 00352 boot.get_pos(), boot.get_neg(), 0, 0, zoom, 00353 display_min, display_max); 00354 #endif 00355 } 00356 total_saved = detect.get_total_saved(); 00357 ms = tpass.elapsed_milliseconds(); 00358 if (!silent) { 00359 mout << bbs.pretty_short(detect.get_labels()); 00360 mout << "processing=" << ms << " ms (" 00361 << tpass.elapsed() << ")" << endl; 00362 } 00363 DEBUGMEM_PRETTY("after detection"); 00364 // switch 'updated' flag on to warn we just added new data 00365 set_out_updated(); 00366 // display sleep 00367 if (display_sleep > 0) { 00368 mout << "sleeping for " << display_sleep << "ms." << endl; 00369 millisleep(display_sleep); 00370 } 00371 if (conf.exists("save_max") && 00372 detect.get_total_saved() > conf.get_uint("save_max")) 00373 break ; // limit number of detection saves 00374 } 00375 mout << "detection finished. Execution time: " << toverall.elapsed()<<endl; 00376 // free variables 00377 if (net) delete net; 00378 } catch(string &err) { eblerror(err.c_str()); } 00379 } 00380 00381 // thread communication ////////////////////////////////////////////////////// 00382 00383 template <typename Tnet> 00384 void detection_thread<Tnet>::init_detector(detector<SFUNC(Tnet)> &detect, 00385 configuration &conf, 00386 string &odir) { 00387 // multi-scaling parameters 00388 double maxs = conf.exists("max_scale")?conf.get_double("max_scale") : 1.0; 00389 double mins = conf.exists("min_scale")?conf.get_double("min_scale") : 1.0; 00390 t_scaling scaling_type = 00391 (t_scaling) conf.try_get_uint("scaling_type", ORIGINAL); 00392 midxdim scales; 00393 switch (scaling_type) { 00394 case MANUAL: 00395 if (!conf.exists("scales")) 00396 eblerror("expected \"scales\" variable to be defined in manual mode"); 00397 scales = string_to_idxdimvector(conf.get_cstring("scales")); 00398 detect.set_resolutions(scales); 00399 break ; 00400 case ORIGINAL: detect.set_scaling_original(); break ; 00401 case SCALES_STEP: 00402 detect.set_resolutions(conf.get_double("scaling"), maxs, mins); 00403 break ; 00404 case SCALES_STEP_UP: 00405 detect.set_resolutions(conf.get_double("scaling"), maxs, mins); 00406 detect.set_scaling_type(scaling_type); 00407 break ; 00408 default: 00409 detect.set_scaling_type(scaling_type); 00410 } 00411 00412 // optimize memory usage by using only 2 buffers for entire flow 00413 SBUF<Tnet> input(1, 1, 1), output(1, 1, 1); 00414 if (!conf.exists_false("mem_optimization")) 00415 detect.set_mem_optimization(input, output, true); 00416 // TODO: always keep inputs, otherwise detection doesnt work. fix this. 00417 // conf.exists_true("save_detections") || 00418 // (display && !mindisplay)); 00419 // zero padding 00420 float hzpad = 0, wzpad = 0; 00421 if (conf.exists("hzpad")) hzpad = conf.get_float("hzpad"); 00422 if (conf.exists("wzpad")) wzpad = conf.get_float("wzpad"); 00423 detect.set_zpads(hzpad, wzpad); 00424 if (conf.exists("input_min")) // limit inputs size 00425 detect.set_min_resolution(conf.get_uint("input_min")); 00426 if (conf.exists("input_max")) // limit inputs size 00427 detect.set_max_resolution(conf.get_uint("input_max")); 00428 detect.set_silent(); 00429 if (conf.exists_bool("save_detections")) { 00430 string detdir = odir; 00431 detdir += "detections"; 00432 uint nsave = 0; 00433 if (conf.exists("save_max_per_frame")) 00434 nsave = conf.get_uint("save_max_per_frame"); 00435 bool diverse = conf.exists_true("save_diverse"); 00436 detdir = detect.set_save(detdir, nsave, diverse); 00437 } 00438 detect.set_scaler_mode(conf.exists_true("scaler_mode")); 00439 if (conf.exists("bbox_decision")) 00440 detect.set_bbox_decision(conf.get_uint("bbox_decision")); 00441 if (conf.exists("bbox_scalings")) { 00442 mfidxdim scalings = 00443 string_to_fidxdimvector(conf.get_cstring("bbox_scalings")); 00444 detect.set_bbox_scalings(scalings); 00445 } 00446 00447 // nms configuration ////////////////////////////////////////////////////// 00448 t_nms nms_type = (t_nms) conf.try_get_uint("nms", 0); 00449 float pre_threshold = conf.try_get_float("pre_threshold", 0.0); 00450 float post_threshold = conf.try_get_float("post_threshold", 0.0); 00451 float pre_hfact = conf.try_get_float("pre_hfact", 1.0); 00452 float pre_wfact = conf.try_get_float("pre_wfact", 1.0); 00453 float post_hfact = conf.try_get_float("post_hfact", 1.0); 00454 float post_wfact = conf.try_get_float("post_wfact", 1.0); 00455 float woverh = conf.try_get_float("woverh", 1.0); 00456 float max_overlap = conf.try_get_float("max_overlap", 1.0); 00457 float max_hcenter_dist = conf.try_get_float("max_hcenter_dist", 0.0); 00458 float max_wcenter_dist = conf.try_get_float("max_wcenter_dist", 0.0); 00459 float vote_max_overlap = conf.try_get_float("vote_max_overlap", 1.0); 00460 float vote_mhd = conf.try_get_float("vote_max_hcenter_dist", 0.0); 00461 float vote_mwd = conf.try_get_float("vote_max_wcenter_dist", 0.0); 00462 detect.set_nms(nms_type, pre_threshold, post_threshold, pre_hfact, 00463 pre_wfact, post_hfact, post_wfact, woverh, max_overlap, 00464 max_hcenter_dist, max_wcenter_dist, vote_max_overlap, 00465 vote_mhd, vote_mwd); 00466 if (conf.exists("raw_thresholds")) { 00467 string srt = conf.get_string("raw_thresholds"); 00468 vector<float> rt = string_to_floatvector(srt.c_str()); 00469 detect.set_raw_thresholds(rt); 00470 } 00472 if (conf.exists("netdims")) { 00473 idxdim d = string_to_idxdim(conf.get_string("netdims")); 00474 detect.set_netdim(d); 00475 } 00476 if (conf.exists("smoothing")) 00477 detect.set_smoothing(conf.get_uint("smoothing")); 00478 if (conf.exists("background_name")) 00479 detect.set_bgclass(conf.get_cstring("background_name")); 00480 if (conf.exists_true("bbox_ignore_outsiders")) 00481 detect.set_ignore_outsiders(); 00482 if (conf.exists("corners_inference")) 00483 detect.set_corners_inference(conf.get_uint("corners_inference")); 00484 } 00485 00486 template <typename Tnet> 00487 bool detection_thread<Tnet>::get_data(bboxes &bboxes2, idx<ubyte> &frame2, 00488 uint &total_saved_, string &frame_name_, 00489 uint &id, svector<midx<Tnet> > &samples, 00490 bboxes &bbsamples, bool &skipped) { 00491 // lock data 00492 mutex_out.lock(); 00493 // only read data if it has been updated 00494 if (!out_updated) { 00495 // unlock data 00496 mutex_out.unlock(); 00497 return false; 00498 } 00499 // data is updated, but just to tell we skipped the frame 00500 if (frame_skipped) { 00501 skipped = true; 00502 frame_skipped = false; 00503 // reset updated flag 00504 out_updated = false; 00505 // declare thread as available 00506 bavailable = true; 00507 // unlock data 00508 mutex_out.unlock(); 00509 return false; 00510 } 00511 skipped = false; 00512 // clear bboxes 00513 bboxes2.clear(); 00514 bboxes2.push_back_new(bbs); 00515 bbs.clear(); // no use for local bounding boxes anymore, clear them 00516 // check frame is correctly allocated, if not, allocate. 00517 if (frame2.order() != uframe.order()) 00518 frame2 = idx<ubyte>(uframe.get_idxdim()); 00519 else if (frame2.get_idxdim() != uframe.get_idxdim()) 00520 frame2.resize(uframe.get_idxdim()); 00521 // copy frame 00522 idx_copy(uframe, frame2); 00523 // set total of boxes saved 00524 total_saved_ = total_saved; 00525 // set frame name 00526 frame_name_ = frame_name; 00527 // set frame id 00528 id = frame_id; 00529 // overwrite samples 00530 samples.clear(); 00531 bbsamples.clear(); 00532 samples.push_back_new(returned_samples); 00533 bbsamples.push_back_new(returned_samples_bboxes); 00534 returned_samples.clear(); 00535 returned_samples_bboxes.clear(); 00536 // reset updated flag 00537 out_updated = false; 00538 // declare thread as available 00539 bavailable = true; 00540 // unlock data 00541 mutex_out.unlock(); 00542 // confirm that we copied data. 00543 return true; 00544 } 00545 00546 template <typename Tnet> 00547 bool detection_thread<Tnet>::set_data(idx<ubyte> &frame2, string &fullname, 00548 string &name, uint id) { 00549 // lock data (non blocking) 00550 if (!mutex_in.trylock()) 00551 return false; 00552 // check frame is correctly allocated, if not, allocate. 00553 if (frame2.order() != uframe.order()) 00554 uframe = idx<ubyte>(frame2.get_idxdim()); 00555 else if (frame2.get_idxdim() != uframe.get_idxdim()) 00556 uframe.resize(frame2.get_idxdim()); 00557 idx_copy(frame2, uframe); // copy frame 00558 frame_loaded = true; // frame is loaded 00559 frame_fullname = fullname; 00560 frame_name = name; // copy name 00561 frame_id = id; // copy frame_id 00562 in_updated = true; // reset updated flag 00563 bavailable = false; // declare thread as not available 00564 bfed = true; // data has been fed at least once 00565 mutex_in.unlock(); // unlock data 00566 return true; // confirm that we copied data. 00567 } 00568 00569 template <typename Tnet> 00570 bool detection_thread<Tnet>::set_data(string &fullname, string &name,uint id){ 00571 // lock data (non blocking) 00572 if (!mutex_in.trylock()) 00573 return false; 00574 // load image 00575 frame_fullname = fullname; 00576 frame_name = name; // copy name 00577 frame_id = id; // copy frame_id 00578 in_updated = true; // reset updated flag 00579 frame_loaded = false; // let it be loaded later 00580 bavailable = false; // declare thread as not available 00581 bfed = true; // data has been fed at least once 00582 mutex_in.unlock(); // unlock data 00583 return true; 00584 } 00585 00586 template <typename Tnet> 00587 bool detection_thread<Tnet>::available() { 00588 return bavailable; 00589 } 00590 00591 template <typename Tnet> 00592 bool detection_thread<Tnet>::fed() { 00593 return bfed; 00594 } 00595 00596 template <typename Tnet> 00597 string detection_thread<Tnet>::get_output_directory(configuration &conf) { 00598 string s; 00599 if (conf.exists("output_dir")) s << conf.get_string("output_dir"); 00600 s << "/detections"; 00601 if (conf.exists_true("nms")) s << "_" << tstamp(); 00602 s << "/"; 00603 mkdir_full(s); 00604 return s; 00605 } 00606 00607 // protected methods ///////////////////////////////////////////////////////// 00608 00609 template <typename Tnet> 00610 void detection_thread<Tnet>::clear_bboxes() { 00611 // lock data 00612 mutex_out.lock(); 00613 // clear bboxes 00614 bbs.clear(); 00615 // unlock data 00616 mutex_out.unlock(); 00617 } 00618 00619 template <typename Tnet> 00620 void detection_thread<Tnet>::copy_bboxes(bboxes &bb) { 00621 // lock data 00622 mutex_out.lock(); 00623 bbs = bb; 00624 // unlock data 00625 mutex_out.unlock(); 00626 } 00627 00628 template <typename Tnet> 00629 void detection_thread<Tnet>::copy_bootstrapping(svector<midx<Tnet> > &samples, 00630 bboxes &bb) { 00631 // lock data 00632 mutex_out.lock(); 00633 returned_samples = samples; 00634 returned_samples_bboxes = bb; 00635 cout << "samples: " << samples << endl; 00636 cout << "boxes: " << bb << endl; 00637 // unlock data 00638 mutex_out.unlock(); 00639 } 00640 00641 template <typename Tnet> 00642 void detection_thread<Tnet>::set_out_updated() { 00643 // lock data 00644 mutex_out.lock(); 00645 // set flag 00646 out_updated = true; 00647 // unlock data 00648 mutex_out.unlock(); 00649 } 00650 00651 template <typename Tnet> 00652 void detection_thread<Tnet>::skip_frame() { 00653 // lock data 00654 mutex_out.lock(); 00655 mutex_in.lock(); 00656 mout << "frame skipping requested for " << frame_fullname << endl; 00657 // set flag 00658 out_updated = true; 00659 frame_skipped = true; 00660 // unlock data 00661 mutex_in.unlock(); 00662 mutex_out.unlock(); 00663 } 00664 00665 } // end namespace ebl 00666 00667 #endif /* DETECTION_THREAD_HPP_ */