00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <iostream>
00021 using namespace std;
00022 #include "kpttracker.h"
00023 #ifdef WITH_FAST
00024 #include "fast.h"
00025 #endif
00026 #include "mylkpyramid.h"
00027 #include <stack>
00028 #ifdef _OPENMP
00029 #include <omp.h>
00030 #endif
00031 #include "timer.h"
00032
00033 #ifdef WITH_ADAPT_THRESH
00034 #include <adapt_thresh.h>
00035 #endif
00036
00037 #ifdef WIN32
00038 static inline double drand48() {
00039 return (double)rand()/(double)RAND_MAX;
00040 }
00041
00042 #ifdef max
00043 #undef max
00044 #endif
00045 #ifdef min
00046 #undef min
00047 #endif
00048 #endif
00049
00050 int ncc_calls=0;
00051
00052 float cmp_ncc(pyr_keypoint *a, pyr_keypoint *b);
00053
00054 void pyr_keypoint::dispose() {
00055 pyr_frame *f = static_cast<pyr_frame *>(frame);
00056 unlink();
00057 if (f)
00058 f->tracker->kpt_recycler.recycle(this);
00059 else
00060 delete this;
00061 }
00062
00063 kpt_tracker::~kpt_tracker() {
00064 clear();
00065 kpt_recycler.clear();
00066 if (tree) delete tree;
00067 if (id_clusters) delete id_clusters;
00068 #ifdef WITH_YAPE
00069 if (detector) delete detector;
00070 if (points) delete[] points;
00071 #endif
00072 #ifdef WITH_ADAPT_THRESH
00073 cvReleaseMat(&adapt_thresh_mat);
00074 #endif
00075 }
00076
00077 void kpt_tracker::clear() {
00078 while (frames) remove_unmatched_tracks(frame_iterator(this));
00079 }
00080
00081 static void license() {
00082 static bool printed=false;
00083 if (!printed) {
00084 printed=true;
00085 std::cerr <<
00086 " Polyora, Copyright (c) 2010 Julien Pilet\n"
00087 " Polyora comes with ABSOLUTELY NO WARRANTY; see LICENSE.txt.\n"
00088 " This is free software, and you are welcome to redistribute it under certain conditions; see LICENSE.txt.\n";
00089 }
00090 }
00091
00092 pyr_keypoint::pyr_keypoint_factory_t default_pyr_keypoint_factory;
00093 pyr_frame::pyr_frame_factory_t default_pyr_frame_factory;
00094 pyr_track::pyr_track_factory_t default_pyr_track_factory;
00095
00096 kpt_tracker::kpt_tracker(int width, int height, int levels, int max_motion, bool glContext,
00097 pyr_keypoint::pyr_keypoint_factory_t *kf,
00098 pyr_frame::pyr_frame_factory_t *ff,
00099 pyr_track::pyr_track_factory_t *tf )
00100 : tracks((kf?kf:&default_pyr_keypoint_factory),(ff?ff:&default_pyr_frame_factory),(tf?tf:&default_pyr_track_factory)),
00101 nb_points(0), max_motion(max_motion), nb_levels(levels),
00102 kpt_recycler(kf?kf:&default_pyr_keypoint_factory)
00103 {
00104 license();
00105 patch_size= patch_tagger::patch_size;
00106
00107 ncc_threshold=.88;
00108 ncc_threshold_high=.9;
00109 tree=0;
00110 id_clusters=0;
00111 pipeline_stage1=0;
00112
00113 #ifdef WITH_YAPE
00114 detector = new pyr_yape(width, height, levels);
00115 detector->set_radius(5);
00116 points = new keypoint[10000];
00117 #endif
00118 #ifdef WITH_SIFTGPU
00119
00120 char * argv[] ={ "-s", "-v", "0", "-fo", "0", "-pack" };
00121 sift.ParseParam(sizeof(argv)/sizeof(char *), argv);
00122
00123 int support;
00124 if (glContext)
00125 support = sift.VerifyContextGL();
00126 else
00127 support = sift.CreateContextGL();
00128 if(support != SiftGPU::SIFTGPU_FULL_SUPPORTED) {
00129 cerr << "no suitable hardware/driver for SiftGPU !\n";
00130 exit(-1);
00131 }
00132
00133 assert(sizeof(kmean_tree::descriptor_t) == 128*sizeof(float));
00134 #endif
00135 #ifdef WITH_ADAPT_THRESH
00136 adapt_thresh_mat = cvCreateMat(2000,2,CV_32F);
00137 #endif
00138 }
00139
00140 bool kpt_tracker::load_tree(sqlite3 *db)
00141 {
00142 if (db==0) return false;
00143
00144
00145 tree= kmean_tree::load(db);
00146 if (!tree) {
00147 std::cout << "Failed to load tree from database.\n";
00148 return false;
00149 }
00150 return true;
00151 }
00152
00153 bool kpt_tracker::load_clusters(sqlite3 *db)
00154 {
00155 if (db==0) return false;
00156
00157 if (id_clusters)
00158 delete id_clusters;
00159 id_clusters = new id_cluster_collection( id_cluster_collection::QUERY_NORMALIZED_FREQ );
00160 return id_clusters->load(db);
00161 }
00162
00163 bool kpt_tracker::load_from_db(const char *dbfile)
00164 {
00165 sqlite3 *db;
00166 int rc = sqlite3_open_v2(dbfile, &db, SQLITE_OPEN_READONLY, 0);
00167 if (rc) return false;
00168 bool r = load_from_db(db);
00169 sqlite3_close(db);
00170 return r;
00171 }
00172
00173 bool kpt_tracker::load_from_db(sqlite3 *db)
00174 {
00175 return load_tree(db) && load_clusters(db);
00176 }
00177
00178 bool kpt_tracker::load_tree(const char *fn)
00179 {
00180 tree= kmean_tree::load(fn);
00181 if (!tree)
00182 std::cout << fn << ": failed to load tree.\n";
00183
00184 return tree!=0;
00185 }
00186
00187 bool kpt_tracker::load_clusters(const char *fn)
00188 {
00189 if (id_clusters)
00190 delete id_clusters;
00191 id_clusters = new id_cluster_collection( id_cluster_collection::QUERY_NORMALIZED_FREQ );
00192 if (!id_clusters->load(fn)) {
00193 std::cerr << "clusters.bin: failed to load id clusters.\n";
00194 delete id_clusters;
00195 id_clusters=0;
00196 return false;
00197 }
00198 return true;
00199 }
00200
00201 void kpt_tracker::set_size(int width, int height, int levels, int )
00202 {
00203 nb_levels = levels;
00204 #ifdef WITH_YAPE
00205 delete detector;
00206 detector = new pyr_yape(width,height,levels);
00207 #endif
00208 #ifdef WITH_SIFTGPU
00209 sift.AllocatePyramid(width,height);
00210 #endif
00211 }
00212
00213 pyr_frame *kpt_tracker::process_frame_pipeline(IplImage *im) {
00214 pyr_frame *new_f=0;
00215 if (im) new_f = create_frame(im);
00216 #pragma omp parallel
00217 {
00218 #pragma omp master
00219 {
00220 if (im) {
00221
00222 new_f->pyr->build();
00223
00224
00225 detect_keypoints(new_f);
00226
00227 }
00228 }
00229 #pragma omp single
00230 {
00231 if (pipeline_stage1) {
00232 traverse_tree(pipeline_stage1);
00233 pipeline_stage1->append_to(*this);
00234 track_ncclk(pipeline_stage1, (pyr_frame *)get_nth_frame(1));
00235 }
00236 }
00237 }
00238 pyr_frame *out = pipeline_stage1;
00239 pipeline_stage1 = new_f;
00240 return out;
00241 }
00242
00243 pyr_frame *kpt_tracker::process_frame(IplImage *im) {
00244 pyr_frame *f = create_frame(im);
00245 TaskTimer::pushTask("pyramid");
00246 f->pyr->build();
00247 TaskTimer::popTask();
00248 TaskTimer::pushTask("Feature detection");
00249 detect_keypoints(f);
00250 TaskTimer::popTask();
00251 traverse_tree(f);
00252 f->append_to(*this);
00253 track_ncclk(f, (pyr_frame *)get_nth_frame(1));
00254 return f;
00255 }
00256
00257 pyr_frame::pyr_frame(PyrImage *p, int bits) :
00258 tframe(p->images[0]->width, p->images[0]->height, bits),
00259 pyr(p), tracker(0)
00260 {
00261 }
00262
00263 void pyr_frame::append_to(tracks &t)
00264 {
00265 tframe::append_to(t);
00266 tracker=static_cast<kpt_tracker *>(&t);
00267 }
00268
00269 pyr_frame *kpt_tracker::add_frame(IplImage *im)
00270 {
00271 pyr_frame *f = create_frame(im);
00272 f->pyr->build();
00273 f->append_to(*this);
00274 return f;
00275 }
00276
00277 pyr_frame *kpt_tracker::create_frame(IplImage *im)
00278 {
00279
00280
00281 pyr_frame *lf = (pyr_frame *) get_nth_frame(3);
00282 PyrImage *p;
00283 if (lf && lf->pyr) {
00284 p = lf->pyr;
00285 lf->pyr=0;
00286 cvReleaseImage(&p->images[0]);
00287 p->images[0] = im;
00288 } else {
00289 p = new PyrImage(im, nb_levels, false);
00290 }
00291
00292
00293 pyr_frame *f = (pyr_frame*)(((pyr_frame::pyr_frame_factory_t *) tframe_factory)->create(p,4));
00294
00295 return f;
00296 }
00297
00298
00299 void kpt_tracker::detect_keypoints(pyr_frame *f) {
00300
00301 f->tracker = this;
00302 #ifdef WITH_YAPE
00303
00304 TaskTimer::pushTask("yape");
00305 nb_points = detector->detect(f->pyr, points, 800);
00306 TaskTimer::popTask();
00307
00308 TaskTimer::pushTask("descriptor");
00309
00310 for (int i=0; i<nb_points; i++) {
00311
00312 pyr_keypoint *p = kpt_recycler.get_new();
00313 p->set(f,points[i],patch_size);
00314
00315 if (p->stdev < 10*10) {
00316 p->dispose();
00317 }
00318 else {
00319 assert(p->descriptor.total>0);
00320 }
00321
00322
00323
00324 }
00325 TaskTimer::popTask();
00326 #endif
00327
00328 #ifdef WITH_FAST
00329 for (int l=1; l<f->pyr->nbLev; ++l) {
00330 IplImage *im = f->pyr->images[l];
00331 int npts=1000;
00332 xy *pts = fast11_detect_nonmax((byte *)im->imageData, im->width, im->height, im->widthStep, 10, &npts);
00333
00334 for (int i=0;i<npts; i++) {
00335 pyr_keypoint *p = kpt_recycler.get_new();
00336 p->set(f, pts[i].x, pts[i].y, l, patch_size);
00337 if (p->stdev < 10*10) p->dispose();
00338 }
00339 free(pts);
00340 }
00341 #endif
00342
00343 #ifdef WITH_MSER
00344 cv::Mat _f(f->pyr->images[1]);
00345 int npts = mser.mser(_f, cv::Mat());
00346 for (MSERDetector::iterator i = mser.begin(); --npts>=0; ++i)
00347 {
00348 pyr_keypoint *p = kpt_recycler.get_new();
00349 MSERDetector::Contour contour(*i);
00350 mser.getRegion(contour, p->mser);
00351
00352 float mag=2;
00353 p->mser.c.x *= 2; p->mser.c.y *= 2;
00354 p->mser.e1.x *= mag*2; p->mser.e1.y *= mag*2;
00355 p->mser.e2.x *= mag*2; p->mser.e2.y *= mag*2;
00356
00357 p->set(f, p->mser.c.x, p->mser.c.y, 0, patch_size);
00358 if (p->descriptor.total==0) p->dispose();
00359 }
00360 #endif
00361
00362 #ifdef WITH_ADAPT_THRESH
00363 for (int l=0; l<f->pyr->nbLev; ++l) {
00364 IplImage *im = f->pyr->images[l];
00365 int npts= detectAdaptiveTresholdKeypoints(im, adapt_thresh_mat);
00366
00367 float *pts = &CV_MAT_ELEM(*adapt_thresh_mat, float, 0, 0);
00368 for (int i=0;i<npts; i++) {
00369 pyr_keypoint *p = kpt_recycler.get_new();
00370 p->set(f, pts[i*2], pts[i*2+1], l, patch_size);
00371 if (p->stdev < 10*10) p->dispose();
00372 }
00373 }
00374 #endif
00375
00376 #ifdef WITH_SURF
00377 CvSeq *surf_pts=0;
00378 CvSeq *surf_descr=0;
00379 CvMemStorage* storage = cvCreateMemStorage(0);
00380 CvSURFParams params = cvSURFParams(500, 1);
00381 cvExtractSURF(f->pyr->images[0], 0, &surf_pts, &surf_descr, storage, params);
00382 int tot = surf_pts->total;
00383 CvSeqReader reader, descr;
00384 cvStartReadSeq(surf_pts, &reader);
00385 cvStartReadSeq(surf_descr, &descr);
00386 for (int i=0; i<tot; i++) {
00387 CvSURFPoint *s = (CvSURFPoint *) reader.ptr;
00388 const float *d = (const float *) descr.ptr;
00389 CV_NEXT_SEQ_ELEM(reader.seq->elem_size, reader);
00390 CV_NEXT_SEQ_ELEM(descr.seq->elem_size, descr);
00391 pyr_keypoint *p = kpt_recycler.get_new();
00392 p->set(f, s->pt.x, s->pt.y, 0, patch_size);
00393 p->descriptor.orientation = (360-s->dir) * M_PI / 180.0f;
00394 memcpy(p->surf_descriptor.descriptor, d, sizeof(p->surf_descriptor));
00395 p->id = 0;
00396 p->cid=0;
00397
00398
00399 }
00400 cvReleaseMemStorage( &storage );
00401 #endif
00402
00403 #ifdef WITH_GOOD_FEATURES_TO_TRACK
00404
00405 PyrImage eig(cvCreateImage(cvGetSize(f->pyr->images[0]), IPL_DEPTH_32F, 1), f->pyr->nbLev);
00406 PyrImage tmp(cvCreateImage(cvGetSize(f->pyr->images[0]), IPL_DEPTH_32F, 1), f->pyr->nbLev);
00407 CvPoint2D32f corners[2048];
00408 int total=0;
00409 int r = 1;
00410 for (int l=f->pyr->nbLev-1; l>=0; --l, r*=2) {
00411 IplImage *im = f->pyr->images[l];
00412 int cnt=2048;
00413 cvGoodFeaturesToTrack(im, eig[l], tmp[l], corners, &cnt, .01, r);
00414 cvFindCornerSubPix(im, corners, cnt, cvSize(5,5), cvSize(-1,-1),
00415 cvTermCriteria(CV_TERMCRIT_ITER| CV_TERMCRIT_EPS, 3, 0.01));
00416 for (int i=0; i<cnt; i++) {
00417 if (!f->has_point_in(corners[i].x, corners[i].y, r)) {
00418 pyr_keypoint *p = kpt_recycler.get_new();
00419 p->set(f, corners[i].x, corners[i].y, l, patch_size);
00420 if (total++ > 1500) break;
00421
00422 }
00423 }
00424 }
00425 #endif
00426
00427 #ifdef WITH_SIFTGPU
00428 TaskTimer::pushTask("SiftGPU");
00429 IplImage *im = f->pyr->images[0];
00430 sift.RunSIFT(im->width, im->height, im->imageData, GL_LUMINANCE, GL_UNSIGNED_BYTE);
00431 int num = sift.GetFeatureNum();
00432
00433
00434 vector<float> descriptors(128*num);
00435 vector<SiftGPU::SiftKeypoint> keys(num);
00436
00437
00438 if (num) {
00439 sift.GetFeatureVector(&keys[0], &descriptors[0]);
00440 TaskTimer::popTask();
00441 TaskTimer::pushTask("descriptor & tree");
00442 for (int i=0; i<num; i++) {
00443 pyr_keypoint *p = kpt_recycler.get_new();
00444 p->set(f, keys[i].x/2, keys[i].y/2, 1, patch_size);
00445 memcpy(&(p->sift_descriptor), &descriptors[i*128], sizeof(float)*128);
00446 p->descriptor.orientation = keys[i].o;
00447 p->id = 0;
00448 }
00449 }
00450 TaskTimer::popTask();
00451 #endif
00452 }
00453
00454 void kpt_tracker::track_ncclk(pyr_frame *f, pyr_frame *lf)
00455 {
00456
00457 ncc_calls=0;
00458 if (!f || !lf) return;
00459 assert(f->tracker == this);
00460 assert(lf->tracker == this);
00461
00462 TaskTimer::pushTask("Feature tracking");
00463 TaskTimer::pushTask("NCC frame-to-frame matching");
00464
00465 int nmatches=0;
00466 for (keypoint_frame_iterator it(lf->points.begin()); !it.end(); ++it) {
00467 pyr_keypoint *kpt = (pyr_keypoint *) it.elem();
00468 float ku = kpt->u;
00469 float kv = kpt->v;
00470 if (kpt->matches.prev) {
00471
00472 ku = (ku - kpt->matches.prev->u) + ku;
00473 kv = (kv - kpt->matches.prev->v) + kv;
00474 }
00475 pyr_keypoint *r = best_match(kpt, f->points.search(ku, kv, max_motion));
00476 if (r) {
00477 if (!r->matches.prev) {
00478 nmatches++;
00479 set_match(kpt, r);
00480 } else {
00481
00482 unset_match(r);
00483 }
00484 }
00485 }
00486
00487
00488
00489 if (0)
00490 for (keypoint_frame_iterator it(f->points.begin()); !it.end(); ++it)
00491 {
00492 pyr_keypoint *k = (pyr_keypoint *) it.elem();
00493 pyr_keypoint *r = best_match(k, lf->points.search(k->u, k->v, max_motion));
00494 if (r) {
00495 if (r->matches.next != k) {
00496
00497 if (r->matches.next) {
00498 unset_match(r->matches.next);
00499 }
00500 if (k->matches.prev) {
00501 unset_match(k);
00502 }
00503 }
00504 }
00505 }
00506
00507 TaskTimer::popTask();
00508 TaskTimer::pushTask("LK tracking");
00509
00510 int nft=0;
00511 #define MAX_TRACK_FT 512
00512 CvPoint2D32f prev_ft[MAX_TRACK_FT];
00513 pyr_keypoint* prev_kpt[MAX_TRACK_FT];
00514 char lk_status[MAX_TRACK_FT];
00515 CvPoint2D32f curr_ft[MAX_TRACK_FT];
00516
00517
00518
00519 for (keypoint_frame_iterator it(lf->points.begin()); !it.end(); ++it) {
00520 pyr_keypoint *k = (pyr_keypoint *) it.elem();
00521
00522 if (k->matches.next==0 && k->track_is_longer(4)
00523 && ((pyr_track*)k->track)->nb_lk_tracked <= k->track_length()/2) {
00524 float ku = k->u;
00525 float kv = k->v;
00526 prev_ft[nft].x = ku;
00527 prev_ft[nft].y = kv;
00528
00529 curr_ft[nft].x = (ku - k->matches.prev->u) + ku;
00530 curr_ft[nft].y = (kv - k->matches.prev->v) + kv;
00531 prev_kpt[nft] = k;
00532 nft++;
00533 if (nft>=MAX_TRACK_FT) break;
00534
00535 }
00536 }
00537 myCalcOpticalFlowPyrLK(lf->pyr, f->pyr,
00538 prev_ft, curr_ft, nft, cvSize(patch_size,patch_size), f->pyr->nbLev, lk_status,
00539 0, cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,3,0.1), CV_LKFLOW_INITIAL_GUESSES);
00540 int nsaved=0;
00541 #ifdef WITH_SIFTGPU
00542 vector<pyr_keypoint *> need_descriptors;
00543 vector<SiftGPU::SiftKeypoint> keys;
00544 need_descriptors.reserve(2000);
00545 keys.reserve(2000);
00546 #endif
00547
00548 for (int i=0; i<nft; i++) {
00549 if (!lk_status[i]) continue;
00550
00551 pyr_keypoint *closest = (pyr_keypoint *) f->points.closest_point(curr_ft[i].x, curr_ft[i].y, 2);
00552 if (closest) {
00553 if (closest->matches.prev==0) {
00554 set_match(prev_kpt[i], closest);
00555 static_cast<pyr_track *>(closest->track)->nb_lk_tracked++;
00556 }
00557 } else {
00558 pyr_keypoint *newkpt = kpt_recycler.get_new();
00559 float s = 1.0f/(1<<(int)prev_kpt[i]->scale);
00560 newkpt->set(f,curr_ft[i].x*s, curr_ft[i].y*s, prev_kpt[i]->scale, patch_size);
00561 newkpt->score = prev_kpt[i]->score;
00562 #ifdef WITH_SURF
00563 newkpt->id = prev_kpt[i]->id;
00564 newkpt->cid = prev_kpt[i]->cid;
00565 newkpt->descriptor.orientation = prev_kpt[i]->descriptor.orientation;
00566 newkpt->surf_descriptor.descriptor[0]=-1;
00567 #endif
00568 if (cmp_ncc(prev_kpt[i], newkpt)> ncc_threshold) {
00569 set_match(prev_kpt[i],newkpt);
00570 static_cast<pyr_track *>(newkpt->track)->nb_lk_tracked++;
00571 nsaved++;
00572
00573 #ifdef WITH_SIFTGPU
00574
00575
00576
00577 #ifdef COMPUTE_ADDITIONAL_SIFT_DESCRIPTORS
00578 SiftGPU::SiftKeypoint skp;
00579 skp.x = newkpt->u;
00580 skp.y = newkpt->v;
00581 skp.s = newkpt->scale;
00582 skp.o = 0;
00583 keys.push_back(skp);
00584 need_descriptors.push_back(newkpt);
00585 #else
00586 memcpy(&newkpt->sift_descriptor, &prev_kpt[i]->sift_descriptor, 128*sizeof(float));
00587 #endif
00588 #endif
00589 } else {
00590 newkpt->dispose();
00591 }
00592 }
00593 }
00594
00595 #if defined(WITH_SIFTGPU) && defined(COMPUTE_ADDITIONAL_SIFT_DESCRIPTORS)
00596
00597 TaskTimer::pushTask("SiftGPU");
00598 vector<float> descriptors(128*keys.size());
00599 sift.RunSIFT(keys.size(), &keys[0]);
00600 sift.GetFeatureVector(NULL, &descriptors[0]);
00601 for (unsigned i=0; i<keys.size(); i++)
00602 {
00603 memcpy(&(need_descriptors[i]->sift_descriptor), &descriptors[128*i], 128*sizeof(float));
00604 }
00605 TaskTimer::popTask();
00606 #endif
00607
00608
00609
00610
00611
00612
00613
00614
00615 TaskTimer::popTask();
00616 TaskTimer::popTask();
00617
00618 }
00619
00620 void pyr_keypoint::prepare_patch(int win_size)
00621 {
00622 TaskTimer::pushTask("descriptor");
00623 int half = win_size/2;
00624 win_size |= 1;
00625
00626 pyr_frame *f = static_cast<pyr_frame *>(frame);
00627
00628 int s = scale;
00629 IplImage *im = f->pyr->images[s];
00630
00631 float level_u = (s==scale? level.u : level.u/2);
00632 float level_v = (s==scale? level.v : level.v/2);
00633 CvRect rect = cvRect(level_u-half, level_v-half, win_size, win_size);
00634
00635
00636 if (((rect.x | rect.y) < 0) || (rect.x+rect.width> im->width) || (rect.y+rect.height> im->height))
00637
00638 {
00639 int aw = (win_size+3) & 0xfffffc;
00640 if (!data) data = new unsigned char[aw*aw];
00641 cvInitMatHeader(&patch, win_size, win_size, CV_8UC1, data, aw);
00642
00643 for (int j= -half; j<=half; j++) {
00644 int y= level_v+j;
00645 if (y<0) y=0;
00646 if (y>=im->height) y=im->height-1;
00647 unsigned char *d = data+(j+half)*aw;
00648
00649 for (int i= -half; i<=half; i++) {
00650
00651 int x= level_u+i;
00652 if (x<0) x=0;
00653 if (x>=im->width) x=im->width-1;
00654
00655 *d++ = CV_IMAGE_ELEM(im, unsigned char, y, x);
00656 }
00657 }
00658 } else {
00659 cvGetSubRect(im, &patch, rect);
00660 if (data) delete[] data;
00661 data=0;
00662 }
00663
00664 unsigned sum=0;
00665 unsigned sqsum=0;
00666
00667 for (int j=0; j<patch.rows; j++) {
00668 unsigned char *p = &CV_MAT_ELEM(patch, unsigned char, j, 0);
00669 for (int i=0; i<patch.cols; i++) {
00670 unsigned f = *p++;
00671 sum += f;
00672 sqsum += f*f;
00673 }
00674 }
00675 float n = (patch.rows*patch.cols);
00676 mean = sum/n;
00677 stdev = sqrtf(sqsum - n*mean*mean);
00678
00679 if (stdev < .1) {
00680 id=0;
00681 cid=0;
00682 descriptor.total=0;
00683 stdev=0;
00684 TaskTimer::popTask();
00685 return;
00686 }
00687
00688
00689 id = 0;
00690 cid=0;
00691
00692 #ifdef WITH_PATCH_TAGGER_DESCRIPTOR
00693 #ifdef WITH_MSER
00694
00695 cvInitMatHeader(&descriptor.rotated, patch_tagger::patch_size, patch_tagger::patch_size, CV_32FC1, descriptor._rotated);
00696 cv::Mat _rot(&descriptor.rotated);
00697 descriptor.orientation = atan2(mser.e1.y, mser.e1.x);
00698 if (descriptor.orientation<0) descriptor.orientation+=6.283185307179586476925286766559f;
00699
00700 descriptor.total= (get_mser_patch(*f->pyr, _rot) ? 1:0);
00701 descriptor.total= 1;
00702
00703 #else
00704 float subpix_x = level_u - floor(level_u);
00705 float subpix_y = level_v - floor(level_v);
00706
00707
00708 patch_tagger::singleton()->cmp_descriptor(&patch, &descriptor, subpix_x, subpix_y);
00709 #endif
00710
00711 if (descriptor.total ==0) {
00712 stdev=0;
00713 }
00714 #endif
00715 TaskTimer::popTask();
00716 }
00717
00718 void kpt_tracker::traverse_tree(pyr_frame *frame)
00719 {
00720 if (!tree || !frame) return ;
00721
00722 TaskTimer::pushTask("tree");
00723
00724 for (tracks::keypoint_frame_iterator it(frame->points.begin()); !it.end(); ++it) {
00725 pyr_keypoint *k = (pyr_keypoint *) it.elem();
00726 #ifdef WITH_PATCH_TAGGER_DESCRIPTOR
00727 kmean_tree::descriptor_t array;
00728 k->descriptor.array(array.descriptor);
00729 k->id = tree->get_id(&array, &k->node);
00730 #endif
00731 #ifdef WITH_SIFTGPU
00732 k->id = tree->get_id(&k->sift_descriptor, &k->node);
00733 #endif
00734 #ifdef WITH_SURF
00735 k->id = tree->get_id(&k->surf_descriptor, &k->node);
00736 #endif
00737 }
00738 TaskTimer::popTask();
00739 }
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757 pyr_keypoint::pyr_keypoint(const pyr_keypoint &a)
00758 : tkeypoint(a), scale(a.scale), level(a.level), mean(a.mean),
00759 stdev(a.stdev), id(a.id), cid(a.cid),
00760 #ifdef WITH_SURF
00761 surf_descriptor(a.surf_descriptor),
00762 #endif
00763 #ifdef WITH_SIFTGPU
00764 sift_descriptor(a.sift_descriptor),
00765 #endif
00766 descriptor(a.descriptor),
00767 node(a.node)
00768 {
00769 patch = a.patch;
00770 if (a.data) {
00771 int sz = patch.step * patch.rows;
00772 data = new unsigned char [sz];
00773 memcpy(data,a.data,sz);
00774 patch.data.ptr = data;
00775 } else {
00776 data=0;
00777 }
00778 }
00779
00780 const pyr_keypoint &pyr_keypoint::operator = (const pyr_keypoint &a)
00781 {
00782 tkeypoint::operator =(a);
00783 scale=a.scale;
00784 level=a.level;
00785 mean=a.mean;
00786 stdev=a.stdev;
00787 id=a.id;
00788 cid=a.cid;
00789 #ifdef WITH_SURF
00790 surf_descriptor=a.surf_descriptor;
00791 #endif
00792 #ifdef WITH_SIFTGPU
00793 sift_descriptor=a.sift_descriptor;
00794 #endif
00795 descriptor=a.descriptor;
00796 node=a.node;
00797 assert(data==0 || a.data==0 || a.patch.rows == patch.rows);
00798 patch = a.patch;
00799 if (a.data) {
00800 int sz = patch.step * patch.rows;
00801 if (data==0) data = new unsigned char [sz];
00802 memcpy(data,a.data,sz);
00803 patch.data.ptr = data;
00804 } else if (data) {
00805 delete[] data;
00806 data=0;
00807 }
00808 return *this;
00809 }
00810
00811
00812 void pyr_keypoint::set(tframe *f, keypoint &pt, int patch_size)
00813 {
00814 tkeypoint::set(f,pt.fr_u(), pt.fr_v());
00815 if (data) delete[] data;
00816 data=0;
00817 scale=pt.scale;
00818 score = pt.score;
00819 level.u = pt.u;
00820 level.v = pt.v;
00821 prepare_patch(patch_size);
00822 node=0;
00823 }
00824 void pyr_keypoint::set(tframe *f, float u, float v, int scale, int patch_size)
00825 {
00826 tkeypoint::set(f,u*(1<<scale),v*(1<<scale));
00827 if (data) delete[] data;
00828 data=0;
00829 score=0;
00830 this->scale = std::min(scale, ((pyr_frame *)f)->pyr->nbLev-1);
00831 level.u = u;
00832 level.v = v;
00833 prepare_patch(patch_size);
00834 node=0;
00835 }
00836
00837 pyr_keypoint::~pyr_keypoint() {
00838 if (data) delete[] data;
00839 data=0;
00840 }
00841
00842 #ifdef WITH_MSER
00843 bool pyr_keypoint::get_mser_patch(PyrImage &pyr, cv::Mat dst)
00844 {
00845 unsigned w = dst.cols;
00846 unsigned h = dst.rows;
00847 unsigned scale = std::min(unsigned(pyr.nbLev-1),(unsigned)max(0.0f,floorf(log2f(cv::norm(mser.e2)/w)+1)));
00848 float s(1.0f/(1 << scale));
00849
00850 float _a[] = {
00851 s*mser.e1.x*2.0f/w, s*mser.e2.x*2.0f/h, s*mser.c.x,
00852 s*mser.e1.y*2.0f/w, s*mser.e2.y*2.0f/h, s*mser.c.y
00853 };
00854
00855 CvMat A;
00856 cvInitMatHeader(&A, 2, 3, CV_32FC1, _a);
00857
00858 CvMat _dst = dst;
00859 cvGetQuadrangleSubPix(pyr[scale], &_dst, &A);
00860
00861 CvScalar mean, stdev;
00862
00863 cvAvgSdv(&_dst, &mean, &stdev);
00864
00865 if (stdev.val[0] < .0005) return false;
00866
00867 double div_sdv(.5/stdev.val[0]);
00868 dst = dst*div_sdv-mean.val[0]*div_sdv + .5;
00869 return true;
00870 }
00871 #endif
00872
00873
00874
00875 float cmp_ncc(pyr_keypoint *a, pyr_keypoint *b)
00876 {
00877 ncc_calls++;
00878
00879
00880 int w=a->patch.cols;
00881 int h=a->patch.rows;
00882
00883 int ma = a->mean;
00884 int mb = b->mean;
00885 int sum=0;
00886 float norm = (a->stdev*b->stdev);
00887 if (a->stdev < 1 || b->stdev<1) return 0;
00888
00889 if (a->id && a->id == b->id) return .95;
00890
00891
00892 for (int j=0; j<h; j++) {
00893 const unsigned char *pa = &CV_MAT_ELEM(a->patch, unsigned char, j, 0);
00894 const unsigned char *pb = &CV_MAT_ELEM(b->patch, unsigned char, j, 0);
00895 int i=w;
00896 do {
00897 sum += ((*pa++)-ma)*((*pb++)-mb);
00898 } while(--i);
00899
00900
00901 }
00902
00903 return sum/norm;
00904 }
00905
00906
00907 struct score_kpt {
00908 int score;
00909 pyr_keypoint *k;
00910 };
00911 bool operator <(score_kpt &a, score_kpt &b) {
00912 return a.score < b.score;
00913 }
00914 int score_kpt_cmp(const void *_a, const void *_b) {
00915 score_kpt *a = (score_kpt*)_a;
00916 score_kpt *b = (score_kpt*)_b;
00917 return (a->score < b->score ? 0 : 1);
00918 }
00919
00920 pyr_keypoint *kpt_tracker::best_match(pyr_keypoint *templ, tracks::keypoint_frame_iterator it)
00921 {
00922 if (it.end()) return 0;
00923
00924 pyr_keypoint *best_kpt=0;
00925 float best_corr=0;
00926
00927
00928 for ( ; !it.end(); ++it) {
00929 pyr_keypoint *k = (pyr_keypoint *) it.elem();
00930 float ncc = cmp_ncc(templ, k);
00931 if (ncc> best_corr) {
00932 best_corr = ncc;
00933 best_kpt = k;
00934 if (best_corr>ncc_threshold_high) break;
00935 }
00936 }
00937
00938 if (best_corr>ncc_threshold) return best_kpt;
00939 return 0;
00940 }
00941
00942 pyr_frame::~pyr_frame() {
00943 if (pyr) delete pyr;
00944 }
00945
00946 #if 0
00947 void kpt_tracker::match_template(pyr_keypoint *templ, pyr_frame *frame, float delta[2])
00948 {
00949
00950 point2d pos(templ->u,templ->v);
00951
00952
00953
00954 if (!templ || !frame || !frame->pyr || !frame->pyr->images[0]) return;
00955
00956
00957 int jacobian[PATCH_SIZE][PATCH_SIZE][2];
00958 float pseudo_inv[2][2];
00959
00960
00961 for (int y=0; y<templ->patch.rows-1; y++) {
00962 unsigned char *p = &CV_MAT_ELEM(templ->patch, unsigned char, y, 0);
00963 for (int x=0; x<templ->patch.cols-1; x++) {
00964 jacobian[y][x][0] = p[1]-p[0];
00965 jacobian[y][x][1] = p[templ->patch.step]-p[0];
00966 }
00967 }
00968 {
00969 int x = templ->patch.cols-1;
00970 unsigned char *p = &CV_MAT_ELEM(templ->patch, unsigned char, 0, x);
00971 for (int y=0; y<templ->patch.rows; y++) {
00972 jacobian[y][x][0] = jacobian[y][x-1][0];
00973
00974
00975
00976 CvRect r = cvRect(0,0, templ->patch.cols, templ->patch.rows);
00977 int half = templ->patch.cols/2;
00978
00979
00980 for (int iter=0; iter<10; iter++) {
00981 CvMat tg;
00982 r.x = pos.u - half;
00983 r.y = pos.v - half;
00984 cvGetSubRect(frame->pyr->images[level],&tg, r);
00985
00986 float JtD[2] = {0,0};
00987 for (int y=0;y<r.height;y++) {
00988 unsigned char *tp = &CV_MAT_ELEM(templ->patch, unsigned char, y, 0);
00989 unsigned char *ip = &CV_MAT_ELEM(tg, unsigned char, y, 0);
00990 for (int x=0; x<r.width; x++) {
00991 int err = ip[x] - tp[x];
00992 JtD[0] += jacobian[y][x][0]*err;
00993 JtD[1] += jacobian[y][x][1]*err;
00994 }
00995 }
00996 pos.u -= pseudo_inv[0][0]*JtD[0] + pseudo_inv[0][1]*JtD[1];
00997 pos.v -= pseudo_inv[1][0]*JtD[0] + pseudo_inv[1][1]*JtD[1];
00998 }
00999 }
01000 #endif
01001
01002 pyr_track::pyr_track(tracks *db) : ttrack(db), id_histo(0), nb_lk_tracked(0) {}
01003
01004 void pyr_track::point_added(tkeypoint *p)
01005 {
01006 ttrack::point_added(p);
01007
01008 pyr_keypoint *pk = (pyr_keypoint *) p;
01009 pyr_frame *f = (pyr_frame *)pk->frame;
01010 id_histo.database = f->tracker->id_clusters;
01011 if (pk->id) {
01012 TaskTimer::pushTask("Cluster retrieval");
01013 id_histo.modify(pk->id,1);
01014
01015
01016 if (f->tracker->id_clusters && id_histo.query_cluster.total>0) {
01017 incremental_query::iterator it = id_histo.sort_results_min_ratio(.98);
01018
01019 if (it != id_histo.end()) {
01020 pk->cid = it->c->id;
01021 pk->cscore = it->score;
01022 } else
01023 pk->cid=0;
01024 }
01025 TaskTimer::popTask();
01026 } else {
01027 pk->cid=0;
01028 }
01029 }
01030
01031 void pyr_track::point_removed(tkeypoint *p)
01032 {
01033 ttrack::point_removed(p);
01034 pyr_keypoint *pk = (pyr_keypoint *) p;
01035 if (pk->id) id_histo.modify(pk->id, -1);
01036 }