00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "MultiMarkerBundle.h"
00025
00026 using namespace std;
00027
00028 namespace alvar {
00029 using namespace std;
00030
00031 MultiMarkerBundle::MultiMarkerBundle(std::vector<int>& indices)
00032 : MultiMarker(indices)
00033 {
00034 MeasurementsReset();
00035 }
00036
00037 MultiMarkerBundle::~MultiMarkerBundle()
00038 {
00039 }
00040
00041 void MultiMarkerBundle::MeasurementsReset() {
00042 optimization_error=-1;
00043 optimization_keyframes=0;
00044 optimization_markers=0;
00045 optimizing=false;
00046 camera_poses.clear();
00047 measurements.clear();
00048 }
00049
00050 int n_images;
00051 int n_markers;
00052 Camera *camera;
00053
00054 void Est(CvMat* state, CvMat* estimation, void *param)
00055 {
00056
00057
00058
00059
00060
00061 for(int i = 0; i < n_images; ++i)
00062 {
00063
00064 Pose p; p.SetQuaternion(&(state->data.db[i*7+3]));
00065
00066 double tra[3];
00067 double rodr[3];
00068 CvMat mat_translation_vector = cvMat(3, 1, CV_64F, tra);
00069 CvMat mat_rotation_vector = cvMat(3, 1, CV_64F, rodr);
00070
00071 memcpy(tra, &(state->data.db[i*7]), 3*sizeof(double));
00072 p.GetRodriques(&mat_rotation_vector);
00073
00074
00075 int n_points = n_markers*4;
00076 for(int j = 0; j < n_points; ++j)
00077 {
00078 int index = n_images*7 + 3*j;
00079
00080 double object_points[3] = {state->data.db[index+0],
00081 state->data.db[index+1],
00082 state->data.db[index+2]};
00083
00084
00085 CvMat mat_object_points;
00086 cvInitMatHeader(&mat_object_points, 1, 1, CV_64FC3, object_points);
00087
00088 double proj[2]={0};
00089 CvMat mat_proj = cvMat(1, 1, CV_64FC2, proj);
00090
00091 cvProjectPoints2(&mat_object_points, &mat_rotation_vector,
00092 &mat_translation_vector, &(camera->calib_K),
00093 &(camera->calib_D), &mat_proj);
00094
00095 index = i*n_points*2 + j*2;
00096 estimation->data.db[index+0] = proj[0];
00097 estimation->data.db[index+1] = proj[1];
00098 }
00099 }
00100 }
00101
00102 bool MultiMarkerBundle::Optimize(Camera *_cam, double stop, int max_iter, Optimization::OptimizeMethod method)
00103 {
00104
00105
00106 camera = _cam;
00107 n_images = camera_poses.size();
00108 n_markers = marker_indices.size();
00109
00110 if(n_images < 1)
00111 {
00112 cout<<"Too few images! At least 1 images needed."<<endl;
00113 return false;
00114 }
00115
00116 optimizing = true;
00117
00118
00119 size_t frames = camera_poses.size();
00120 int n_params = frames*7 + 3*4*n_markers;
00121 int n_meas = 2*4*n_markers*frames;
00122 CvMat* parameters_mat = cvCreateMat(n_params, 1, CV_64F);
00123 CvMat* parameters_mask_mat = cvCreateMat(n_params, 1, CV_8U);
00124 CvMat* measurements_mat = cvCreateMat(n_meas, 1, CV_64F);
00125 CvMat* weight_mat = cvCreateMat(n_meas, 1, CV_64F);
00126 cvZero(parameters_mat);
00127 cvSet(parameters_mask_mat, cvScalar(1));
00128 cvZero(measurements_mat);
00129 cvSet(weight_mat, cvRealScalar(1.0));
00130
00131
00132 for(size_t i = 0; i < marker_indices.size(); ++i) {
00133 int id = marker_indices[i];
00134 for (int j=0; j<4; j++) {
00135
00136 int index = frames*7 + i*(3*4) + j*3;
00137
00138 if (i == 0) {
00139 cvSet2D(parameters_mask_mat, index+0, 0, cvScalar(0));
00140 cvSet2D(parameters_mask_mat, index+1, 0, cvScalar(0));
00141 cvSet2D(parameters_mask_mat, index+2, 0, cvScalar(0));
00142 }
00143 if (marker_status[i] > 0) {
00144 cvmSet(parameters_mat, index+0, 0, pointcloud[pointcloud_index(id,j)].x);
00145 cvmSet(parameters_mat, index+1, 0, pointcloud[pointcloud_index(id,j)].y);
00146 cvmSet(parameters_mat, index+2, 0, pointcloud[pointcloud_index(id,j)].z);
00147 } else {
00148
00149 cvSet2D(parameters_mask_mat, index+0, 0, cvScalar(0));
00150 cvSet2D(parameters_mask_mat, index+1, 0, cvScalar(0));
00151 cvSet2D(parameters_mask_mat, index+2, 0, cvScalar(0));
00152 }
00153 }
00154 }
00155
00156 int n_measurements = 0;
00157 for (size_t f=0; f < frames; f++) {
00158
00159
00160 CvMat tra = cvMat(3, 1, CV_64F, &(parameters_mat->data.db[f*7+0]));
00161 CvMat qua = cvMat(4, 1, CV_64F, &(parameters_mat->data.db[f*7+3]));
00162 camera_poses[f].GetTranslation(&tra);
00163 camera_poses[f].GetQuaternion(&qua);
00164
00165 for(size_t i = 0; i < marker_indices.size(); ++i) {
00166 int id = marker_indices[i];
00167 if (measurements.find(measurements_index(f,id,0)) != measurements.end()) {
00168 for (int j=0; j<4; j++) {
00169
00170
00171 int index = f*(n_markers*4*2) + i*(4*2) + j*2;
00172 cvmSet(measurements_mat, index+0, 0, measurements[measurements_index(f, id, j)].x);
00173 cvmSet(measurements_mat, index+1, 0, measurements[measurements_index(f, id, j)].y);
00174 n_measurements += 2;
00175 }
00176 } else {
00177 for (int j=0; j<4; j++) {
00178
00179 int index = f*(n_markers*4*2) + i*(4*2) + j*2;
00180 cvmSet(weight_mat, index+0, 0, 0.);
00181 cvmSet(weight_mat, index+1, 0, 0.);
00182 }
00183 }
00184 }
00185 }
00186
00187
00188 optimization_keyframes = n_images;
00189 optimization_markers = 0;
00190 for(size_t i = 0; i < marker_indices.size(); ++i) if (marker_status[i] > 0) optimization_markers++;
00191 Optimization optimization(n_params, n_meas);
00192 cout<<"Optimizing with "<<optimization_keyframes<<" keyframes and "<<optimization_markers<<" markers"<<endl;
00193 optimization_error =
00194 optimization.Optimize(parameters_mat, measurements_mat, stop, max_iter,
00195 Est, 0, method, parameters_mask_mat, NULL, weight_mat);
00196 optimization_error /= n_measurements;
00197 cout<<"Optimization error per corner: "<<optimization_error<<endl;
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 for(size_t i = 0; i < marker_indices.size(); ++i) {
00235 int id = marker_indices[i];
00236 for (int j=0; j<4; j++) {
00237
00238 int index = frames*7 + i*(3*4) + j*3;
00239 pointcloud[pointcloud_index(id,j)].x = cvmGet(parameters_mat, index+0,0);
00240 pointcloud[pointcloud_index(id,j)].y = cvmGet(parameters_mat, index+1,0);
00241 pointcloud[pointcloud_index(id,j)].z = cvmGet(parameters_mat, index+2,0);
00242 }
00243 }
00244
00245 cvReleaseMat(¶meters_mat);
00246 cvReleaseMat(¶meters_mask_mat);
00247 cvReleaseMat(&measurements_mat);
00248
00249 optimizing = false;
00250 return true;
00251 }
00252
00253 void MultiMarkerBundle::_MeasurementsAdd(MarkerIterator &begin, MarkerIterator &end, const Pose& camera_pose) {
00254 camera_poses.push_back(camera_pose);
00255 int frame_no = camera_poses.size()-1;
00256
00257 for (MarkerIterator &i = begin.reset(); i != end; ++i)
00258 {
00259 const Marker* marker = *i;
00260 int id = marker->GetId();
00261 int index = get_id_index(id);
00262 if (index < 0) continue;
00263
00264 for (int j = 0; j<4; j++) {
00265 measurements[measurements_index(frame_no, id, j)] =
00266 marker->marker_corners_img[j];
00267
00268 }
00269
00270 }
00271 }
00272
00273 }