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 BOOTSTRAPPING_HPP_ 00034 #define BOOTSTRAPPING_HPP_ 00035 00036 namespace ebl { 00037 00039 // bootstrapping 00040 00041 template <typename T, class Tstate> 00042 bootstrapping<T,Tstate>::bootstrapping(configuration &conf_) 00043 : conf(conf_), silent(false) { 00044 gt_path = conf.try_get_string("gt_path", ""); 00045 silent = conf.exists_true("silent"); 00046 extract_pos = conf.exists_true("gt_extract_pos"); 00047 extract_neg = conf.exists_true("gt_extract_neg"); 00048 _activated = conf.exists_true("bootstrapping"); 00049 _max_size = conf.try_get_intg("bootstrapping_max", limits<intg>::max()); 00050 if (_max_size == 0) _max_size = limits<intg>::max(); 00051 neg_gt_only = conf.exists_true("gt_neg_gt_only"); 00052 neg_threshold = (T) conf.try_get_double("gt_neg_threshold", .0001); 00053 if (conf.exists("bbox_scalings")) 00054 bbox_scalings =string_to_fidxdimvector(conf.get_cstring("bbox_scalings")); 00055 mirror_pos = conf.exists_true("gt_mirror_pos"); 00056 } 00057 00058 template <typename T, class Tstate> 00059 bootstrapping<T,Tstate>::~bootstrapping() { 00060 } 00061 00062 template <typename T, class Tstate> 00063 void bootstrapping<T,Tstate>::fprop(detector<T,Tstate> &detect, 00064 string &fname, bool reset, double scale) { 00065 if (reset) clear(); 00066 try { 00067 try { 00068 // load groundtruth data 00069 gt_all = load_groundtruth(fname); 00070 gt_clean = load_clean_groundtruth(fname, conf, gt_rest); 00071 // negs do not need groundtruth data 00072 if (extract_neg) 00073 bbneg = get_negatives 00074 (detect.answers, gt_clean, gt_rest, detect.itl, detect.itr, 00075 detect.ibl, detect.ibr, conf.try_get_float("gt_neg_matching", .5), 00076 conf.try_get_uint("gt_neg_max", 5), detect.bgclass, neg_threshold); 00077 // get bootstrapping boxes 00078 if (extract_pos) { 00079 // scale groundtruth (for positives only) 00080 if (scale != 1.0) { 00081 gt_all.scale_centered(scale, scale); 00082 gt_clean.scale_centered(scale, scale); 00083 } 00084 bbpos = get_positives 00085 (detect.outputs[0], gt_clean, detect.itl, detect.itr, detect.ibl, 00086 detect.ibr, conf.try_get_float("gt_pos_matching", .5), 00087 conf.try_get_float("gt_min_context", 1.0)); 00088 } 00089 } catch (eblexception &e) { eblwarn(e); } 00090 // get preprocessed bootstrappings 00091 bboxes ppbout; 00092 spos = detect.get_preprocessed(bbpos, ppbout); 00093 sneg = detect.get_preprocessed(bbneg, ppbout); 00094 if (mirror_pos) add_mirrors(spos, bbpos); 00095 // fuse all results 00096 bball.push_back(bbpos); 00097 bball.push_back(bbneg); 00098 sall.push_back(spos); 00099 sall.push_back(sneg); 00100 } catch (eblexception &e) { eblwarn(e); } 00101 } 00102 00103 template <typename T, class Tstate> 00104 void bootstrapping<T,Tstate>::clear() { 00105 sall.clear(); 00106 sneg.clear(); 00107 spos.clear(); 00108 gt_rest.clear(); 00109 gt_clean.clear(); 00110 gt_all.clear(); 00111 bball.clear(); 00112 bbneg.clear(); 00113 bbpos.clear(); 00114 } 00115 00116 // accessors ///////////////////////////////////////////////////////////////// 00117 00118 template <typename T, class Tstate> 00119 bboxes& bootstrapping<T,Tstate>::get_bbpos() { 00120 return bbpos; 00121 } 00122 00123 template <typename T, class Tstate> 00124 bboxes& bootstrapping<T,Tstate>::get_bbneg() { 00125 return bbneg; 00126 } 00127 00128 template <typename T, class Tstate> 00129 bboxes& bootstrapping<T,Tstate>::get_bball() { 00130 return bball; 00131 } 00132 00133 template <typename T, class Tstate> 00134 bboxes& bootstrapping<T,Tstate>::get_gtall() { 00135 return gt_all; 00136 } 00137 00138 template <typename T, class Tstate> 00139 bboxes& bootstrapping<T,Tstate>::get_gtclean() { 00140 return gt_clean; 00141 } 00142 00143 template <typename T, class Tstate> 00144 bboxes& bootstrapping<T,Tstate>::get_gtrest() { 00145 return gt_rest; 00146 } 00147 00148 template <typename T, class Tstate> 00149 svector<midx<T> >& bootstrapping<T,Tstate>::get_pos() { 00150 return spos; 00151 } 00152 00153 template <typename T, class Tstate> 00154 svector<midx<T> >& bootstrapping<T,Tstate>::get_neg() { 00155 return sneg; 00156 } 00157 00158 template <typename T, class Tstate> 00159 svector<midx<T> >& bootstrapping<T,Tstate>::get_all() { 00160 return sall; 00161 } 00162 00163 template <typename T, class Tstate> 00164 bool bootstrapping<T,Tstate>::activated() { 00165 return _activated; 00166 } 00167 00168 template <typename T, class Tstate> 00169 bool bootstrapping<T,Tstate>::extract_positives() { 00170 return extract_pos; 00171 } 00172 00173 template <typename T, class Tstate> 00174 bool bootstrapping<T,Tstate>::groundtruth_found(string &frame_name) { 00175 string s = groundtruth_file(frame_name); 00176 return file_exists(s); 00177 } 00178 00179 template <typename T, class Tstate> 00180 bool bootstrapping<T,Tstate>::skip_frame(string &frame_name) { 00181 if (!_activated) return false; 00182 bool gtfound = groundtruth_found(frame_name); 00183 if (_activated && !extract_neg && !gtfound) { 00184 return true; 00185 } 00186 if (extract_neg && neg_gt_only && !gtfound) { 00187 cout << "frame skipped because no groundtruth found" << endl; 00188 return true; // extract negatives but only in images with groundtruth 00189 } 00190 if (gtfound) { 00191 // groundtruth is found, let's check how many objects are filtered 00192 bboxes b, rest; 00193 b = load_clean_groundtruth(frame_name, conf, rest); 00194 if (b.size() == 0 && !extract_neg) { 00195 cout << "Skipping frame " << frame_name 00196 << " because no clean objects were found." << endl; 00197 return true; 00198 } 00199 } 00200 return false; 00201 } 00202 00203 template <typename T, class Tstate> 00204 intg bootstrapping<T,Tstate>::max_size() { 00205 return _max_size; 00206 } 00207 00208 // dataset methods /////////////////////////////////////////////////////////// 00209 00210 template <typename T, class Tstate> 00211 void bootstrapping<T,Tstate>::save_dataset(svector<midx<T> > &samples, 00212 bboxes &bb, string &outdir, 00213 idx<ubyte> &classes) { 00214 if (samples.size() != bb.size()) 00215 eblerror("expected same number of samples and boxes but got " 00216 << samples.size() << " and " << bb.size()); 00217 if (samples.size() == 0) eblerror("expected at least 1 sample"); 00218 // find max number of submatrices 00219 intg order = samples[0].order(), dim = samples[0].dim(0); 00220 if (order != 1) eblerror("expected order 1"); 00221 for (intg i = 0; i < (intg) samples.size(); ++i) { 00222 if (samples[i].order() != order) 00223 eblerror("expected same order for all samples but found " 00224 << samples[i].order() << " and " << order); 00225 if (samples[i].dim(0) > dim) dim = samples[i].dim(0); 00226 } 00227 cout << "Max number of sub-matrices for each sample is: " << dim << endl; 00228 // create a single midx with all samples 00229 midx<T> all(samples.size(), dim); 00230 idx<intg> scales(samples.size()), labels(samples.size()); 00231 all.clear(); 00232 idx_clear(scales); 00233 // loop on samples 00234 for (intg i = 0; i < (intg) samples.size(); ++i) { 00235 midx<T> &sample = samples[i]; 00236 bbox &b = bb[i]; 00237 // loop on sample's submatrix 00238 for (intg j = 0; j < sample.dim(0); ++j) { 00239 idx<T> layer = sample.get(j); 00240 all.set(layer, i, j); 00241 } 00242 // set scale & label 00243 scales.set(b.oscale_index, i); 00244 labels.set(b.class_id, i); 00245 } 00246 // save files 00247 string name; 00248 name << "bootstrapping_" << conf.get_string("gt_name"); 00249 string data_fname, scales_fname, labels_fname, classes_fname; 00250 cout << "saving dataset..." << endl; 00251 data_fname << outdir << "/" << name << "_" << DATA_NAME << MATRIX_EXTENSION; 00252 save_matrices(all, data_fname); 00253 cout << "saved " << data_fname << " (" << all << ")" << endl; 00254 scales_fname << outdir << "/" << name << "_" << SCALES_NAME 00255 << MATRIX_EXTENSION; 00256 save_matrix(scales, scales_fname); 00257 cout << "saved " << scales_fname << " (" << scales << ")" << endl; 00258 labels_fname << outdir << "/" << name << "_" << LABELS_NAME 00259 << MATRIX_EXTENSION; 00260 save_matrix(labels, labels_fname); 00261 cout << "saved " << labels_fname << " (" << labels << ")" << endl; 00262 classes_fname << outdir << "/" << name << "_" << CLASSES_NAME 00263 << MATRIX_EXTENSION; 00264 save_matrix(classes, classes_fname); 00265 cout << "saved " << classes_fname << " (" << classes << ")" << endl; 00266 } 00267 00268 // internal methods ////////////////////////////////////////////////////////// 00269 00270 template <typename T, class Tstate> 00271 string bootstrapping<T,Tstate>::groundtruth_file(string &frame_name) { 00272 string xml = ""; 00273 xml << gt_path << "/" << noext_name(frame_name.c_str()) << ".xml"; 00274 return xml; 00275 } 00276 00277 template <typename T, class Tstate> 00278 bboxes bootstrapping<T,Tstate>::load_groundtruth(string &frame_name) { 00279 bboxes gt; 00280 // look for xml version 00281 xml_fullname = groundtruth_file(frame_name); 00282 if (file_exists(xml_fullname)) { 00283 if (!silent) cout << "Found groundtruth file: " << xml_fullname << endl; 00284 gt = pascal_xml::get_bboxes(xml_fullname); 00285 EDEBUG("groundtruth boxes: " << gt); 00286 } else eblthrow("groundtruth file not found " << xml_fullname); 00287 return gt; 00288 } 00289 00290 template <typename T, class Tstate> 00291 bboxes bootstrapping<T,Tstate>::load_clean_groundtruth 00292 (string &frame_name, configuration &conf, bboxes &rest) { 00293 rest.clear(); 00294 // load filtering settings 00295 float minvisibility = conf.try_get_float("gt_minvisibility", 0); 00296 float min_ar = conf.try_get_float("gt_min_aspect_ratio", 0); 00297 float max_ar = conf.try_get_float("gt_max_aspect_ratio", 1); 00298 idxdim mindims(1, 1), minborders; 00299 vector<string> included; 00300 if (conf.exists("gt_mindims")) 00301 mindims = string_to_idxdim(conf.get_cstring("gt_mindims")); 00302 if (conf.exists("gt_minborders")) 00303 minborders = string_to_idxdim(conf.get_cstring("gt_minborders")); 00304 if (conf.exists("gt_included")) 00305 included = string_to_stringvector(conf.get_string("gt_included")); 00306 bboxes gt; 00307 // look for xml version 00308 xml_fullname = groundtruth_file(frame_name); 00309 if (file_exists(xml_fullname)) { 00310 if (!silent) 00311 cout << "Found groundtruth file: " << xml_fullname << endl 00312 << "Filtering based on min visibility " << minvisibility 00313 << ", aspect ratio min " << min_ar << " max " << max_ar 00314 << ", mindims " << mindims << ", minborders " << minborders 00315 << ", included classes: " << included << endl; 00316 gt = pascal_xml::get_filtered_bboxes(xml_fullname, minvisibility, min_ar, 00317 max_ar, mindims, minborders, 00318 included, rest); 00319 EDEBUG("clean groundtruth boxes: " << gt); 00320 } else eblthrow("groundtruth file not found " << xml_fullname); 00321 return gt; 00322 } 00323 00324 template <typename T, class Tstate> 00325 bboxes bootstrapping<T,Tstate>::get_positives 00326 (mstate<Tstate> &outputs, bboxes &groundtruth, mfidxdim &topleft, 00327 mfidxdim &topright, mfidxdim &bottomleft, mfidxdim &bottomright, 00328 float matching, float mincontext) { 00329 bboxes res; 00330 float min_overlap = .9; 00331 float closest_overlap = 0, closest_overlap2 = 0, closest_match = 0; 00332 uint closest_overlap_scale = 0, closest_overlap2_scale = 0, 00333 closest_match_scale = 0; 00334 cout << "groundtruth: " << groundtruth << endl; 00335 // loop on groundtruth boxes 00336 for (bboxes::iterator i = groundtruth.begin(); i != groundtruth.end(); ++i){ 00337 bbox >raw = *i; 00338 bboxes candidates; 00339 // loop on outputs maps 00340 for (uint o = 0; o < outputs.size(); ++o) { 00341 Tstate &out = outputs[o]; 00342 // input space corners 00343 fidxdim &tl = topleft[o], &tr = topright[o], &bl = bottomleft[o]; 00344 // steps in input space 00345 double hf = (bl.offset(1) - tl.offset(1)) / out.x.dim(1); 00346 double wf = (tr.offset(2) - tl.offset(2)) / out.x.dim(2); 00347 // box size for this map 00348 bbox b(0, 0, tl.dim(1), tl.dim(2)); 00349 b.o.height = 1; 00350 b.o.width = 1; 00351 // normalize width of gt 00352 bbox gt = gtraw; 00353 gt.scale_width(b.width / b.height); 00354 bbox gtcontext = gt; 00355 gtcontext.scale_centered(mincontext, mincontext); 00356 if (gt.class_id >= out.x.dim(0)) 00357 eblerror("expected dim 0 of " << out.x << " to be > than " 00358 << gt.class_id); 00359 // // box has to be able to include groundtruth entirely, otherwise skip 00360 // rect<float> gt2(0, 0, gt.height, gt.width); 00361 // float gt2_overlap = gt2.overlap_ratio(b); 00362 // if (gt2_overlap > closest_overlap) { 00363 // closest_overlap = gt2_overlap; 00364 // closest_overlap_scale = o; 00365 // } 00366 // if (gt2_overlap < 1.0) { 00367 // EDEBUG("ruling out scale " << o << " because box " << b 00368 // << " doesn't overlap completely with gt " << gt2); 00369 // continue ; 00370 // } 00371 // apply scalings to box 00372 float hscale = 1, wscale = 1; 00373 if (o < bbox_scalings.size()) { 00374 fidxdim &scaling = bbox_scalings[o]; 00375 hscale = scaling.dim(0); 00376 wscale = scaling.dim(1); 00377 } 00378 // loop on width 00379 int wmax = (int) ceil((gt.w0 + gt.width) / wf); 00380 int w = (int) std::max((double)0, floor((gt.w0 - b.width/2 - tl.offset(2)) / wf)); 00381 // force minimum region to explore to at least 4 pixels 00382 int wadd = std::max(wmax - w, 2); 00383 w -= wadd; 00384 wmax += wadd; 00385 for ( ; w < wmax; ++w) { 00386 // loop on height 00387 int hmax = (int) ceil((gt.h0 + gt.height) / hf); 00388 int h = (int) std::max((double)0, floor((gt.h0 - b.height/2 - tl.offset(1)) / hf)); 00389 // force minimum region to explore to at least 4 pixels 00390 int hadd = std::max(hmax - h, 2); 00391 h -= hadd; 00392 hmax += hadd; 00393 for ( ; h < hmax; ++h) { 00394 b.h0 = tl.offset(1) + h * hf; 00395 b.w0 = tl.offset(2) + w * wf; 00396 bbox b2 = b; 00397 b2.scale_centered(hscale, wscale); 00398 EDEBUG("scale " << o << " gt " << (rect<float>&)gt 00399 << "gtcontext " << (rect<float>&)gtcontext << " b " << (rect<float>&)b2 00400 << " matching: " << b2.match(gtcontext)); 00401 // skip this box if not matching gt more than minimum match 00402 float bmatch = b2.match(gt); 00403 if (bmatch > closest_match) { 00404 closest_match = bmatch; 00405 closest_match_scale = o; 00406 } 00407 if (o > 0 && o < outputs.size() -1 00408 && bmatch < matching) continue ; 00409 00410 // skip this box if not including gt entirely 00411 EDEBUG("overlap ratio " << gt.overlap_ratio(b)); 00412 float gtoverlap = gtcontext.overlap_ratio(b); 00413 if (gtoverlap > closest_overlap2) { 00414 closest_overlap2 = gtoverlap; 00415 closest_overlap2_scale = o; 00416 } 00417 if (o < outputs.size() - 1 && gtoverlap < min_overlap) continue ; 00418 // bbox is a potential candidate, add it 00419 // // use output value as confidence 00420 // b.confidence = (float) out.x.get(gt.class_id, h, w); 00421 // use matching value as confidence 00422 b.confidence = bmatch; 00423 // b.iscale_index = scale_indices[a]; // scale index 00424 // b.oscale_index = a; // scale index 00425 // b.i.h0 = ptl.offset(1) + h * phf; 00426 // b.i.w0 = ptl.offset(2) + w * pwf; 00427 // b.i.height = ptl.dim(1); 00428 // b.i.width = ptl.dim(2); 00429 b.o.h0 = h; // answer height in output 00430 b.o.w0 = w; // answer height in output 00431 b.class_id = gt.class_id; 00432 b.iscale_index = o; 00433 b.oscale_index = o; 00434 EDEBUG("adding candidate " << (rect<float>&)b); 00435 candidates.push_back_new(b); 00436 } 00437 } 00438 } 00439 EDEBUG("candidates: " << candidates); 00440 // pick highest score candidates 00441 bboxes highests = candidates.get_most_confidents(); 00442 // out of all highest, pick one with closest center to groundtruth 00443 float dist = limits<float>::max(); 00444 int best = -1; 00445 for (uint i = 0; i < highests.size(); ++i) { 00446 if (highests[i].center_distance(gtraw) < dist) { 00447 best = (int) i; 00448 dist = highests[i].center_distance(gtraw); 00449 } 00450 } 00451 if (best >= 0) res.push_back_new(highests[best]); 00452 #ifdef __DEBUG__ 00453 cerr << "candidate with strongest confidence for grountruth " << gtraw 00454 << " is: "; 00455 if (best >= 0) cerr << highests[best] << endl; 00456 else cerr << "none" << endl; 00457 #endif 00458 if (best < 0) 00459 eblwarn("no positive sample found for groundtruth bbox " << gtraw 00460 << " in file " << xml_fullname 00461 << ", highest overlap " << closest_overlap 00462 << " with scale " << closest_overlap_scale 00463 << ", highest overlap2 " << closest_overlap2 00464 << " with scale " << closest_overlap2_scale 00465 << " (min overlap " << min_overlap << ")" 00466 << ", closest matching " << closest_match 00467 << " with scale " << closest_match_scale 00468 << " (min match " << matching << ")"); 00469 cout << "best: " << best << " gt " << gtraw << endl; 00470 } 00471 EDEBUG("positive bootstraps: " << res); 00472 return res; 00473 } 00474 00475 template <typename T, class Tstate> 00476 bboxes bootstrapping<T,Tstate>::get_negatives 00477 (mstate<Tstate> &answers, bboxes &filtered, bboxes &nonfiltered, 00478 mfidxdim &topleft, mfidxdim &topright, mfidxdim &bottomleft, 00479 mfidxdim &bottomright, float matching, uint nmax, int neg_id, T threshold) { 00480 bboxes res; 00481 // extract all non-negative windows 00482 // loop on outputs maps 00483 for (uint o = 0; o < answers.size(); ++o) { 00484 bboxes pos2, res2; 00485 Tstate &ans = answers[o]; 00486 // input space corners 00487 fidxdim &tl = topleft[o], &tr = topright[o], &bl = bottomleft[o]; 00488 // steps in input space 00489 double hf = (bl.offset(1) - tl.offset(1)) / ans.x.dim(1); 00490 double wf = (tr.offset(2) - tl.offset(2)) / ans.x.dim(2); 00491 // box size for this map 00492 bbox b(0, 0, tl.dim(1), tl.dim(2)); 00493 b.o.height = 1; 00494 b.o.width = 1; 00495 // apply scalings to box 00496 float hscale = 1, wscale = 1; 00497 if (o < bbox_scalings.size()) { 00498 fidxdim &scaling = bbox_scalings[o]; 00499 hscale = scaling.dim(0); 00500 wscale = scaling.dim(1); 00501 } 00502 // loop on width 00503 for (uint w = 0; w < ans.x.dim(2); ++w) { 00504 // loop on height 00505 for (uint h = 0; h < ans.x.dim(1); ++h) { 00506 b.class_id = (int) ans.x.get(0, h, w); 00507 // ignore negative answers 00508 if (b.class_id == neg_id) continue ; 00509 b.confidence = (float) ans.x.get(1, h, w); 00510 // confidence is below threshold, ignore 00511 if (b.confidence < threshold) continue ; 00512 // not negative, enqueue 00513 b.h0 = tl.offset(1) + h * hf; 00514 b.w0 = tl.offset(2) + w * wf; 00515 b.o.h0 = h; // answer height in output 00516 b.o.w0 = w; // answer height in output 00517 b.oscale_index = o; 00518 pos2.push_back_new(b); 00519 } 00520 } 00521 // sort positives by confidence 00522 pos2.sort_by_confidence(); 00523 // extract nmax most confident 00524 for (uint i = 0; i < pos2.size() && res2.size() < nmax; ++i) { 00525 bbox &b = pos2[i]; 00526 bbox b2 = b; 00527 b2.scale_centered(hscale, wscale); 00528 bool accept = true; 00529 // check that b doesn't overlap more than matching with filtered gt 00530 for (bboxes::iterator j = filtered.begin();j != filtered.end();++j){ 00531 if (b.class_id == j->class_id && b2.match(*j) > matching) { 00532 accept = false; 00533 break ; 00534 } 00535 } 00536 if (!accept) continue ; 00537 // check that b doesn't overlap at all with non-filtered gt 00538 for (bboxes::iterator j = nonfiltered.begin(); 00539 j != nonfiltered.end(); ++j) { 00540 if (b.overlap(*j)) { 00541 accept = false; 00542 break ; 00543 } 00544 } 00545 if (!accept) continue ; 00546 // check that b doesn't overlap at all with other accepted positives 00547 for (bboxes::iterator j = res2.begin();j != res2.end();++j){ 00548 if (b.overlap(*j)) { 00549 accept = false; 00550 break ; 00551 } 00552 } 00553 if (!accept) continue ; 00554 // all checks passed, keep this box 00555 if (accept) res2.push_back(b); 00556 } 00557 res.push_back(res2); 00558 if (res2.size() == 0) eblwarn("no negatives found for scale " << o); 00559 } 00560 // set all boxes to negative id 00561 for (bboxes::iterator j = res.begin(); j != res.end(); ++j) 00562 j->class_id = neg_id; 00563 EDEBUG("negative bootstraps: " << res); 00564 return res; 00565 } 00566 00567 template <typename T, class Tstate> 00568 void bootstrapping<T,Tstate>::add_mirrors(svector<midx<T> > &samples, 00569 bboxes &boxes) { 00570 svector<midx<T> > mirrors; 00571 bboxes bmirrors; 00572 for (uint i = 0; i < samples.size(); ++i) { 00573 bbox &b = boxes[i]; 00574 midx<T> &s = samples[i]; 00575 midx<T> flipped = idx_flip(s, 2); 00576 mirrors.push_back_new(flipped); 00577 bmirrors.push_back_new(b); 00578 } 00579 samples.push_back(mirrors); 00580 boxes.push_back(bmirrors); 00581 } 00582 00583 } // end namespace ebl 00584 00585 #endif /* BOOTSTRAPPING_HPP_ */