00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #include <iostream>
00056 #include <fstream>
00057 #include <climits>
00058 #include <float.h>
00059 #include <cstring>
00060 #include <cerrno>
00061 #include <cmath>
00062 #include <vector>
00063 #include <utility>
00064 #include <algorithm>
00065
00066 #include <cvd/image_io.h>
00067 #include <cvd/random.h>
00068 #include <cvd/vector_image_ref.h>
00069
00070 #include <tag/tuple.h>
00071 #include <tag/stdpp.h>
00072 #include <tag/fn.h>
00073 #include <tag/printf.h>
00074
00075 #include <TooN/TooN.h>
00076
00077 #include "gvars_vector.h"
00078 #include "faster_tree.h"
00079 #include "faster_bytecode.h"
00080 #include "offsets.h"
00081 #include "utility.h"
00082 #include "load_data.h"
00083
00084
00085 using namespace std;
00086 using namespace CVD;
00087 using namespace tag;
00088 using namespace GVars3;
00089 using namespace TooN;
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 double sq(double d)
00101 {
00102 return d*d;
00103 }
00104
00105
00106
00107
00108
00109
00110 vector<int> range(int num)
00111 {
00112 vector<int> r;
00113
00114 for(int i=0; i < num; i++)
00115 r.push_back(i);
00116 return r;
00117 }
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 vector<ImageRef> generate_disc(int radius)
00132 {
00133 vector<ImageRef> ret;
00134 ImageRef p;
00135
00136 for(p.y = -radius; p.y <= radius; p.y++)
00137 for(p.x = -radius; p.x <= radius; p.x++)
00138 if((int)p.mag_squared() <= radius)
00139 ret.push_back(p);
00140 return ret;
00141 }
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 Image<bool> paint_circles(const vector<ImageRef>& corners, const vector<ImageRef>& circle, ImageRef size)
00154 {
00155 Image<bool> im(size, 0);
00156
00157
00158 for(unsigned int i=0; i < corners.size(); i++)
00159 for(unsigned int j=0; j < circle.size(); j++)
00160 if(im.in_image(corners[i] + circle[j]))
00161 im[corners[i] + circle[j]] = 1;
00162
00163 return im;
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 float compute_repeatability(const vector<vector<Image<array<float, 2> > > >& warps, const vector<vector<ImageRef> >& corners, int r, ImageRef size)
00177 {
00178 unsigned int n = corners.size();
00179
00180 vector<ImageRef> disc = generate_disc(r);
00181
00182 vector<Image<bool> > detected;
00183 for(unsigned int i=0; i < n; i++)
00184 detected.push_back(paint_circles(corners[i], disc, size));
00185
00186 int corners_tested = 0;
00187 int good_corners = 0;
00188
00189 for(unsigned int i=0; i < n; i++)
00190 for(unsigned int j=0; j < n; j++)
00191 {
00192 if(i==j)
00193 continue;
00194
00195 for(unsigned int k=0; k < corners[i].size(); k++)
00196 {
00197 ImageRef dest = ir_rounded(warps[i][j][corners[i][k]]);
00198
00199 if(dest.x != -1)
00200 {
00201 corners_tested++;
00202 if(detected[j][dest])
00203 good_corners++;
00204 }
00205 }
00206 }
00207
00208 return 1.0 * good_corners / (DBL_EPSILON + corners_tested);
00209 }
00210
00211
00212
00213
00214
00215
00216
00217
00218 tree_element* random_tree(int d, bool is_eq_branch=1)
00219 {
00220
00221
00222
00223 if(d== 0)
00224 if(is_eq_branch)
00225 return new tree_element(0);
00226 else
00227 return new tree_element(rand()%2);
00228 else
00229 return new tree_element(random_tree(d-1, 0), random_tree(d-1, 1), random_tree(d-1, 0), rand()%num_offsets );
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 double compute_temperature(int i, int imax)
00242 {
00243 double scale=GV3::get<double>("Temperature.expo.scale");
00244 double alpha = GV3::get<double>("Temperature.expo.alpha");
00245
00246 return scale * exp(-alpha * i / imax);
00247 }
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 tree_element* learn_detector(const vector<Image<byte> >& images, const vector<vector<Image<array<float,2> > > >& warps)
00259 {
00260 unsigned int iterations=GV3::get<unsigned int>("iterations");
00261 int threshold = GV3::get<int>("FAST_threshold");
00262 int fuzz_radius=GV3::get<int>("fuzz");
00263 double repeatability_scale = GV3::get<double>("repeatability_scale");
00264 double num_cost = GV3::get<double>("num_cost");
00265 int max_nodes = GV3::get<int>("max_nodes");
00266
00267 bool first_time = 1;
00268 double old_cost = HUGE_VAL;
00269
00270 ImageRef image_size = images[0].size();
00271
00272 set<int> debug_triggers = GV3::get<set<int> >("triggers");
00273
00274
00275 Image<int> scratch_scores(image_size, 0);
00276
00277
00278 tree_element* tree = random_tree(GV3::get<int>("initial_tree_depth"));
00279
00280 for(unsigned int itnum=0; itnum < iterations; itnum++)
00281 {
00282 if(debug_triggers.count(itnum))
00283 GUI.ParseLine(GV3::get<string>(sPrintf("trigger.%i", itnum)));
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309 tree_element* new_tree = tree->copy();
00310
00311 cout << "\n\n-------------------------------------\n";
00312 cout << print << "Iteration" << itnum;
00313
00314 if(GV3::get<bool>("debug.print_old_tree"))
00315 {
00316 cout << "Old tree is:" << endl;
00317 tree->print(cout);
00318 }
00319
00320
00321
00322 if(!first_time)
00323 {
00324
00325
00326 tree_element* node;
00327 bool node_is_eq;
00328
00329
00330
00331 int nnum = rand() % new_tree->num_nodes();
00332 rpair(node, node_is_eq) = new_tree->nth_element(nnum);
00333
00334 cout << "Permuting tree at node " << nnum << endl;
00335 cout << print << "Node" << node << node_is_eq;
00336
00337
00338
00339 if(node->eq == NULL)
00340 {
00341 if(rand() % 2 || node_is_eq)
00342 {
00343 cout << "Growing a subtree:\n";
00344
00345 tree_element* stub = random_tree(1);
00346
00347 stub->print(cout);
00348
00349
00350 *node = *stub;
00351 stub->lt = stub->eq = stub->gt = 0;
00352 delete stub;
00353
00354 }
00355 else
00356 {
00357 cout << "Flipping the classification\n";
00358 node->is_corner = ! node->is_corner;
00359 }
00360 }
00361 else
00362 {
00363 double d = rand_u();
00364
00365 if(d < 1./3.)
00366 {
00367 cout << "Randomizing the test\n";
00368 node->offset_index = rand() % num_offsets;
00369 }
00370 else if(d < 2./3.)
00371 {
00372
00373 int r = rand() % 3;
00374 int c;
00375 while((c = rand()%3) == r){}
00376
00377 cout << "Copying branches " << c << " to " << r <<endl;
00378
00379
00380 tree_element* tmp;
00381
00382 if(c == 0)
00383 tmp = node->lt->copy();
00384 else if(c == 1)
00385 tmp = node->eq->copy();
00386 else
00387 tmp = node->gt->copy();
00388
00389
00390 if(r == 0)
00391 {
00392 delete node->lt;
00393 node->lt = tmp;
00394 }
00395 else if(r == 1)
00396 {
00397 delete node->eq;
00398 node->eq = tmp;
00399 }
00400 else
00401 {
00402 delete node->gt;
00403 node->gt = tmp;
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 if(node->eq->is_leaf())
00417 node->eq->is_corner = 0;
00418
00419
00420
00421
00422
00423
00424 }
00425 else
00426 {
00427 cout << "Splat!!!1\n";
00428 delete node->lt;
00429 delete node->eq;
00430 delete node->gt;
00431 node->lt = node->eq = node->gt = 0;
00432
00433 if(node_is_eq)
00434 node->is_corner = 0;
00435 else
00436 node->is_corner = rand()%2;
00437 }
00438 }
00439 }
00440 first_time=0;
00441
00442 if(GV3::get<bool>("debug.print_new_tree"))
00443 {
00444 cout << "New tree is: "<< endl;
00445 new_tree->print(cout);
00446 }
00447
00448
00449
00450 vector<vector<ImageRef> > detected_corners;
00451 for(unsigned int i=0; i < images.size(); i++)
00452 detected_corners.push_back(tree_detect_corners(images[i], new_tree, threshold, scratch_scores));
00453
00454
00455
00456 double repeatability = compute_repeatability(warps, detected_corners, fuzz_radius, image_size);
00457 double repeatability_cost = 1 + sq(repeatability_scale/repeatability);
00458
00459
00460 float number_cost=0;
00461 for(unsigned int i=0; i < detected_corners.size(); i++)
00462 {
00463 double cost = sq(detected_corners[i].size() / num_cost);
00464 cout << print << "Image" << i << detected_corners[i].size()<< cost;
00465 number_cost += cost;
00466 }
00467 number_cost = 1 + number_cost / detected_corners.size();
00468 cout << print << "Number cost" << number_cost;
00469
00470
00471 double size_cost = 1 + sq(1.0 * new_tree->num_nodes()/max_nodes);
00472
00473
00474 double cost = size_cost * repeatability_cost * number_cost;
00475
00476 double temperature = compute_temperature(itnum,iterations);
00477
00478
00479
00480
00481
00482
00483 double liklihood=exp((old_cost-cost) / temperature);
00484
00485
00486 cout << print << "Temperature" << temperature;
00487 cout << print << "Number cost" << number_cost;
00488 cout << print << "Repeatability" << repeatability << repeatability_cost;
00489 cout << print << "Nodes" << new_tree->num_nodes() << size_cost;
00490 cout << print << "Cost" << cost;
00491 cout << print << "Old cost" << old_cost;
00492 cout << print << "Liklihood" << liklihood;
00493
00494
00495 if(rand_u() < liklihood)
00496 {
00497 cout << "Keeping change" << endl;
00498 old_cost = cost;
00499 delete tree;
00500 tree = new_tree;
00501 }
00502 else
00503 {
00504 cout << "Rejecting change" << endl;
00505 delete new_tree;
00506 }
00507
00508 cout << print << "Final cost" << old_cost;
00509
00510 }
00511
00512
00513 return tree;
00514 }
00515
00516
00517
00518
00519
00520
00521
00522 void run_learn_detector(int argc, char** argv)
00523 {
00524
00525
00526 GUI.LoadFile("learn_detector.cfg");
00527 GUI.parseArguments(argc, argv);
00528
00529
00530
00531 if(GV3::get<int>("random_seed") != -1)
00532 srand(GV3::get<int>("random_seed"));
00533
00534
00535 create_offsets();
00536 draw_offsets();
00537
00538
00539
00540 string dir=GV3::get<string>("repeatability_dataset.directory");
00541 string format=GV3::get<string>("repeatability_dataset.format");
00542 int num=GV3::get<int>("repeatability_dataset.size");
00543
00544 vector<Image<byte> > images;
00545 vector<vector<Image<array<float, 2> > > > warps;
00546
00547 rpair(images, warps) = load_data(dir, num, format);
00548
00549 prune_warps(warps, images[0].size());
00550
00551
00552
00553 tree_element* tree = learn_detector(images, warps);
00554
00555
00556 cout << "Final tree is:" << endl;
00557 tree->print(cout);
00558 cout << endl;
00559
00560 cout << "Final block detector is:" << endl;
00561 {
00562 block_bytecode f = tree->make_fast_detector(9999);
00563 f.print(cout, 9999);
00564 }
00565 }
00566
00567
00568
00569
00570
00571
00572 int main(int argc, char** argv)
00573 {
00574 try
00575 {
00576 run_learn_detector(argc, argv);
00577 }
00578 catch(Exceptions::All w)
00579 {
00580 cerr << "Error: " << w.what << endl;
00581 }
00582 }
00583
00584
00585
00586
00587
00588
00589