MarkerDetector.cpp
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 
25 
29 
30 using namespace std;
31 
32 namespace alvar {
33  MarkerDetectorImpl::MarkerDetectorImpl() {
34  SetMarkerSize();
35  SetOptions();
36  labeling = NULL;
37  }
38 
39  MarkerDetectorImpl::~MarkerDetectorImpl() {
40  if (labeling) delete labeling;
41  }
42 
43  void MarkerDetectorImpl::TrackMarkersReset() {
44  _track_markers_clear();
45  }
46 
47  void MarkerDetectorImpl::TrackMarkerAdd(int id, PointDouble corners[4]) {
48  Marker *mn = new_M(edge_length, res, margin);
49  if (map_edge_length.find(id) != map_edge_length.end()) {
50  mn->SetMarkerSize(map_edge_length[id], res, margin);
51  }
52 
53  mn->SetId(id);
54  mn->marker_corners_img.clear();
55  mn->marker_corners_img.push_back(corners[0]);
56  mn->marker_corners_img.push_back(corners[1]);
57  mn->marker_corners_img.push_back(corners[2]);
58  mn->marker_corners_img.push_back(corners[3]);
59  _track_markers_push_back(mn);
60  delete mn;
61  }
62 
63  void MarkerDetectorImpl::SetMarkerSize(double _edge_length, int _res, double _margin) {
64  edge_length = _edge_length;
65  res = _res;
66  margin = _margin;
67  map_edge_length.clear(); // TODO: Should we clear these here?
68  }
69 
70  void MarkerDetectorImpl::SetMarkerSizeForId(unsigned long id, double _edge_length) {
71  map_edge_length[id] = _edge_length;
72  }
73 
74  void MarkerDetectorImpl::SetOptions(bool _detect_pose_grayscale) {
75  detect_pose_grayscale = _detect_pose_grayscale;
76  }
77 
78  int MarkerDetectorImpl::Detect(IplImage *image,
79  Camera *cam,
80  bool track,
81  bool visualize,
82  double max_new_marker_error,
83  double max_track_error,
84  LabelingMethod labeling_method,
85  bool update_pose)
86  {
87  assert(image->origin == 0); // Currently only top-left origin supported
88  double error=-1;
89 
90  // Swap marker tables
91  _swap_marker_tables();
92  _markers_clear();
93 
94  switch(labeling_method)
95  {
96  case CVSEQ :
97 
98  if(!labeling)
99  labeling = new LabelingCvSeq();
100  ((LabelingCvSeq*)labeling)->SetOptions(detect_pose_grayscale);
101  break;
102  }
103 
104  labeling->SetCamera(cam);
105  labeling->LabelSquares(image, visualize);
106  vector<vector<PointDouble> >& blob_corners = labeling->blob_corners;
107  IplImage* gray = labeling->gray;
108 
109  int orientation;
110 
111  // When tracking we find the best matching blob and test if it is near enough?
112  if (track) {
113  for (size_t ii=0; ii<_track_markers_size(); ii++) {
114  Marker *mn = _track_markers_at(ii);
115  if (mn->GetError(Marker::DECODE_ERROR|Marker::MARGIN_ERROR) > 0) continue; // We track only perfectly decoded markers
116  int track_i=-1;
117  int track_orientation=0;
118  double track_error=1e200;
119  for(unsigned i = 0; i < blob_corners.size()/*blobs_ret.size()*/; ++i) {
120  if (blob_corners[i].empty()) continue;
121  mn->CompareCorners(blob_corners[i], &orientation, &error);
122  if (error < track_error) {
123  track_i = i;
124  track_orientation = orientation;
125  track_error = error;
126  }
127  }
128  if (track_error <= max_track_error) {
129  mn->SetError(Marker::DECODE_ERROR, 0);
130  mn->SetError(Marker::MARGIN_ERROR, 0);
131  mn->SetError(Marker::TRACK_ERROR, track_error);
132  mn->UpdateContent(blob_corners[track_i], gray, cam); //Maybe should only do this when kinect is being used? Don't think it hurts anything...
133  mn->UpdatePose(blob_corners[track_i], cam, track_orientation, update_pose);
134  _markers_push_back(mn);
135  blob_corners[track_i].clear(); // We don't want to handle this again...
136  if (visualize) mn->Visualize(image, cam, CV_RGB(255,255,0));
137  }
138  }
139  }
140 
141  // Now we go through the rest of the blobs -- in case there are new markers...
142  for(size_t i = 0; i < blob_corners.size(); ++i)
143  {
144  if (blob_corners[i].empty()) continue;
145 
146  Marker *mn = new_M(edge_length, res, margin);
147  bool ub = mn->UpdateContent(blob_corners[i], gray, cam);
148  bool db = mn->DecodeContent(&orientation);
149  if (ub && db &&
150  (mn->GetError(Marker::MARGIN_ERROR | Marker::DECODE_ERROR) <= max_new_marker_error))
151  {
152  if (map_edge_length.find(mn->GetId()) != map_edge_length.end()) {
153  mn->SetMarkerSize(map_edge_length[mn->GetId()], res, margin);
154  }
155  mn->UpdatePose(blob_corners[i], cam, orientation, update_pose);
156  mn->ros_orientation = orientation;
157  _markers_push_back(mn);
158 
159  if (visualize) mn->Visualize(image, cam, CV_RGB(255,0,0));
160  }
161 
162  delete mn;
163  }
164 
165  return (int) _markers_size();
166  }
167 
168  int MarkerDetectorImpl::DetectAdditional(IplImage *image, Camera *cam, bool visualize, double max_track_error)
169  {
170  assert(image->origin == 0); // Currently only top-left origin supported
171  if(!labeling) return -1;
172  double error=-1;
173  int orientation;
174  int count=0;
175  vector<vector<PointDouble> >& blob_corners = labeling->blob_corners;
176 
177  for (size_t ii=0; ii<_track_markers_size(); ii++) {
178  Marker *mn = _track_markers_at(ii);
179  if (mn->GetError(Marker::DECODE_ERROR|Marker::MARGIN_ERROR) > 0) continue; // We track only perfectly decoded markers
180  int track_i=-1;
181  int track_orientation=0;
182  double track_error=1e200;
183  for(unsigned i = 0; i < blob_corners.size(); ++i) {
184  if (blob_corners[i].empty()) continue;
185  mn->CompareCorners(blob_corners[i], &orientation, &error);
186  if (error < track_error) {
187  track_i = i;
188  track_orientation = orientation;
189  track_error = error;
190  }
191  }
192  if (track_error <= max_track_error) {
193  mn->SetError(Marker::DECODE_ERROR, 0);
194  mn->SetError(Marker::MARGIN_ERROR, 0);
195  mn->SetError(Marker::TRACK_ERROR, track_error);
196  mn->UpdatePose(blob_corners[track_i], cam, track_orientation);
197  _markers_push_back(mn);
198  count++;
199  blob_corners[track_i].clear(); // We don't want to handle this again...
200 
201  if (visualize) {
202  mn->Visualize(image, cam, CV_RGB(0,255,255));
203  }
204  }
205  }
206  return count;
207  }
208 
209 }
double max_new_marker_error
Main ALVAR namespace.
Definition: Alvar.h:174
int ros_orientation
Definition: Marker.h:181
std::vector< PointDouble > marker_corners_img
Marker corners in image coordinates.
Definition: Marker.h:177
virtual unsigned long GetId() const
Get id for this marker This is used e.g. in MarkerDetector to associate a marker id with an appropria...
Definition: Marker.h:118
virtual bool UpdateContent(std::vector< Point< CvPoint2D64f > > &_marker_corners_img, IplImage *gray, Camera *cam, int frame_no=0)
Updates the marker_content from the image using Homography.
Definition: Marker.cpp:184
int visualize
void SetError(int error_type, double value)
Set the marker error estimate.
Definition: Marker.h:153
void Visualize(IplImage *image, Camera *cam, CvScalar color=CV_RGB(255, 0, 0)) const
Visualize the marker.
Definition: Marker.cpp:134
const double margin
This file implements a generic marker detector.
unsigned char * image
Definition: GlutViewer.cpp:155
virtual void SetId(unsigned long _id)
Definition: Marker.h:119
virtual bool DecodeContent(int *orientation)
Decodes the marker content. Please call UpdateContent before this. This virtual method is meant to be...
Definition: Marker.cpp:316
Simple Camera class for calculating distortions, orientation or projections with pre-calibrated camer...
Definition: Camera.h:82
MarkerDetector for detecting markers of type M
double GetError(int errors=(MARGIN_ERROR|DECODE_ERROR)) const
Get marker detection error estimate.
Definition: Marker.h:144
void UpdatePose(std::vector< Point< CvPoint2D64f > > &_marker_corners_img, Camera *cam, int orientation, int frame_no=0, bool update_pose=true)
Updates the markers pose estimation.
Definition: Marker.cpp:306
Basic 2D Marker functionality.
Definition: Marker.h:52
cv::Mat gray
void CompareCorners(std::vector< Point< CvPoint2D64f > > &_marker_corners_img, int *orientation, double *error)
Compares the marker corners with the previous match.
Definition: Marker.cpp:163
#define ALVAR_EXPORT
Definition: Alvar.h:168
double max_track_error
ALVAR_EXPORT Point< CvPoint2D64f > PointDouble
The default double point type.
Definition: Util.h:108
void SetMarkerSize(double _edge_length=0, int _res=0, double _margin=0)
Method for resizing the marker dimensions.
Definition: Marker.cpp:356
Camera * cam
const int res
Labeling class that uses OpenCV routines to find connected components.


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