MultiMarkerBundle.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 
26 using namespace std;
27 
28 namespace alvar {
29 using namespace std;
30 
31 MultiMarkerBundle::MultiMarkerBundle(std::vector<int>& indices)
32  : MultiMarker(indices)
33 {
35 }
36 
38 {
39 }
40 
45  optimizing=false;
46  camera_poses.clear();
47  measurements.clear();
48 }
49 
50 int n_images; // TODO: This should not be global (use the param instead)
51 int n_markers; // TODO: This should not be global (use the param instead)
52 Camera *camera; // TODO: This should not be global (use the param instead)
53 
54 void Est(CvMat* state, CvMat* estimation, void *param)
55 {
56 
57  // State: cam1, cam2, cam3, cam4, ..., X1(x,y,z), X2, X3, ...
58  // Estimation: (u11,v11), (u)
59 
60  // For every image observation (camera)...
61  for(int i = 0; i < n_images; ++i)
62  {
63  // Get camera from state
64  Pose p; p.SetQuaternion(&(state->data.db[i*7+3]));
65 
66  double tra[3];
67  double rodr[3];
68  CvMat mat_translation_vector = cvMat(3, 1, CV_64F, tra);
69  CvMat mat_rotation_vector = cvMat(3, 1, CV_64F, rodr);
70 
71  memcpy(tra, &(state->data.db[i*7]), 3*sizeof(double));
72  p.GetRodriques(&mat_rotation_vector);
73 
74  // For every point in marker field
75  int n_points = n_markers*4;
76  for(int j = 0; j < n_points; ++j)
77  {
78  int index = n_images*7 + 3*j;
79 
80  double object_points[3] = {state->data.db[index+0],
81  state->data.db[index+1],
82  state->data.db[index+2]};
83 
84 
85  CvMat mat_object_points;
86  cvInitMatHeader(&mat_object_points, 1, 1, CV_64FC3, object_points);
87 
88  double proj[2]={0};
89  CvMat mat_proj = cvMat(1, 1, CV_64FC2, proj);
90 
91  cvProjectPoints2(&mat_object_points, &mat_rotation_vector,
92  &mat_translation_vector, &(camera->calib_K),
93  &(camera->calib_D), &mat_proj);
94 
95  index = i*n_points*2 + j*2;
96  estimation->data.db[index+0] = proj[0];
97  estimation->data.db[index+1] = proj[1];
98  }
99  }
100 }
101 
102 bool MultiMarkerBundle::Optimize(Camera *_cam, double stop, int max_iter, Optimization::OptimizeMethod method)
103 {
104  // Est() needs these
105  // TODO: Better way to deliver them??? Other than using global variables???
106  camera = _cam;
107  n_images = camera_poses.size();
108  n_markers = marker_indices.size();
109 
110  if(n_images < 1)
111  {
112  cout<<"Too few images! At least 1 images needed."<<endl;
113  return false;
114  }
115 
116  optimizing = true;
117 
118  // Initialize
119  size_t frames = camera_poses.size();
120  int n_params = frames*7 + 3*4*n_markers;
121  int n_meas = 2*4*n_markers*frames;
122  CvMat* parameters_mat = cvCreateMat(n_params, 1, CV_64F);
123  CvMat* parameters_mask_mat = cvCreateMat(n_params, 1, CV_8U);
124  CvMat* measurements_mat = cvCreateMat(n_meas, 1, CV_64F);
125  CvMat* weight_mat = cvCreateMat(n_meas, 1, CV_64F);
126  cvZero(parameters_mat);
127  cvSet(parameters_mask_mat, cvScalar(1));
128  cvZero(measurements_mat);
129  cvSet(weight_mat, cvRealScalar(1.0));
130 
131  // Fill in the point cloud that is used as starting point for optimization
132  for(size_t i = 0; i < marker_indices.size(); ++i) {
133  int id = marker_indices[i];
134  for (int j=0; j<4; j++) {
135  //hop int index = frames*7 + id*(3*4) + j*3;
136  int index = frames*7 + i*(3*4) + j*3;
137  // Lets keep the base marker constant (1st marker given in the indices list)
138  if (i == 0) {
139  cvSet2D(parameters_mask_mat, index+0, 0, cvScalar(0));
140  cvSet2D(parameters_mask_mat, index+1, 0, cvScalar(0));
141  cvSet2D(parameters_mask_mat, index+2, 0, cvScalar(0));
142  }
143  if (marker_status[i] > 0) {
144  cvmSet(parameters_mat, index+0, 0, pointcloud[pointcloud_index(id,j)].x);
145  cvmSet(parameters_mat, index+1, 0, pointcloud[pointcloud_index(id,j)].y);
146  cvmSet(parameters_mat, index+2, 0, pointcloud[pointcloud_index(id,j)].z);
147  } else {
148  // We don't optimize known-initialized parameters?
149  cvSet2D(parameters_mask_mat, index+0, 0, cvScalar(0));
150  cvSet2D(parameters_mask_mat, index+1, 0, cvScalar(0));
151  cvSet2D(parameters_mask_mat, index+2, 0, cvScalar(0));
152  }
153  }
154  }
155  // Fill in the frame data. Camera poses into parameters and corners into measurements
156  int n_measurements = 0; // number of actual measurement data points.
157  for (size_t f=0; f < frames; f++) {
158  //cout<<"frame "<<f<<" / "<<frames<<endl;
159  // Camera pose
160  CvMat tra = cvMat(3, 1, CV_64F, &(parameters_mat->data.db[f*7+0]));
161  CvMat qua = cvMat(4, 1, CV_64F, &(parameters_mat->data.db[f*7+3]));
162  camera_poses[f].GetTranslation(&tra);
163  camera_poses[f].GetQuaternion(&qua);
164  // Measurements
165  for(size_t i = 0; i < marker_indices.size(); ++i) {
166  int id = marker_indices[i];
167  if (measurements.find(measurements_index(f,id,0)) != measurements.end()) {
168  for (int j=0; j<4; j++) {
169  //cout<<measurements[measurements_index(f, id, j)].x<<endl;
170  //hop int index = f*(n_markers*4*2) + id*(4*2) + j*2;
171  int index = f*(n_markers*4*2) + i*(4*2) + j*2;
172  cvmSet(measurements_mat, index+0, 0, measurements[measurements_index(f, id, j)].x);
173  cvmSet(measurements_mat, index+1, 0, measurements[measurements_index(f, id, j)].y);
174  n_measurements += 2;
175  }
176  } else {
177  for (int j=0; j<4; j++) {
178  //hop int index = f*(n_markers*4*2) + id*(4*2) + j*2;
179  int index = f*(n_markers*4*2) + i*(4*2) + j*2;
180  cvmSet(weight_mat, index+0, 0, 0.);
181  cvmSet(weight_mat, index+1, 0, 0.);
182  }
183  }
184  }
185  }
186  //out_matrix(measurements_mat, "measurements");
187  //out_matrix(parameters_mat, "parameters");
190  for(size_t i = 0; i < marker_indices.size(); ++i) if (marker_status[i] > 0) optimization_markers++;
191  Optimization optimization(n_params, n_meas);
192  cout<<"Optimizing with "<<optimization_keyframes<<" keyframes and "<<optimization_markers<<" markers"<<endl;
194  optimization.Optimize(parameters_mat, measurements_mat, stop, max_iter,
195  Est, 0, method, parameters_mask_mat, NULL, weight_mat);
196  optimization_error /= n_measurements;
197  cout<<"Optimization error per corner: "<<optimization_error<<endl;
198  /*
199  if ((frames > 3) && (optimization_error > stop)) {
200  CvMat *err = optimization.GetErr();
201  int max_k=-1;
202  double max=0;
203  for (int k=0; k<err->height; k++) {
204  if (cvmGet(err, k, 0) > max) {
205  max = cvmGet(err, k, 0);
206  max_k = k;
207  }
208  }
209  if (max_k >= 0) {
210  // We remove all 8 corner measurements
211  int f = (max_k - (max_k % (n_markers*4*2))) / (n_markers*4*2);
212  max_k -= f*(n_markers*4*2);
213  int id = (max_k - (max_k % (4*2))) / (4*2);
214  cout<<"Optimization error over the threshold -- remove the biggest outlier: ";
215  cout<<"frame "<<f<<" id "<<id<<endl;
216  measurements.erase(measurements_index(f,id,0));
217  measurements.erase(measurements_index(f,id,1));
218  measurements.erase(measurements_index(f,id,2));
219  measurements.erase(measurements_index(f,id,3));
220  for (int j=0; j<4; j++) {
221  int index = f*(n_markers*4*2) + id*(4*2) + j*2;
222  cvmSet(measurements_mat, index+0, 0, measurements[measurements_index(f, id, j)].x);
223  cvmSet(measurements_mat, index+1, 0, measurements[measurements_index(f, id, j)].y);
224  }
225  optimization_error = optimization.Optimize(parameters_mat, measurements_mat, stop, max_iter, Est, method, parameters_mask_mat);
226  cout<<"Optimization error: "<<optimization_error<<endl;
227  }
228  }
229  */
230  //out_matrix(parameters_mat, "parameters");
231  //out_matrix(parameters_mask_mat, "parameters_mask");
232 
233  // Fill in the point cloud with optimized values
234  for(size_t i = 0; i < marker_indices.size(); ++i) {
235  int id = marker_indices[i];
236  for (int j=0; j<4; j++) {
237  //hop int index = frames*7 + id*(3*4) + j*3;
238  int index = frames*7 + i*(3*4) + j*3;
239  pointcloud[pointcloud_index(id,j)].x = cvmGet(parameters_mat, index+0,0);
240  pointcloud[pointcloud_index(id,j)].y = cvmGet(parameters_mat, index+1,0);
241  pointcloud[pointcloud_index(id,j)].z = cvmGet(parameters_mat, index+2,0);
242  }
243  }
244 
245  cvReleaseMat(&parameters_mat);
246  cvReleaseMat(&parameters_mask_mat);
247  cvReleaseMat(&measurements_mat);
248 
249  optimizing = false;
250  return true;
251 }
252 
254  camera_poses.push_back(camera_pose);
255  int frame_no = camera_poses.size()-1;
256  //cout<<"Adding measurements for frame "<<frame_no<<endl;
257  for (MarkerIterator &i = begin.reset(); i != end; ++i)
258  {
259  const Marker* marker = *i;
260  int id = marker->GetId();
261  int index = get_id_index(id);
262  if (index < 0) continue;
263  //cout<<"Id "<<id<<" ";
264  for (int j = 0; j<4; j++) {
265  measurements[measurements_index(frame_no, id, j)] =
266  marker->marker_corners_img[j];
267  //cout<<markers->at(i).marker_corners_img[j].x<<" ";
268  }
269  //cout<<endl;
270  }
271 }
272 
273 } // namespace alvar
Main ALVAR namespace.
Definition: Alvar.h:174
void GetRodriques(CvMat *mat) const
Returns the rotation in rotation vector form.
Definition: Rotation.cpp:341
CvMat calib_D
Definition: Camera.h:87
std::vector< PointDouble > marker_corners_img
Marker corners in image coordinates.
Definition: Marker.h:177
f
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
int measurements_index(int frame, int marker_id, int marker_corner)
std::vector< int > marker_status
Definition: MultiMarker.h:65
double Optimize(CvMat *parameters, CvMat *measurements, double stop, int max_iter, EstimateCallback Estimate, void *param=0, OptimizeMethod method=LEVENBERGMARQUARDT, CvMat *parameters_mask=0, CvMat *J_mat=0, CvMat *weights=0)
Runs the optimization loop with selected parameters.
bool Optimize(Camera *_cam, double stop, int max_iter, Optimization::OptimizeMethod method=Optimization::TUKEY_LM)
Runs the bundle adjustment optimization.
Base class for using MultiMarker.
Definition: MultiMarker.h:47
TFSIMD_FORCE_INLINE const tfScalar & y() const
std::map< int, CvPoint3D64f > pointcloud
Definition: MultiMarker.h:63
Non-linear optimization routines. There are three methods implemented that include Gauss-Newton...
Definition: Optimization.h:44
int get_id_index(int id, bool add_if_missing=false)
Definition: MultiMarker.cpp:38
std::vector< int > marker_indices
Definition: MultiMarker.h:64
Simple Camera class for calculating distortions, orientation or projections with pre-calibrated camer...
Definition: Camera.h:82
OptimizeMethod
Selection between the algorithm used in optimization. Following should be noticed: ...
Definition: Optimization.h:74
int pointcloud_index(int marker_id, int marker_corner, bool add_if_missing=false)
Definition: MultiMarker.cpp:34
CvMat calib_K
Definition: Camera.h:86
Camera * camera
Pose representation derived from the Rotation class
Definition: Pose.h:50
TFSIMD_FORCE_INLINE const tfScalar & x() const
Basic 2D Marker functionality.
Definition: Marker.h:52
std::map< int, PointDouble > measurements
TFSIMD_FORCE_INLINE const tfScalar & z() const
Iterator type for traversing templated Marker vector without the template.
Definition: Marker.h:277
void _MeasurementsAdd(MarkerIterator &begin, MarkerIterator &end, const Pose &camera_pose)
This file implements an algorithm to create a multi-marker field configuration.
void Est(CvMat *state, CvMat *estimation, void *param)
void MeasurementsReset()
Resets the measurements and camera poses that are stored for bundle adjustment. If something goes fro...
void SetQuaternion(CvMat *mat)
Sets the rotation from given quaternion.
Definition: Rotation.cpp:294
virtual MarkerIterator & reset()=0
std::vector< Pose > camera_poses


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