00001 #include "sparse_bundle_adjustment/sba_file_io.h"
00002 #include <map>
00003
00004 using namespace sba;
00005 using namespace Eigen;
00006 using namespace frame_common;
00007 using namespace std;
00008
00009 int sba::readBundlerFile(const char *filename, SysSBA& sbaout)
00010 {
00011
00012 vector< Vector3d, Eigen::aligned_allocator<Vector3d> > camps;
00013 vector< Matrix3d, Eigen::aligned_allocator<Matrix3d> > camRs;
00014 vector< Vector3d, Eigen::aligned_allocator<Vector3d> > camts;
00015 vector< Vector3d, Eigen::aligned_allocator<Vector3d> > ptps;
00016 vector< Vector3i, Eigen::aligned_allocator<Vector3i> > ptcs;
00017 vector< vector< Vector4d, Eigen::aligned_allocator<Vector4d> > > ptts;
00018
00019 int ret = ParseBundlerFile(filename, camps, camRs, camts, ptps, ptcs, ptts);
00020 if (ret < 0)
00021 return -1;
00022
00023 int ncams = camps.size();
00024 int npts = ptps.size();
00025 int nprjs = 0;
00026 for (int i=0; i<npts; i++)
00027 nprjs += (int)ptts[i].size();
00028
00029
00030
00031 cout << "Setting up nodes..." << flush;
00032 for (int i=0; i<ncams; i++)
00033 {
00034
00035 Vector3d &camp = camps[i];
00036 CamParams cpars = {camp[0],camp[0],0,0,0};
00037
00038
00039
00040
00041
00042
00043
00044
00045 Matrix3d m180x;
00046 m180x << 1, 0, 0, 0, -1, 0, 0, 0, -1;
00047 Matrix3d camR = m180x * camRs[i];
00048 Quaternion<double> frq(camR.transpose());
00049 if (frq.w() < 0.0)
00050 {
00051 frq.x() = -frq.x();
00052 frq.y() = -frq.y();
00053 frq.z() = -frq.z();
00054 frq.w() = -frq.w();
00055 }
00056
00057 frq.normalize();
00058
00059
00060 Vector3d &camt = camts[i];
00061 Vector4d frt;
00062 frt.head<3>() = -camRs[i].transpose() * camt;
00063 frt[3] = 1.0;
00064
00065 Node nd;
00066
00067 sbaout.addNode(frt, frq, cpars);
00068 }
00069
00070
00071
00072 cout << "Setting up points..." << flush;
00073 for (int i=0; i<npts; i++)
00074 {
00075
00076 Vector3d &ptp = ptps[i];
00077 Point pt;
00078 pt.head<3>() = ptp;
00079 pt[3] = 1.0;
00080 sbaout.addPoint(pt);
00081 }
00082
00083
00084
00085 sbaout.useLocalAngles = true;
00086 sbaout.nFixed = 1;
00087
00088
00089 int ntot = 0;
00090 cout << "Setting up projections..." << flush;
00091 for (int i=0; i<npts; i++)
00092 {
00093
00094 vector<Vector4d, Eigen::aligned_allocator<Vector4d> > &ptt = ptts[i];
00095 int nprjs = ptt.size();
00096 for (int j=0; j<nprjs; j++)
00097 {
00098
00099 Vector4d &prj = ptt[j];
00100 int cami = (int)prj[0];
00101 Vector2d pt = prj.segment<2>(2);
00102 pt[1] = -pt[1];
00103 if (cami >= ncams)
00104 cout << "*** Cam index exceeds bounds: " << cami << endl;
00105 sbaout.addMonoProj(cami,i,pt);
00106 ntot++;
00107 }
00108 }
00109 cout << "done" << endl;
00110
00111 return 0;
00112 }
00113
00114 int sba::writeBundlerFile(const char *filename, SysSBA& sbain)
00115 {
00116 ofstream outfile(filename, ios_base::trunc);
00117 if (outfile == NULL)
00118 {
00119 cout << "Can't open file " << filename << endl;
00120 return -1;
00121 }
00122
00123 outfile.precision(10);
00124 outfile.setf(ios_base::scientific);
00125
00126 unsigned int i = 0;
00127
00128 outfile << "# Bundle file v0.3" << endl;
00129
00130 outfile << sbain.nodes.size() << ' ' << sbain.tracks.size() << endl;
00131
00132
00133 Matrix3d m180x;
00134 m180x << 1, 0, 0, 0, -1, 0, 0, 0, -1;
00135
00136
00137
00138 for (i = 0; i < sbain.nodes.size(); i++)
00139 {
00140
00141 outfile << sbain.nodes[i].Kcam(0, 0) << ' ' << 0.0 << ' ' << 0.0 << endl;
00142
00143 Quaternion<double> quat(sbain.nodes[i].qrot);
00144
00145 quat.normalize();
00146 Matrix3d rotmat = m180x * quat.toRotationMatrix().transpose();
00147
00148 outfile << rotmat(0, 0) << ' ' << rotmat(0, 1) << ' ' << rotmat(0, 2) << endl;
00149 outfile << rotmat(1, 0) << ' ' << rotmat(1, 1) << ' ' << rotmat(1, 2) << endl;
00150 outfile << rotmat(2, 0) << ' ' << rotmat(2, 1) << ' ' << rotmat(2, 2) << endl;
00151
00152 Vector3d trans = sbain.nodes[i].trans.head<3>();
00153 trans = -rotmat*trans;
00154 outfile << trans(0) << ' ' << trans(1) << ' ' << trans(2) << endl;
00155 }
00156
00157 outfile.setf(ios_base::fixed);
00158
00159
00160 for (i = 0; i < sbain.tracks.size(); i++)
00161 {
00162
00163 outfile << sbain.tracks[i].point(0) << ' ' << sbain.tracks[i].point(1)
00164 << ' ' << sbain.tracks[i].point(2) << endl;
00165
00166 outfile << "255 255 255" << endl;
00167
00168
00169
00170
00171
00172 ProjMap &prjs = sbain.tracks[i].projections;
00173
00174
00175 outfile << prjs.size() << ' ';
00176
00177
00178 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++)
00179 {
00180 Proj &prj = itr->second;
00181
00182 Node &node = sbain.nodes[prj.ndi];
00183
00184 double cx = node.Kcam(0, 2);
00185 double cy = node.Kcam(1, 2);
00186
00187 outfile << prj.ndi << ' ' << i << ' ' << prj.kp(0)-cx << ' '
00188 << -(prj.kp(1)-cy) << ' ';
00189 }
00190
00191 outfile << endl;
00192 }
00193
00194 return 0;
00195 }
00196
00197 int sba::ParseBundlerFile(const char *fin,
00198 vector< Vector3d, Eigen::aligned_allocator<Vector3d> > &camp,
00199 vector< Matrix3d, Eigen::aligned_allocator<Matrix3d> > &camR,
00200 vector< Vector3d, Eigen::aligned_allocator<Vector3d> > &camt,
00201 vector< Vector3d, Eigen::aligned_allocator<Vector3d> > &ptp,
00202 vector< Vector3i, Eigen::aligned_allocator<Vector3i> > &ptc,
00203 vector< vector< Vector4d, Eigen::aligned_allocator<Vector4d> > > &ptt
00204 )
00205 {
00206 ifstream ifs(fin);
00207 if (ifs == NULL)
00208 {
00209 cout << "Can't open file " << fin << endl;
00210 return -1;
00211 }
00212 ifs.precision(10);
00213
00214
00215
00216 string line;
00217 if (!getline(ifs,line) || line != "# Bundle file v0.3")
00218 {
00219 cout << "Bad header" << endl;
00220 return -1;
00221 }
00222 cout << "Found Bundler 3.0 file" << endl;
00223
00224
00225 int ncams, npts;
00226 if (!(ifs >> ncams >> npts))
00227 {
00228 cout << "Bad header" << endl;
00229 return -1;
00230 }
00231 cout << "Number of cameras: " << ncams << " Number of points: " << npts << endl;
00232
00233 cout << "Reading in camera data..." << flush;
00234 for (int i=0; i<ncams; i++)
00235 {
00236 double v1,v2,v3,v4,v5,v6,v7,v8,v9;
00237 if (!(ifs >> v1 >> v2 >> v3))
00238 {
00239 cout << "Bad camera params at number " << i << endl;
00240 return -1;
00241 }
00242 camp.push_back(Vector3d(v1,v2,v3));
00243
00244 if (!(ifs >> v1 >> v2 >> v3 >> v4 >> v5 >> v6 >> v7 >> v8 >> v9))
00245 {
00246 cout << "Bad camera rotation matrix at number " << i << endl;
00247 return -1;
00248 }
00249 Matrix3d m;
00250 m << v1,v2,v3,v4,v5,v6,v7,v8,v9;
00251 camR.push_back(m);
00252
00253 if (!(ifs >> v1 >> v2 >> v3))
00254 {
00255 cout << "Bad camera translation at number " << i << endl;
00256 return -1;
00257 }
00258 camt.push_back(Vector3d(v1,v2,v3));
00259 }
00260 cout << "done" << endl;
00261
00262 ptt.resize(npts);
00263
00264 cout << "Reading in pts data..." << flush;
00265 for (int i=0; i<npts; i++)
00266 {
00267 double v1,v2,v3;
00268 int i1,i2,i3;
00269
00270 if (!(ifs >> v1 >> v2 >> v3))
00271 {
00272 cout << "Bad point position at number " << i << endl;
00273 return -1;
00274 }
00275 ptp.push_back(Vector3d(v1,v2,v3));
00276
00277 if (!(ifs >> i1 >> i2 >> i3))
00278 {
00279 cout << "Bad point color at number " << i << endl;
00280 return -1;
00281 }
00282 ptc.push_back(Vector3i(i1,i2,i3));
00283
00284
00285 if (!(ifs >> i1))
00286 {
00287 cout << "Bad track count at number " << i << endl;
00288 return -1;
00289 }
00290 int nprjs = i1;
00291
00292 vector<Vector4d, Eigen::aligned_allocator<Vector4d> > &prjs = ptt[i];
00293 for (int j=0; j<nprjs; j++)
00294 {
00295 if (!(ifs >> i1 >> i2 >> v1 >> v2))
00296 {
00297 cout << "Bad track parameter at number " << i << endl;
00298 return -1;
00299 }
00300 prjs.push_back(Vector4d(i1,i2,v1,v2));
00301 }
00302
00303 }
00304 cout << "done" << endl;
00305
00306
00307 double nprjs = 0;
00308 for (int i=0; i<npts; i++)
00309 nprjs += ptt[i].size();
00310 cout << "Number of projections: " << (int)nprjs << endl;
00311 cout << "Average projections per camera: " << nprjs/(double)ncams << endl;
00312 cout << "Average track length: " << nprjs/(double)npts << endl;
00313 return 0;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322 void sba::writeLourakisFile(const char *fname, SysSBA& sba)
00323 {
00324 char name[1024];
00325 sprintf(name,"%s-cams.txt",fname);
00326 FILE *fn = fopen(name,"w");
00327 if (fn == NULL)
00328 {
00329 cout << "[WriteFile] Can't open file " << name << endl;
00330 return;
00331 }
00332
00333
00334 int ncams = sba.nodes.size();
00335 for (int i=0; i<ncams; i++)
00336 {
00337 Node &nd = sba.nodes[i];
00338
00339
00340 Quaternion<double> frq(nd.w2n.block<3,3>(0,0));
00341 fprintf(fn,"%f %f %f %f ", frq.w(), frq.x(), frq.y(), frq.z());
00342 Vector3d tr = nd.w2n.col(3);
00343 fprintf(fn,"%f %f %f\n", tr[0], tr[1], tr[2]);
00344 }
00345 fclose(fn);
00346
00347 sprintf(name,"%s-pts.txt",fname);
00348 fn = fopen(name,"w");
00349 if (fn == NULL)
00350 {
00351 cout << "[WriteFile] Can't open file " << name << endl;
00352 return;
00353 }
00354
00355 fprintf(fn,"# X Y Z nframes frame0 x0 y0 frame1 x1 y1 ...\n");
00356
00357
00358
00359 for(size_t i=0; i<sba.tracks.size(); i++)
00360 {
00361 ProjMap &prjs = sba.tracks[i].projections;
00362
00363 Point &pt = sba.tracks[i].point;
00364
00365 fprintf(fn,"%f %f %f ", pt.x(), pt.y(), pt.z());
00366 fprintf(fn,"%d ",(int)prjs.size());
00367
00368
00369 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++)
00370 {
00371 Proj &prj = itr->second;
00372 if (!prj.isValid) continue;
00373 int cami = itr->first;
00374
00375 fprintf(fn," %d %f %f ",cami,prj.kp[0],prj.kp[1]);
00376 }
00377 fprintf(fn,"\n");
00378 }
00379
00380 fclose(fn);
00381
00382
00383 sprintf(name,"%s-calib.txt",fname);
00384 fn = fopen(name,"w");
00385 if (fn == NULL)
00386 {
00387 cout << "[WriteFile] Can't open file " << name << endl;
00388 return;
00389 }
00390
00391 Matrix3d &K = sba.nodes[0].Kcam;
00392 fprintf(fn,"%f %f %f\n", K(0,0), K(0,1), K(0,2));
00393 fprintf(fn,"%f %f %f\n", K(1,0), K(1,1), K(1,2));
00394 fprintf(fn,"%f %f %f\n", K(2,0), K(2,1), K(2,2));
00395
00396 fclose(fn);
00397 }
00398
00399
00400
00401 void sba::writeA(const char *fname, SysSBA& sba)
00402 {
00403 ofstream ofs(fname);
00404 if (ofs == NULL)
00405 {
00406 cout << "Can't open file " << fname << endl;
00407 return;
00408 }
00409
00410
00411 Eigen::IOFormat pfmt(16);
00412 ofs << sba.A.format(pfmt) << endl;
00413 ofs.close();
00414 }
00415
00416
00417
00418 void sba::writeSparseA(const char *fname, SysSBA& sba)
00419 {
00420 char name[1024];
00421 sprintf(name,"%s-A.tri",fname);
00422
00423 {
00424 ofstream ofs(name);
00425 if (ofs == NULL)
00426 {
00427 cout << "Can't open file " << fname << endl;
00428 return;
00429 }
00430
00431
00432 Eigen::IOFormat pfmt(16);
00433
00434 int nrows = sba.A.rows();
00435 int ncols = sba.A.cols();
00436
00437 cout << "[WriteSparseA] Size: " << nrows << "x" << ncols << endl;
00438
00439
00440 int nnz = 0;
00441 for (int i=0; i<nrows; i++)
00442 for (int j=i; j<ncols; j++)
00443 {
00444 double a = sba.A(i,j);
00445 if (a != 0.0) nnz++;
00446 }
00447
00448 ofs << nrows << " " << ncols << " " << nnz << " 1" << endl;
00449
00450 for (int i=0; i<nrows; i++)
00451 for (int j=i; j<ncols; j++)
00452 {
00453 double a = sba.A(i,j);
00454 if (a != 0.0)
00455 ofs << i << " " << j << " " << setprecision(16) << a << endl;
00456 }
00457
00458 ofs.close();
00459 }
00460
00461 sprintf(name,"%s-B.txt",fname);
00462
00463 {
00464 ofstream ofs(name);
00465 if (ofs == NULL)
00466 {
00467 cout << "Can't open file " << fname << endl;
00468 return;
00469 }
00470
00471
00472 Eigen::IOFormat pfmt(16);
00473
00474 int nrows = sba.B.rows();
00475
00476 ofs << nrows << " " << 1 << endl;
00477
00478 for (int i=0; i<nrows; i++)
00479 {
00480 double a = sba.B(i);
00481 ofs << setprecision(16) << a << endl;
00482 }
00483 ofs.close();
00484 }
00485 }
00486
00487
00488 int sba::readGraphFile(const char *filename, SysSBA& sbaout)
00489 {
00490
00491 vector< Vector5d, Eigen::aligned_allocator<Vector5d> > camps;
00492 vector< Vector4d, Eigen::aligned_allocator<Vector4d> > camqs;
00493 vector< Vector3d, Eigen::aligned_allocator<Vector3d> > camts;
00494 vector< Vector3d, Eigen::aligned_allocator<Vector3d> > ptps;
00495 vector< vector< Vector11d, Eigen::aligned_allocator<Vector11d> > > ptts;
00496
00497 int ret = ParseGraphFile(filename, camps, camqs, camts, ptps, ptts);
00498 if (ret < 0)
00499 return -1;
00500
00501 int ncams = camps.size();
00502 int npts = ptps.size();
00503 int nprjs = 0;
00504 for (int i=0; i<npts; i++)
00505 nprjs += (int)ptts[i].size();
00506
00507
00508
00509
00510 for (int i=0; i<ncams; i++)
00511 {
00512
00513 Vector5d &camp = camps[i];
00514 CamParams cpars = {camp[0],camp[1],camp[2],camp[3],camp[4]};
00515
00516
00517
00518
00519
00520 Quaternion<double> frq(camqs[i]);
00521 if (frq.w() < 0.0)
00522 {
00523 frq.x() = -frq.x();
00524 frq.y() = -frq.y();
00525 frq.z() = -frq.z();
00526 frq.w() = -frq.w();
00527 }
00528
00529 frq.normalize();
00530
00531
00532 Vector3d &camt = camts[i];
00533 Vector4d frt;
00534 frt.head<3>() = camt;
00535 frt[3] = 1.0;
00536
00537 Node nd;
00538
00539 sbaout.addNode(frt, frq, cpars);
00540 }
00541
00542
00543
00544
00545 for (int i=0; i<npts; i++)
00546 {
00547
00548 Vector3d &ptp = ptps[i];
00549 Point pt;
00550 pt.head<3>() = ptp;
00551 pt[3] = 1.0;
00552 sbaout.addPoint(pt);
00553 }
00554
00555
00556
00557 sbaout.useLocalAngles = true;
00558 sbaout.nFixed = 1;
00559
00560
00561 int ntot = 0;
00562
00563 for (int i=0; i<npts; i++)
00564 {
00565
00566 vector<Vector11d, Eigen::aligned_allocator<Vector11d> > &ptt = ptts[i];
00567 int nprjs = ptt.size();
00568 for (int j=0; j<nprjs; j++)
00569 {
00570
00571 Vector11d &prj = ptt[j];
00572 int cami = (int)prj[0];
00573 if (cami >= ncams)
00574 cout << "*** Cam index exceeds bounds: " << cami << endl;
00575 if (prj[4] > 0)
00576 {
00577 Vector3d pt = prj.segment<3>(2);
00578 sbaout.addStereoProj(cami,i,pt);
00579 }
00580 else
00581 {
00582 Vector2d pt = prj.segment<2>(2);
00583 sbaout.addMonoProj(cami,i,pt);
00584 }
00585
00586 ntot++;
00587 }
00588 }
00589
00590
00591 return 0;
00592 }
00593
00594
00595
00596
00597 static void make_qrot(double rr, double rp, double ry, Vector4d &v)
00598 {
00599 double sr = sin(rr/2.0);
00600 double cr = cos(rr/2.0);
00601 double sp = sin(rp/2.0);
00602 double cp = cos(rp/2.0);
00603 double sy = sin(ry/2.0);
00604 double cy = cos(ry/2.0);
00605 v[0] = sr*cp*cy - cr*sp*sy;
00606 v[1] = cr*sp*cy + sr*cp*sy;
00607 v[2] = cr*cp*sy - sr*sp*cy;
00608 v[3] = cr*cp*cy + sr*sp*sy;
00609 }
00610
00611 int sba::ParseGraphFile(const char *fin,
00612 vector< Vector5d, Eigen::aligned_allocator<Vector5d> > &camp,
00613 vector< Vector4d, Eigen::aligned_allocator<Vector4d> > &camq,
00614 vector< Vector3d, Eigen::aligned_allocator<Vector3d> > &camt,
00615 vector< Vector3d, Eigen::aligned_allocator<Vector3d> > &ptp,
00616
00617
00618 vector< vector< Vector11d, Eigen::aligned_allocator<Vector11d> > > &ptts
00619 )
00620 {
00621
00622 ifstream ifs(fin);
00623 if (ifs == NULL)
00624 {
00625 cout << "Can't open file " << fin << endl;
00626 return -1;
00627 }
00628 ifs.precision(10);
00629
00630
00631 map<int,int> nodemap;
00632 map<int,int> pointmap;
00633
00634
00635 string line;
00636 int nline = 0;
00637 int nid = 0;
00638 int pid = 0;
00639 while (getline(ifs,line))
00640 {
00641 nline++;
00642 stringstream ss(line);
00643 string type;
00644 ss >> type;
00645 size_t pos = type.find("#");
00646 if (pos != string::npos)
00647 continue;
00648
00649 if (type == "VERTEX_SE3" ||
00650 type == "VERTEX_CAM")
00651 {
00652 int n;
00653 double tx,ty,tz,qx,qy,qz,qw,fx,fy,cx,cy,bline;
00654 if (!(ss >> n >> tx >> ty >> tz >> qx >> qy >> qz >> qw >> fx >> fy >>
00655 cx >> cy >> bline))
00656 {
00657 cout << "[ReadSPA] Bad VERTEX_SE3 at line " << nline << endl;
00658 return -1;
00659 }
00660 nodemap.insert(pair<int,int>(n,nid));
00661 nid++;
00662 camt.push_back(Vector3d(tx,ty,tz));
00663 Vector4d v(qx,qy,qz,qw);
00664
00665 camq.push_back(v);
00666
00667
00668 Vector5d cp;
00669 cp << fx,fy,cx,cy,bline;
00670 camp.push_back(cp);
00671 }
00672
00673 else if (type == "VERTEX_XYZ")
00674 {
00675 int n;
00676 double tx,ty,tz;
00677 if (!(ss >> n >> tx >> ty >> tz))
00678 {
00679 cout << "[ReadSPA] Bad VERTEX_XYZ at line " << nline << endl;
00680 return -1;
00681 }
00682 pointmap.insert(pair<int,int>(n,pid));
00683 pid++;
00684 ptp.push_back(Vector3d(tx,ty,tz));
00685 }
00686
00687 else if (type == "EDGE_PROJECT_XYZ" ||
00688 type == "EDGE_PROJECT_P2MC" ||
00689 type == "EDGE_PROJECT_P2SC")
00690 {
00691 int n1,n2;
00692 double u,v,d;
00693 double cv0, cv1, cv2, cv3, cv4, cv5;
00694 cv3 = cv4 =cv5 = 0.0;
00695
00696
00697 d = 0;
00698 if (type == "EDGE_PROJECT_P2SC")
00699 {
00700 if (!(ss >> n1 >> n2 >> u >> v >> d >>
00701 cv0 >> cv1 >> cv2 >> cv3 >> cv4 >> cv5))
00702 {
00703 cout << "[ReadSPA] Bad EDGE_PROJECT_XYZ at line " << nline << endl;
00704 return -1;
00705 }
00706 }
00707 else
00708 {
00709 if (!(ss >> n1 >> n2 >> u >> v >> cv0 >> cv1 >> cv2))
00710 {
00711 cout << "[ReadSPA] Bad EDGE_PROJECT_XYZ at line " << nline << endl;
00712 return -1;
00713 }
00714 }
00715
00716
00717 map<int,int>::iterator it;
00718 it = pointmap.find(n1);
00719 if (it == pointmap.end())
00720 {
00721 cout << "[ReadSPA] Missing point index " << n1 << " at line " << nline << endl;
00722 return -1;
00723 }
00724 int pi = it->second;
00725 if (pi >= (int)ptp.size())
00726 {
00727 cout << "[ReadSPA] Point index " << pi << " too large at line " << nline << endl;
00728 return -1;
00729 }
00730
00731
00732 it = nodemap.find(n2);
00733 if (it == nodemap.end())
00734 {
00735 cout << "[ReadSPA] Missing camera index " << n2 << " at line " << nline << endl;
00736 return -1;
00737 }
00738 int ci = it->second;
00739 if (ci >= (int)camp.size())
00740 {
00741 cout << "[ReadSPA] Camera index " << ci << " too large at line " << nline << endl;
00742 return -1;
00743 }
00744
00745
00746
00747 if (ptts.size() < (size_t)pi+1)
00748 ptts.resize(pi+1);
00749 vector< Vector11d, Eigen::aligned_allocator<Vector11d> > &trk = ptts[pi];
00750 Vector11d tv;
00751 tv << ci,pi,u,v,d,cv0,cv1,cv2,cv3,cv4,cv5;
00752 trk.push_back(tv);
00753 }
00754
00755 else
00756 {
00757 cout << "[ReadSPA] Undefined type <" << type <<"> at line " << nline << endl;
00758 return -1;
00759 }
00760 }
00761
00762
00763 double nprjs = 0;
00764 int ncams = camp.size();
00765 int npts = ptp.size();
00766 for (int i=0; i<npts; i++)
00767 nprjs += ptts[i].size();
00768 cout << "Number of cameras: " << ncams << endl;
00769 cout << "Number of points: " << npts << endl;
00770 cout << "Number of projections: " << (int)nprjs << endl;
00771 cout << "Average projections per camera: " << nprjs/(double)ncams << endl;
00772 cout << "Average track length: " << nprjs/(double)npts << endl;
00773 return 0;
00774 }
00775
00776
00783 int sba::writeGraphFile(const char *filename, SysSBA& sba, bool mono)
00784 {
00785 ofstream outfile(filename, ios_base::trunc);
00786 if (outfile == NULL)
00787 {
00788 cout << "Can't open file " << filename << endl;
00789 return -1;
00790 }
00791
00792 outfile.precision(5);
00793
00794 outfile.setf(ios_base::fixed);
00795
00796 unsigned int i = 0;
00797
00798
00799
00800
00801
00802
00803
00804
00805 int ncams = sba.nodes.size();
00806 for (i = 0; i < (unsigned int)ncams; i++)
00807 {
00808 outfile << "VERTEX_CAM" << " ";
00809 outfile << i << " ";
00810 Vector3d trans = sba.nodes[i].trans.head<3>();
00811 outfile << trans(0) << ' ' << trans(1) << ' ' << trans(2) << ' ';
00812 Vector4d rot = sba.nodes[i].qrot.coeffs();
00813 outfile << rot(0) << ' ' << rot(1) << ' ' << rot(2) << ' ' << rot(3) << ' ';
00814
00815 outfile << sba.nodes[i].Kcam(0,0) << ' ' << sba.nodes[i].Kcam(1,1) << ' ' <<
00816 sba.nodes[i].Kcam(0,2) << ' ' << sba.nodes[i].Kcam(1,2) << ' ' << sba.nodes[i].baseline << endl;
00817 }
00818
00819
00820
00821
00822
00823
00824 for (i = 0; i < sba.tracks.size(); i++)
00825 {
00826 outfile << "VERTEX_XYZ" << ' ' << ncams+i << ' ';
00827
00828 outfile << sba.tracks[i].point(0) << ' ' << sba.tracks[i].point(1)
00829 << ' ' << sba.tracks[i].point(2) << endl;
00830
00831 ProjMap &prjs = sba.tracks[i].projections;
00832
00833
00834
00835 for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++)
00836 {
00837
00838 Proj &prj = itr->second;
00839 if (prj.stereo && !mono)
00840 {
00841 outfile << "EDGE_PROJECT_P2SC ";
00842 outfile << ncams+i << ' ' << prj.ndi << ' ' << prj.kp(0) << ' '
00843 << prj.kp(1) << ' ' << prj.kp(2) << ' ';
00844 outfile << "1 0 0 0 1 1" << endl;
00845 }
00846 else
00847 {
00848 outfile << "EDGE_PROJECT_P2MC ";
00849 outfile << ncams+i << ' ' << prj.ndi << ' ' << prj.kp(0) << ' '
00850 << prj.kp(1) << ' ';
00851 outfile << "1 0 1" << endl;
00852 }
00853 }
00854 }
00855
00856 return 0;
00857 }
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869 void
00870 addnode(SysSPA &spa, int n,
00871 std::vector< Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d> > ntrans,
00872 std::vector< Eigen::Vector4d, Eigen::aligned_allocator<Eigen::Vector4d> > nqrot,
00873 std::vector< Eigen::Vector2i, Eigen::aligned_allocator<Eigen::Vector2i> > cind,
00874 std::vector< Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d> > ctrans,
00875 std::vector< Eigen::Vector4d, Eigen::aligned_allocator<Eigen::Vector4d> > cqrot,
00876 std::vector< Eigen::Matrix<double,6,6>, Eigen::aligned_allocator<Eigen::Matrix<double,6,6> > > prec)
00877 {
00878 Node nd;
00879
00880
00881 Quaternion<double> frq;
00882 frq.coeffs() = nqrot[n];
00883 #if 0
00884 frq.normalize();
00885 if (frq.w() <= 0.0) frq.coeffs() = -frq.coeffs();
00886 nd.qrot = frq.coeffs();
00887 #endif
00888
00889
00890 Vector4d v;
00891 v.head(3) = ntrans[n];
00892 v(3) = 1.0;
00893
00894 spa.addNode(v,frq);
00895
00896 #if 0
00897 nd.trans = v;
00898 nd.setTransform();
00899 nd.setDr(true);
00900
00901
00902 spa.nodes.push_back(nd);
00903 #endif
00904
00905
00906 for (int i=0; i<(int)ctrans.size(); i++)
00907 {
00908 ConP2 con;
00909 con.ndr = cind[i].x();
00910 con.nd1 = cind[i].y();
00911
00912 if ((con.ndr == n && con.nd1 <= n-1) ||
00913 (con.nd1 == n && con.ndr <= n-1))
00914 {
00915 con.tmean = ctrans[i];
00916 Quaternion<double> qr;
00917 qr.coeffs() = cqrot[i];
00918 qr.normalize();
00919 con.qpmean = qr.inverse();
00920 con.prec = prec[i];
00921
00922
00923
00924 spa.p2cons.push_back(con);
00925 }
00926 }
00927 }
00928
00929 int sba::readSPAGraphFile(const char *filename, SysSPA& spaout)
00930 {
00931
00932 std::vector< Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d> > ntrans;
00933 std::vector< Eigen::Vector4d, Eigen::aligned_allocator<Eigen::Vector4d> > nqrot;
00934 std::vector< Eigen::Vector2i, Eigen::aligned_allocator<Eigen::Vector2i> > cind;
00935 std::vector< Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d> > ctrans;
00936 std::vector< Eigen::Vector4d, Eigen::aligned_allocator<Eigen::Vector4d> > cqrot;
00937 std::vector< Eigen::Matrix<double,6,6>, Eigen::aligned_allocator<Eigen::Matrix<double,6,6> > > prec;
00938
00939 int ret = ParseSPAGraphFile(filename, ntrans, nqrot, cind, ctrans, cqrot, prec);
00940 if (ret < 0)
00941 return -1;
00942
00943 cout << "# [ReadSPAFile] Found " << (int)ntrans.size() << " nodes and "
00944 << (int)cind.size() << " constraints" << endl;
00945
00946 int nnodes = ntrans.size();
00947
00948
00949 for (int i=0; i<nnodes; i++)
00950 addnode(spaout, i, ntrans, nqrot, cind, ctrans, cqrot, prec);
00951
00952 return 0;
00953 }
00954
00955
00956
00957 void make_covar(double *cv, Matrix<double,6,6> &m)
00958 {
00959 m.setZero();
00960
00961 int i = 0;
00962 m(0,0) = cv[i++];
00963 m(0,1) = cv[i++];
00964 m(0,2) = cv[i++];
00965 m(0,3) = cv[i++];
00966 m(0,4) = cv[i++];
00967 m(0,5) = cv[i++];
00968
00969 m(1,1) = cv[i++];
00970 m(1,2) = cv[i++];
00971 m(1,3) = cv[i++];
00972 m(1,4) = cv[i++];
00973 m(1,5) = cv[i++];
00974
00975 m(2,2) = cv[i++];
00976 m(2,3) = cv[i++];
00977 m(2,4) = cv[i++];
00978 m(2,5) = cv[i++];
00979
00980 m(3,3) = cv[i++];
00981 m(3,4) = cv[i++];
00982 m(3,5) = cv[i++];
00983
00984 m(4,4) = cv[i++];
00985 m(4,5) = cv[i++];
00986
00987 m(5,5) = cv[i++];
00988
00989
00990 Matrix<double,6,6> mt = m.transpose();
00991 mt.diagonal().setZero();
00992 m = m+mt;
00993 }
00994
00995 int
00996 sba::ParseSPAGraphFile(const char *fin,
00997 std::vector< Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d> > &ntrans,
00998 std::vector< Eigen::Vector4d, Eigen::aligned_allocator<Eigen::Vector4d> > &nqrot,
00999 std::vector< Eigen::Vector2i, Eigen::aligned_allocator<Eigen::Vector2i> > &cind,
01000 std::vector< Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d> > &ctrans,
01001 std::vector< Eigen::Vector4d, Eigen::aligned_allocator<Eigen::Vector4d> > &cqrot,
01002 std::vector< Eigen::Matrix<double,6,6>, Eigen::aligned_allocator<Eigen::Matrix<double,6,6> > > &prec)
01003 {
01004 ifstream ifs(fin);
01005 if (ifs == NULL)
01006 {
01007 cout << "Can't open file " << fin << endl;
01008 return -1;
01009 }
01010 ifs.precision(10);
01011
01012
01013 string line;
01014 int nline = 0;
01015 bool first = true;
01016 while (getline(ifs,line))
01017 {
01018 nline++;
01019 stringstream ss(line);
01020 string type;
01021 ss >> type;
01022 size_t pos = type.find("#");
01023 if (pos != string::npos)
01024 continue;
01025
01026 if (type == "VERTEX_SE3")
01027 {
01028 int n;
01029 double tx,ty,tz,rr,rp,ry;
01030 if (!(ss >> n >> tx >> ty >> tz >> rr >> rp >> ry))
01031 {
01032 cout << "[ReadSPA] Bad VERTEX_SE3 at line " << nline << endl;
01033 return -1;
01034 }
01035 ntrans.push_back(Vector3d(tx,ty,tz));
01036 Vector4d v;
01037 make_qrot(rr,rp,ry,v);
01038 nqrot.push_back(v);
01039 }
01040
01041 if (type == "EDGE_SE3_SE3")
01042 {
01043 int n1,n2;
01044 double tx,ty,tz,rr,rp,ry;
01045 double cv[21];
01046
01047
01048 if (!(ss >> n1 >> n2 >> tx >> ty >> tz >> rr >> rp >> ry))
01049 {
01050 cout << "[ReadSPA] Bad EDGE_SE3_SE3 at line " << nline << endl;
01051 return -1;
01052 }
01053 cind.push_back(Vector2i(n1,n2));
01054 ctrans.push_back(Vector3d(tx,ty,tz));
01055 Vector4d v;
01056 make_qrot(rr,rp,ry,v);
01057 cqrot.push_back(v);
01058
01059
01060 if (!(ss >> cv[0] >> cv[1] >> cv[2] >> cv[3] >> cv[4]
01061 >> cv[5] >> cv[6] >> cv[7] >> cv[8] >> cv[9]
01062 >> cv[10] >> cv[11] >> cv[12] >> cv[13] >> cv[14]
01063 >> cv[15] >> cv[16] >> cv[17] >> cv[18] >> cv[19] >> cv[20]))
01064 {
01065 cout << "[ReadSPA] Bad EDGE_SE3_SE3 at line " << nline << endl;
01066 return -1;
01067 }
01068 Matrix<double,6,6> m;
01069 make_covar(cv,m);
01070 if (first)
01071 {
01072
01073
01074
01075
01076 first = false;
01077 }
01078 prec.push_back(m);
01079 }
01080
01081 }
01082 return 0;
01083 }