EC.h
Go to the documentation of this file.
1 /*
2  * This file is part of ALVAR, A Library for Virtual and Augmented Reality.
3  *
4  * Copyright 2007-2012 VTT Technical Research Centre of Finland
5  *
6  * Contact: VTT Augmented Reality Team <alvar.info@vtt.fi>
7  * <http://www.vtt.fi/multimedia/alvar.html>
8  *
9  * ALVAR is free software; you can redistribute it and/or modify it under the
10  * terms of the GNU Lesser General Public License as published by the Free
11  * Software Foundation; either version 2.1 of the License, or (at your option)
12  * any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
17  * for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with ALVAR; if not, see
21  * <http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html>.
22  */
23 
24 #ifndef EC_H
25 #define EC_H
26 
34 #include "TrackerFeatures.h"
35 #include "Camera.h"
36 #include "MarkerDetector.h"
37 #include "MultiMarker.h"
38 
39 namespace alvar {
40 
153 public:
154  int type_id;
155  bool has_p2d;
156  bool has_p3d;
157  CvPoint2D32f p2d;
158  CvPoint3D32f p3d;
159  CvPoint2D32f projected_p2d; // This is only temporary -- user needs to take care that it has valid content
160  ExternalContainer() : type_id(-1), has_p2d(false), has_p3d(false) {}
162  type_id = c.type_id;
163  has_p2d = c.has_p2d;
164  has_p3d = c.has_p3d;
165  p2d.x = c.p2d.x;
166  p2d.y = c.p2d.y;
167  p3d.x = c.p3d.x;
168  p3d.y = c.p3d.y;
169  p3d.z = c.p3d.z;
170  projected_p2d.x = c.projected_p2d.x;
171  projected_p2d.y = c.projected_p2d.y;
172  }
173 };
174 
181 template<typename T>
183 protected:
184  int type_id;
187 public:
188  DoHandleTest(int _type_id=-1, bool _needs_has_p2d=false, bool _needs_has_p3d=false)
189  : type_id(_type_id), needs_has_p2d(_needs_has_p2d), needs_has_p3d(_needs_has_p3d) {}
190  virtual bool operator()(const T &f) const {
191  if (needs_has_p2d && !f.has_p2d) return false;
192  if (needs_has_p3d && !f.has_p3d) return false;
193  // if (f.type_id == -1) return false; // Unnecessary?
194  if ((type_id != -1) && (type_id != f.type_id)) return false;
195  return true;
196  }
197 };
198 
204 template<typename T>
205 class DoEraseTest {
206 protected:
207  int type_id;
211  float limit_sq;
212 public:
213  DoEraseTest(bool _erase_without_p2d, bool _erase_without_p3d, int _type_id=-1)
214  : type_id(_type_id), erase_without_p2d(_erase_without_p2d), erase_without_p3d(_erase_without_p3d),
215  test_reprojection(false), limit_sq(0.f) {}
216  DoEraseTest(float _limit, bool _erase_without_p2d=false, bool _erase_without_p3d=false, int _type_id=-1)
217  : type_id(_type_id), erase_without_p2d(_erase_without_p2d), erase_without_p3d(_erase_without_p3d),
218  test_reprojection(true), limit_sq(_limit*_limit) {}
219  virtual bool operator()(const T &f) const {
220  if ((type_id != -1) && (type_id != f.type_id)) return false;
221  if (erase_without_p2d && !f.has_p2d) return true;
222  if (erase_without_p3d && !f.has_p3d) return true;
223  if (test_reprojection) {
224  if (!f.has_p2d) return false;
225  if (!f.has_p3d) return false;
226  // Note that the projected_p2d needs to have valid content at this point
227  double dist_sq = (f.p2d.x-f.projected_p2d.x)*(f.p2d.x-f.projected_p2d.x);
228  dist_sq += (f.p2d.y-f.projected_p2d.y)*(f.p2d.y-f.projected_p2d.y);
229  if (dist_sq > limit_sq)
230  return true;
231  }
232  return false;
233  }
234 };
235 
237 template<typename T, typename F>
238 inline int EraseItemsEC(std::map<int,T> &container, F do_erase_test) {
239  int count=0;
240  typename std::map<int,T>::iterator iter = container.begin();
241  while(iter != container.end()) {
242  T &f = iter->second;
243  if (do_erase_test(f)) {
244  container.erase(iter++);
245  count++;
246  } else iter++;
247  }
248  return count;
249 }
250 
253 protected:
254  bool purge;
255 public:
257  TrackerFeaturesEC(int _max_features=100, int _min_features=90, double _quality_level=0.01, double _min_distance=10, int _pyr_levels=4, int win_size=6)
258  : TrackerFeatures(_max_features, _min_features, _quality_level, _min_distance, _pyr_levels, win_size), purge(false) {}
259 
261  template<typename T>
262  bool Track(IplImage *img, IplImage *mask, std::map<int,T> &container, int type_id=-1, int first_id=-1, int last_id=-1)
263  {
264  DoHandleTest<T> do_handle_test_default(type_id);
265  if (type_id == -1) type_id=0;
266  return Track(img, mask, container, do_handle_test_default, type_id, first_id, last_id);
267  }
268 
270  /*template<typename T, typename F>
271  bool Track(IplImage *img, IplImage *mask, std::map<int,T> &container, F do_handle_test, int type_id=0, int first_id=0, int last_id=65535)
272  {
273  // Update features to match the ones in the given container
274  typename std::map<int,T>::iterator iter = container.begin();
275  typename std::map<int,T>::iterator iter_end = container.end();
276  feature_count = 0;
277  for (;iter != iter_end; iter++) {
278  T &f = iter->second;
279  if (!do_handle_test(f)) continue;
280  if (f.has_p2d != true) continue;
281  f.has_p2d = false; // This is updated again to true if tracking succeeds
282  features[feature_count] = f.p2d;
283  ids[feature_count] = iter->first;
284  feature_count++;
285  if (feature_count == max_features) break;
286  }
287  // Check that next_id is ok
288  if (next_id < first_id) next_id = first_id;
289  if (next_id > last_id) return false; // TODO: Make some better solution for this
290  // Purge if needed
291  if (purge) {
292  TrackerFeatures::Purge();
293  purge=false;
294  }
295  // Track as usual (this will swap above features to prev_features)
296  TrackHid(img, mask);
297  // Update the container to have the updated features
298  for (int i=0; i<feature_count; i++) {
299  int id = ids[i];
300  if (id >= last_id) break;
301  T &f = container[id];
302  f.type_id = type_id;
303  f.has_p2d = true;
304  f.p2d = features[i];
305  }
306  return true;
307  }*/
308 
310  template<typename T, typename F>
311  bool Track(IplImage *img, IplImage *mask, std::map<int,T> &container, F do_handle_test, int type_id=0, int first_id=-1, int last_id=-1)
312  {
313  // When first_id && last_id are < 0 then we don't add new features...
314  if (first_id < 0) last_id = -1;
315  // Update features to match the ones in the given container
316  typename std::map<int,T>::iterator iter = container.begin();
317  typename std::map<int,T>::iterator iter_end = container.end();
318  feature_count = 0;
319  for (;iter != iter_end; iter++) {
320  T &f = iter->second;
321  if (!do_handle_test(f)) continue;
322  if (f.has_p2d != true) continue;
323  f.has_p2d = false; // This is updated again to true if tracking succeeds
324  features[feature_count] = f.p2d;
325  ids[feature_count] = iter->first;
326  feature_count++;
327  if (feature_count == max_features) break;
328  }
329  // Purge if needed
330  if (purge) {
332  purge=false;
333  }
334  if (first_id < 0) {
335  // Track as usual (this will swap above features to prev_features)
336  TrackHid(img, mask, false);
337  } else {
338  // Check that next_id is ok
339  if (next_id < first_id) next_id = first_id;
340  if (next_id > last_id) return false; // TODO: Make some better solution for this
341  // Track as usual (this will swap above features to prev_features)
342  TrackHid(img, mask, true);
343  }
344  // Update the container to have the updated features
345  for (int i=0; i<feature_count; i++) {
346  int id = ids[i];
347  if (last_id >= 0 && id >= last_id) break;
348  T &f = container[id];
349  f.type_id = type_id;
350  f.has_p2d = true;
351  f.p2d = features[i];
352  }
353  return true;
354  }
355 
357  template<typename T>
358  bool AddFeatures(std::map<int,T> &container, int type_id=0, int first_id=0, int last_id=65535)
359  {
360  if (TrackerFeatures::AddFeatures() == 0) return false;
361  // Update the container to have the updated features
362  for (int i=0; i<feature_count; i++) {
363  int id = ids[i];
364  if (last_id >= 0 && id >= last_id) break;
365  T &f = container[id];
366  f.type_id = type_id;
367  f.has_p2d = true;
368  f.p2d = features[i];
369  }
370  return true;
371  }
372 
374  template<typename T>
375  int EraseNonTracked(std::map<int,T> &container, int type_id=-1)
376  {
377  DoEraseTest<T> do_erase_test(true, false, type_id);
378  return EraseItemsEC(container, do_erase_test);
379  }
384  void Purge() { purge=true; }
385  void Reset() { throw alvar::AlvarException("Method not supported"); }
386  double Reset(IplImage *img, IplImage *mask) { throw alvar::AlvarException("Method not supported"); }
387  bool DelFeature(int index) { throw alvar::AlvarException("Method not supported"); }
388  bool DelFeatureId(int id) { throw alvar::AlvarException("Method not supported"); }
389 };
390 
392 class ALVAR_EXPORT CameraEC : public Camera {
393 public:
395  template<typename T>
396  void Undistort(std::map<int,T> &container, int type_id=-1) {
397  DoHandleTest<T> do_handle_test_default(type_id);
398  return Undistort(container, do_handle_test_default);
399  }
401  template<typename T, typename F>
402  void Undistort(std::map<int,T> &container, F &do_handle_test) {
403  typename std::map<int,T>::iterator iter = container.begin();
404  typename std::map<int,T>::iterator iter_end = container.end();
405  for (;iter != iter_end; iter++) {
406  T &f = iter->second;
407  if (!do_handle(f)) continue;
408  if (f.has_p2d) Undistort(f.p2d);
409  }
410  }
412  template<typename T>
413  void Distort(std::map<int,T> &container, int type_id=-1) {
414  DoHandleTest<T> do_handle_test_default(type_id);
415  return Distort(container, do_handle_test_default);
416  }
418  template<typename T, typename F>
419  void Distort(std::map<int,T> &container, F &do_handle_test) {
420  typename std::map<int,T>::iterator iter = container.begin();
421  typename std::map<int,T>::iterator iter_end = container.end();
422  for (;iter != iter_end; iter++) {
423  T &f = iter->second;
424  if (!do_handle(f)) continue;
425  if (f.has_p2d) Distort(f.p2d);
426  }
427  }
429  template<typename T>
430  bool CalcExteriorOrientation(std::map<int,T> &container, Pose *pose, int type_id=-1) {
431  DoHandleTest<T> do_handle_test_default(type_id);
432  return CalcExteriorOrientation(container, pose, do_handle_test_default);
433  }
435  template<typename T, typename F>
436  bool CalcExteriorOrientation(std::map<int,T> &container, Pose *pose, F do_handle_test) {
437  int count_points = container.size();
438  if(count_points < 4) return false;
439  CvMat* world_points = cvCreateMat(count_points, 1, CV_32FC3);
440  CvMat* image_observations = cvCreateMat(count_points*2, 1, CV_32FC2);
441  typename std::map<int,T>::iterator iter = container.begin();
442  typename std::map<int,T>::iterator iter_end = container.end();
443  int ind = 0;
444  for (;iter != iter_end; iter++) {
445  T &f = iter->second;
446  if (!do_handle_test(f)) continue;
447  if (f.has_p2d && f.has_p3d) {
448  world_points->data.fl[ind*3+0] = (float)f.p3d.x;
449  world_points->data.fl[ind*3+1] = (float)f.p3d.y;
450  world_points->data.fl[ind*3+2] = (float)f.p3d.z;
451  image_observations->data.fl[ind*2+0] = (float)f.p2d.x;
452  image_observations->data.fl[ind*2+1] = (float)f.p2d.y;
453  ind++;
454  }
455  }
456  if (ind<4) return false;
457 
458  CvRect r; r.x = 0; r.y = 0; r.height = ind; r.width = 1;
459  CvMat world_points_sub;
460  cvGetSubRect(world_points, &world_points_sub, r);
461  CvMat image_observations_sub;
462  cvGetSubRect(image_observations, &image_observations_sub, r);
463 
464  bool ret = Camera::CalcExteriorOrientation(&world_points_sub, &image_observations_sub, pose);
465 
466  cvReleaseMat(&image_observations);
467  cvReleaseMat(&world_points);
468 
469  return ret;
470  }
472  template<typename T>
473  bool UpdatePose(std::map<int,T> &container, Pose *pose, int type_id=-1, std::map<int,double> *weights=0) {
474  DoHandleTest<T> do_handle_test_default(type_id);
475  return UpdatePose(container, pose, do_handle_test_default, weights);
476  }
478  template<typename T>
479  bool UpdateRotation(std::map<int,T> &container, Pose *pose, int type_id=-1) {
480  DoHandleTest<T> do_handle_test_default(type_id);
481  return UpdateRotation(container, pose, do_handle_test_default);
482  }
484  template<typename T, typename F>
485  bool UpdateRotation(std::map<int,T> &container, Pose *pose, F do_handle_test) {
486  int count_points = container.size();
487  if(count_points < 6) return false;
488 
489  CvMat* world_points = cvCreateMat(count_points, 1, CV_64FC3);
490  CvMat* image_observations = cvCreateMat(count_points*2, 1, CV_64F); // [u v u v u v ...]'
491 
492  int ind = 0;
493  typename std::map<int,T>::iterator iter = container.begin();
494  typename std::map<int,T>::iterator iter_end = container.end();
495  for (;iter != iter_end; iter++) {
496  T &f = iter->second;
497  if (!do_handle_test(f)) continue;
498  if (f.has_p2d && f.has_p3d) {
499  world_points->data.db[ind*3+0] = f.p3d.x;
500  world_points->data.db[ind*3+1] = f.p3d.y;
501  world_points->data.db[ind*3+2] = f.p3d.z;
502  image_observations->data.db[ind*2+0] = f.p2d.x;
503  image_observations->data.db[ind*2+1] = f.p2d.y;
504  ind++;
505  }
506  }
507  if (ind < 6) return false;
508 
509  CvRect r; r.x = 0; r.y = 0; r.height = ind; r.width = 1;
510  CvMat world_points_sub;
511  cvGetSubRect(world_points, &world_points_sub, r);
512 
513  r.height = 2*ind;
514  CvMat image_observations_sub;
515  cvGetSubRect(image_observations, &image_observations_sub, r);
516 
517  bool ret = UpdateRotation(&world_points_sub, &image_observations_sub, pose);
518 
519  cvReleaseMat(&image_observations);
520  cvReleaseMat(&world_points);
521 
522  return ret;
523  }
525  template<typename T, typename F>
526  bool UpdatePose(std::map<int,T> &container, Pose *pose, F do_handle_test, std::map<int,double> *weights=0) {
527  int count_points = container.size();
528  if(count_points < 4) return false; // Note, UpdatePose calls CalcExteriorOrientation if 4 or 5 points
529 
530  CvMat* world_points = cvCreateMat(count_points, 1, CV_64FC3);
531  CvMat* image_observations = cvCreateMat(count_points*2, 1, CV_64F); // [u v u v u v ...]'
532  CvMat* w = 0;
533  if(weights) w = cvCreateMat(count_points*2, 1, CV_64F);
534 
535  int ind = 0;
536  typename std::map<int,T>::iterator iter = container.begin();
537  typename std::map<int,T>::iterator iter_end = container.end();
538  for (;iter != iter_end; iter++) {
539  T &f = iter->second;
540  if (!do_handle_test(f)) continue;
541  if (f.has_p2d && f.has_p3d) {
542  world_points->data.db[ind*3+0] = f.p3d.x;
543  world_points->data.db[ind*3+1] = f.p3d.y;
544  world_points->data.db[ind*3+2] = f.p3d.z;
545  image_observations->data.db[ind*2+0] = f.p2d.x;
546  image_observations->data.db[ind*2+1] = f.p2d.y;
547 
548  if(weights)
549  w->data.db[ind*2+1] = w->data.db[ind*2+0] = (*weights)[iter->first];
550  ind++;
551  }
552  }
553  if (ind < 4) return false; // Note, UpdatePose calls CalcExteriorOrientation if 4 or 5 points
554 
555  CvRect r; r.x = 0; r.y = 0; r.height = ind; r.width = 1;
556  CvMat world_points_sub;
557  cvGetSubRect(world_points, &world_points_sub, r);
558 
559  r.height = 2*ind;
560  CvMat image_observations_sub;
561  cvGetSubRect(image_observations, &image_observations_sub, r);
562 
563  bool ret;
564  if (weights) {
565  CvMat w_sub;
566  cvGetSubRect(w, &w_sub, r);
567  ret = UpdatePose(&world_points_sub, &image_observations_sub, pose, &w_sub);
568  }
569  else
570  ret = UpdatePose(&world_points_sub, &image_observations_sub, pose);
571 
572  cvReleaseMat(&image_observations);
573  cvReleaseMat(&world_points);
574  if(w) cvReleaseMat(&w);
575 
576  return ret;
577  }
578 
580  template<typename T>
581  float Reproject(std::map<int,T> &container, Pose *pose, int type_id=-1, bool needs_has_p2d=false, bool needs_has_p3d=false, float average_outlier_limit=0.f)
582  {
583  DoHandleTest<T> do_handle_test(type_id, needs_has_p2d, needs_has_p3d);
584  return Reproject(container, pose, do_handle_test, average_outlier_limit);
585  }
587  template<typename T, typename F>
588  float Reproject(std::map<int,T> &container, Pose *pose, F do_handle_test, float average_outlier_limit=0.f)
589  {
590  float reprojection_sum=0.f;
591  int reprojection_count=0;
592  float limit_sq = average_outlier_limit*average_outlier_limit;
593  typename std::map<int,T>::iterator iter = container.begin();
594  typename std::map<int,T>::iterator iter_end = container.end();
595  for(;iter != iter_end;iter++) {
596  T &f = iter->second;
597  if (!do_handle_test(f)) continue;
598  Camera::ProjectPoint(iter->second.p3d, pose, iter->second.projected_p2d);
599  Camera::ProjectPoint(iter->second.p3d_sh, pose, iter->second.projected_p2d_sh);
600 
601  // TODO: Now this is calculated in several places (should this distance be included in ExternalContainer structure?
602  float dist_sq = (f.p2d.x-f.projected_p2d.x)*(f.p2d.x-f.projected_p2d.x);
603  dist_sq += (f.p2d.y-f.projected_p2d.y)*(f.p2d.y-f.projected_p2d.y);
604  if ((limit_sq == 0) || (dist_sq < limit_sq)) {
605  reprojection_sum += sqrt(dist_sq);
606  reprojection_count++;
607  }
608  }
609  if (reprojection_count == 0) return 0.f;
610  return reprojection_sum/reprojection_count;
611  }
612 
617  template<typename T>
618  int EraseUsingReprojectionError(std::map<int,T> &container, float reprojection_error_limit, int type_id=-1, Pose *pose = 0)
619  {
620  if (pose) Reproject(container, pose, type_id, false, false);
621  DoEraseTest<T> do_erase_test(reprojection_error_limit, false, false, type_id) ;
622  return EraseItemsEC(container, do_erase_test);
623  }
624 
626  bool UpdateRotation(const CvMat* object_points, CvMat* image_points, Pose *pose);
627 
629  bool UpdateRotation(const CvMat* object_points, CvMat* image_points, CvMat *rot, CvMat *tra);
630 
632  bool UpdatePose(const CvMat* object_points, CvMat* image_points, Pose *pose, CvMat *weights=0);
633 
635  bool UpdatePose(const CvMat* object_points, CvMat* image_points, CvMat *rodriques, CvMat *tra, CvMat *weights=0);
636 
638  bool ReconstructFeature(const Pose *pose1, const Pose *pose2, const CvPoint2D32f *u1, const CvPoint2D32f *u2, CvPoint3D32f *p3d, double limit);
639 
641  void Get3dOnPlane(const Pose *pose, CvPoint2D32f p2d, CvPoint3D32f &p3d);
642 
644  void Get3dOnDepth(const Pose *pose, CvPoint2D32f p2d, float depth, CvPoint3D32f &p3d);
645 };
646 
648 inline int MarkerIdToContainerId(int marker_id, int corner_id, int first_id=0, int last_id=65535) {
649  int id = first_id + marker_id*4 + corner_id;
650  if (id > last_id) return -1;
651  return id;
652 }
653 
655 template<class M>
656 class MarkerDetectorEC : public MarkerDetector<M> {
657 protected:
658  template<typename T>
659  bool PreDetect(std::pair<const int,T> &p, int type_id) {
660  return PreDetect(p.second, type_id);
661  }
662  template<typename T>
663  bool PreDetect(T &p, int type_id) {
664  if (p.type_id != type_id) return false;
665  p.has_p2d = false; // This is updated again to true if tracking succeeds
666  return true;
667  }
668 public:
669  int GetId(int marker_id, int corner_id, int first_id=0, int last_id=65535) {
670  return MarkerIdToContainerId(marker_id, corner_id, first_id, last_id);
671  }
672 
674  template<typename T>
675  int Detect(IplImage *image,
676  Camera *cam,
677  std::map<int,T> &container,
678  int type_id=0,
679  int first_id=0,
680  int last_id=65535,
681  bool track=false,
682  bool visualize=false,
683  double max_new_marker_error=0.08,
684  double max_track_error=0.2,
685  LabelingMethod labeling_method=CVSEQ)
686  {
687  int ret;
688 
689  // The existing markers in the container are marked to not have valid p2d (has_p2d=false)
690  typename std::map<int,T>::iterator iter = container.begin();
691  typename std::map<int,T>::iterator iter_end = container.end();
692  for (;iter != iter_end; iter++) {
693  T &f = iter->second;
694  if (f.type_id != type_id) continue;
695  f.has_p2d = false; // This is updated again to true if tracking succeeds
696  }
697 
698  // Detect without making the unnecessary pose update
699  ret = MarkerDetector<M>::Detect(image, cam, track, visualize, max_new_marker_error, max_track_error, labeling_method, false);
700 
701  // Fill in the detected markers to the container
702  for (size_t i=0; i<MarkerDetector<M>::markers->size(); i++) {
703  M &m = (*(MarkerDetector<M>::markers))[i];
704  for (int corner=0; corner<4; corner++) {
705  int id = MarkerIdToContainerId(m.GetId(), corner, first_id, last_id);
706  if (id != -1) {
707  T &f = container[id];
708  f.type_id = type_id;
709  f.has_p2d = true;
710  f.p2d.x = float(m.marker_corners_img[corner].x);
711  f.p2d.y = float(m.marker_corners_img[corner].y);
712  }
713  }
714  }
715  return ret;
716  }
717 
719  template<typename T>
720  void MarkerToEC(std::map<int,T> &container, int marker_id, double edge_length, Pose &pose, int type_id=0, int first_id=0,int last_id=65535) {
721  CvMat *m3 = cvCreateMat(4,4,CV_64F); cvSetIdentity(m3);
722  pose.GetMatrix(m3);
723 
724  for(size_t corner = 0; corner < 4; ++corner)
725  {
726  // TODO: This should be exactly the same as in Marker class.
727  // Should we get the values from there somehow?
728  double X_data[4] = {0, 0, 0, 1};
729  if (corner == 0) {
730  X_data[0] = -0.5*edge_length;
731  X_data[1] = -0.5*edge_length;
732  } else if (corner == 1) {
733  X_data[0] = +0.5*edge_length;
734  X_data[1] = -0.5*edge_length;
735  } else if (corner == 2) {
736  X_data[0] = +0.5*edge_length;
737  X_data[1] = +0.5*edge_length;
738  } else if (corner == 3) {
739  X_data[0] = -0.5*edge_length;
740  X_data[1] = +0.5*edge_length;
741  }
742 
743  CvMat X = cvMat(4, 1, CV_64F, X_data);
744  cvMatMul(m3, &X, &X);
745 
746  int id = MarkerIdToContainerId(marker_id, corner, first_id, last_id);
747  T &f = container[id];
748  f.type_id = type_id;
749  f.p3d.x = float(X_data[0] / X_data[3]);
750  f.p3d.y = float(X_data[1] / X_data[3]);
751  f.p3d.z = float(X_data[2] / X_data[3]);
752  f.has_p3d = true;
753  }
754  cvReleaseMat(&m3);
755  }
756 };
757 
759 class MultiMarkerEC : public MultiMarker {
760 public:
762  template<typename T>
763  bool MarkersToEC(std::map<int,T> &container, int type_id=0, int first_id=0,int last_id=65535) {
764  bool ret = false;
765  for (size_t i = 0; i < marker_indices.size(); i++) {
766  if (marker_status[i] == 0) continue; // Skip the ones not in point cloud
767  int marker_id = marker_indices[i];
768  for (int corner = 0; corner < 4; corner++) {
769  int id = MarkerIdToContainerId(marker_id, corner, first_id, last_id);
770  if (id != -1) {
771  int pc_index = pointcloud_index(marker_id, corner);
772  T &f = container[id];
773  f.type_id = type_id;
774  f.p3d.x = float(pointcloud[pc_index].x);
775  f.p3d.y = float(pointcloud[pc_index].y);
776  f.p3d.z = float(pointcloud[pc_index].z);
777  f.has_p3d = true;
778  ret = true;
779  }
780  }
781  }
782  return ret;
783  }
784 
785  template<typename T>
786  bool MarkersFromEC(std::map<int,T> &container, int type_id=0, int first_id=0,int last_id=65535) {
787  // TODO...
788  return false;
789  }
790 
791  template<typename T>
792  bool Save(std::map<int,T> &container, const char* fname, FILE_FORMAT format = FILE_FORMAT_DEFAULT, int type_id=0, int first_id=0,int last_id=65535) {
793  if (!MarkersFromEC(container, type_id, first_id, last_id)) return false;
794  if (!MultiMarker::Save(fname, format)) return false;
795  return true;
796  }
797 
799  template<typename T>
800  bool Load(std::map<int,T> &container, const char* fname, FILE_FORMAT format = FILE_FORMAT_DEFAULT, int type_id=0, int first_id=0,int last_id=65535) {
801  if (!MultiMarker::Load(fname, format)) return false;
802  return MarkersToEC(container, type_id, first_id, last_id);
803  }
804 };
805 }
806 
807 #endif
808 
double max_new_marker_error
Main ALVAR namespace.
Definition: Alvar.h:174
Default file format.
Definition: FileFormat.h:45
bool needs_has_p3d
Definition: EC.h:186
This file implements a camera used for projecting points and computing homographies.
f
bool UpdatePose(std::map< int, T > &container, Pose *pose, int type_id=-1, std::map< int, double > *weights=0)
Update the pose using the items with matching type_id.
Definition: EC.h:473
bool DelFeatureId(int id)
Definition: EC.h:388
void Undistort(std::map< int, T > &container, F &do_handle_test)
Undistort the items matching the given functor.
Definition: EC.h:402
bool MarkersFromEC(std::map< int, T > &container, int type_id=0, int first_id=0, int last_id=65535)
Definition: EC.h:786
This is a default functor for testing which items in the container should be handled by each method...
Definition: EC.h:182
bool AddFeatures(std::map< int, T > &container, int type_id=0, int first_id=0, int last_id=65535)
add features to the previously tracked frame if there are less than min_features
Definition: EC.h:358
int visualize
Version of Camera using external container.
Definition: EC.h:392
This file implements a generic marker detector.
bool Track(IplImage *img, IplImage *mask, std::map< int, T > &container, int type_id=-1, int first_id=-1, int last_id=-1)
Track features with matching type id. New features will have id&#39;s in the specified id range...
Definition: EC.h:262
float limit_sq
Definition: EC.h:211
int EraseNonTracked(std::map< int, T > &container, int type_id=-1)
Erases the items matching with type_id having has_p2d == false . If type_id == -1 doesn&#39;t test the ty...
Definition: EC.h:375
ExternalContainer(const ExternalContainer &c)
Definition: EC.h:161
unsigned char * image
Definition: GlutViewer.cpp:155
DoEraseTest(float _limit, bool _erase_without_p2d=false, bool _erase_without_p3d=false, int _type_id=-1)
Definition: EC.h:216
bool erase_without_p3d
Definition: EC.h:209
Base class for using MultiMarker.
Definition: MultiMarker.h:47
TFSIMD_FORCE_INLINE const tfScalar & y() const
float Reproject(std::map< int, T > &container, Pose *pose, int type_id=-1, bool needs_has_p2d=false, bool needs_has_p3d=false, float average_outlier_limit=0.f)
Projects p3d in the items matching with type_id into projected_p2d . If type_id == -1 doesn&#39;t test th...
Definition: EC.h:581
Simple Camera class for calculating distortions, orientation or projections with pre-calibrated camer...
Definition: Camera.h:82
double Reset(IplImage *img, IplImage *mask)
Definition: EC.h:386
int Purge()
Purge features that are considerably closer than the defined min_distance.
TrackerFeaturesEC(int _max_features=100, int _min_features=90, double _quality_level=0.01, double _min_distance=10, int _pyr_levels=4, int win_size=6)
Constructor.
Definition: EC.h:257
void Distort(std::map< int, T > &container, int type_id=-1)
Distort the items with matching type_id.
Definition: EC.h:413
bool PreDetect(T &p, int type_id)
Definition: EC.h:663
DoHandleTest(int _type_id=-1, bool _needs_has_p2d=false, bool _needs_has_p3d=false)
Definition: EC.h:188
This is default functor for testing which items in the container should be erased.
Definition: EC.h:205
Version of MarkerDetector using external container.
Definition: EC.h:656
Version of MultiMarker using external container.
Definition: EC.h:759
CvPoint2D32f p2d
Definition: EC.h:157
void Purge()
Purge features that are considerably closer than the defined min_distance.
Definition: EC.h:384
int GetId(int marker_id, int corner_id, int first_id=0, int last_id=65535)
Definition: EC.h:669
bool Track(IplImage *img, IplImage *mask, std::map< int, T > &container, F do_handle_test, int type_id=0, int first_id=-1, int last_id=-1)
Track features matching the given functor. New features will have id&#39;s in the specified id range...
Definition: EC.h:311
int AddFeatures(IplImage *mask=NULL)
add features to the previously tracked frame if there are less than min_features
MarkerDetector for detecting markers of type M
void MarkerToEC(std::map< int, T > &container, int marker_id, double edge_length, Pose &pose, int type_id=0, int first_id=0, int last_id=65535)
Fill in 3D-coordinates for marker_id marker corners using edge_length and pose.
Definition: EC.h:720
DoEraseTest(bool _erase_without_p2d, bool _erase_without_p3d, int _type_id=-1)
Definition: EC.h:213
void Undistort(std::map< int, T > &container, int type_id=-1)
Undistort the items with matching type_id.
Definition: EC.h:396
bool Save(std::map< int, T > &container, const char *fname, FILE_FORMAT format=FILE_FORMAT_DEFAULT, int type_id=0, int first_id=0, int last_id=65535)
Definition: EC.h:792
FILE_FORMAT
Definition: FileFormat.h:39
int EraseItemsEC(std::map< int, T > &container, F do_erase_test)
Erasing items from container using DoEraseTest type functor.
Definition: EC.h:238
This file implements a feature tracker.
int EraseUsingReprojectionError(std::map< int, T > &container, float reprojection_error_limit, int type_id=-1, Pose *pose=0)
Erases the items matching with type_id having large reprojection error. If type_id == -1 doesn&#39;t test...
Definition: EC.h:618
void ProjectPoint(const CvPoint3D64f pw, const Pose *pose, CvPoint2D64f &pi) const
Project one point.
Definition: Camera.cpp:814
Pose representation derived from the Rotation class
Definition: Pose.h:50
ALVAR exception class.
bool UpdateRotation(std::map< int, T > &container, Pose *pose, F do_handle_test)
Update the rotation in pose using the items matching the given functor.
Definition: EC.h:485
TFSIMD_FORCE_INLINE const tfScalar & x() const
bool UpdatePose(std::map< int, T > &container, Pose *pose, F do_handle_test, std::map< int, double > *weights=0)
Update the pose using the items matching the given functor.
Definition: EC.h:526
bool needs_has_p2d
Definition: EC.h:185
TrackerFeatures tracks features using OpenCV&#39;s cvGoodFeaturesToTrack and cvCalcOpticalFlowPyrLK ...
TFSIMD_FORCE_INLINE const tfScalar & z() const
bool DelFeature(int index)
Definition: EC.h:387
int Detect(IplImage *image, Camera *cam, std::map< int, T > &container, int type_id=0, int first_id=0, int last_id=65535, bool track=false, bool visualize=false, double max_new_marker_error=0.08, double max_track_error=0.2, LabelingMethod labeling_method=CVSEQ)
Detect markers in the image and fill in their 2D-positions in the given external container.
Definition: EC.h:675
bool PreDetect(std::pair< const int, T > &p, int type_id)
Definition: EC.h:659
#define ALVAR_EXPORT
Definition: Alvar.h:168
double max_track_error
TFSIMD_FORCE_INLINE const tfScalar & w() const
This file implements a multi-marker.
void GetMatrix(CvMat *mat) const
Definition: Pose.cpp:91
bool erase_without_p2d
Definition: EC.h:208
bool Load(const char *fname, FILE_FORMAT format=FILE_FORMAT_DEFAULT)
Loads multi marker configuration from a text file.
void CalcExteriorOrientation(std::vector< CvPoint3D64f > &pw, std::vector< CvPoint2D64f > &pi, Pose *pose)
Calculate exterior orientation.
bool Load(std::map< int, T > &container, const char *fname, FILE_FORMAT format=FILE_FORMAT_DEFAULT, int type_id=0, int first_id=0, int last_id=65535)
Fill in 3D-coordinates for marker corners to the given container using save MultiMarker file...
Definition: EC.h:800
int Detect(IplImage *image, Camera *cam, bool track=false, bool visualize=false, double max_new_marker_error=0.08, double max_track_error=0.2, LabelingMethod labeling_method=CVSEQ, bool update_pose=true)
Detect Marker &#39;s from image
void Distort(std::map< int, T > &container, F &do_handle_test)
Distort the items matching the given functor.
Definition: EC.h:419
bool CalcExteriorOrientation(std::map< int, T > &container, Pose *pose, int type_id=-1)
Calculate the pose using the items with matching type_id.
Definition: EC.h:430
bool MarkersToEC(std::map< int, T > &container, int type_id=0, int first_id=0, int last_id=65535)
Fill in 3D-coordinates for marker corners to the given container.
Definition: EC.h:763
Camera * cam
CvPoint3D32f p3d
Definition: EC.h:158
CvPoint2D32f projected_p2d
Definition: EC.h:159
Basic structure to be usable with EC methods.
Definition: EC.h:152
bool CalcExteriorOrientation(std::map< int, T > &container, Pose *pose, F do_handle_test)
Calculate the pose using the items matching the given functor.
Definition: EC.h:436
bool UpdateRotation(std::map< int, T > &container, Pose *pose, int type_id=-1)
Update the rotation in pose using the items with matching type_id.
Definition: EC.h:479
bool test_reprojection
Definition: EC.h:210
r
virtual bool operator()(const T &f) const
Definition: EC.h:219
int MarkerIdToContainerId(int marker_id, int corner_id, int first_id=0, int last_id=65535)
Calculate the index used in external container map for specified marker_id.
Definition: EC.h:648
bool Save(const char *fname, FILE_FORMAT format=FILE_FORMAT_DEFAULT)
Saves multi marker configuration to a text file.
float Reproject(std::map< int, T > &container, Pose *pose, F do_handle_test, float average_outlier_limit=0.f)
Projects p3d in the items matching with the given functor.
Definition: EC.h:588
virtual bool operator()(const T &f) const
Definition: EC.h:190
Version of TrackerFeatures using external container.
Definition: EC.h:252


ar_track_alvar
Author(s): Scott Niekum
autogenerated on Mon Jun 10 2019 12:47:04