#ifndef BundleAdjustment_LM_H__ #define BundleAdjustment_LM_H__ #include "Eye.h" #include "BundleAdjustment.h" #include "../math/methods.h" #include "../math/Vector.h" #include "../math/Matrix.h" #include "../math/utility.h" #include "../oo/ObjBase.h" #include namespace meow { template class BundleAdjustment_LM: public BundleAdjustment { private: struct MatchPair { size_t from_i; Matrix from_m; size_t to_i; Matrix to_m; }; class NoOffsetController { private: std::vector* pairs_; std::vector >* rot_; std::vector >* pho_; BallProjection bll_; bool flag; public: NoOffsetController(std::vector* pairs, std::vector >* rot, std::vector >* pho, bool fg): pairs_(pairs), rot_(rot), pho_(pho), bll_(3.0, 1.0), flag(fg) { } Vector init() { if (flag == false) { Vector v(4, 0.0); int i = (*pho_).size() - 1, n = 0; v.entry(n++, (*pho_)[i].focal()); v.entry(n++, (*rot_)[i].theta(0)); v.entry(n++, (*rot_)[i].theta(1)); v.entry(n++, (*rot_)[i].theta(2)); return v; } Vector v((*rot_).size() * 4, 0.0); for (size_t n = 0, i = 0, I = (*rot_).size(); i < I; ++i) { v.entry(n++, (*pho_)[i].focal()); v.entry(n++, (*rot_)[i].theta(0)); v.entry(n++, (*rot_)[i].theta(1)); v.entry(n++, (*rot_)[i].theta(2)); } return v; } Vector residure(Vector const& v) { for (size_t n = 0, i = 0, I = (*rot_).size(); i < I; ++i) { if (flag == false && i != I - 1) continue; (*pho_)[i].focal(v(n++)); (*rot_)[i].theta(0, v(n++)); (*rot_)[i].theta(1, v(n++)); (*rot_)[i].theta(2, v(n++)); } for (typename std::vector::iterator it = (*pairs_).begin(), ed = (*pairs_).end(); it != ed; ++it) { (*it).from_m.entry(2, 0, -(*pho_)[(*it).from_i].focal()); (*it). to_m.entry(2, 0, -(*pho_)[(*it). to_i].focal()); } // Vector ret((*pairs_).size() * 2, 0.0); size_t n = 0; for (typename std::vector::iterator it = (*pairs_).begin(), ed = (*pairs_).end(); it != ed; ++it, ++n) { Matrix tr( (*it).to_m - (*pho_)[(*it).to_i].transformate( (*rot_)[(*it).to_i].transformate( (*rot_)[(*it).from_i].transformateInv( bll_.transformate( (*it).from_m ) ) ) ) ); ret.entry(n * 2 , tr(0, 0)); ret.entry(n * 2 + 1, tr(1, 0)); } //* //for (size_t i = 0; i < ret.dimension(); i++) { // printf("(%-9.1f ", ret(i)); // if (i % 8 == 7) printf("\n"); //} //printf("\n"); printf("re = %20.5f ?? %f\n", ret.length2(), 25.0 * (*pairs_).size()); // */ return ret; } Matrix jacobian() const { Matrix ret; if (flag == false) { ret.reset((*pairs_).size() * 2, 4, 0.0); } else { ret.reset((*pairs_).size() * 2, (*rot_).size() * 4, 0.0); } size_t n = 0; for (typename std::vector::iterator it = (*pairs_).begin(), ed = (*pairs_).end(); it != ed; ++it, ++n) { Matrix tr_A( bll_ .transformate((*it).from_m)); Matrix tr_B((*rot_)[(*it).from_i].transformateInv(tr_A)); Matrix tr_C((*rot_)[(*it). to_i].transformate (tr_B)); Matrix ja_A((*pho_)[(*it). to_i].jacobian (tr_C)); Matrix ja_B((*rot_)[(*it). to_i].jacobian (tr_B)); Matrix ja_C((*rot_)[(*it).from_i].jacobianInv(tr_A)); Matrix m; int fr = (flag == false ? 0 : (*it).from_i); int to = (flag == false ? 0 : (*it). to_i); if (flag != false || (*it).from_i == (*rot_).size() - 1) { m = ja_A * ja_B * ja_C * bll_.jacobian((*it).from_m).col(2); ret.entry(n * 2 , fr * 4, m(0, 0)); ret.entry(n * 2 + 1, fr * 4, m(1, 0)); for (size_t k = 0; k < 3; ++k) { m = ja_A * ja_B * (*rot_)[(*it).from_i].jacobianInv(tr_A, k); ret.entry(n * 2 , fr * 4 + 1 + k, m(0, 0)); ret.entry(n * 2 + 1, fr * 4 + 1 + k, m(1, 0)); } } if (flag != false || (*it).to_i == (*rot_).size() - 1) { m = (*pho_)[(*it).to_i].jacobian(tr_C, 0); ret.entry(n * 2 , to * 4, m(0, 0)); ret.entry(n * 2 + 1, to * 4, m(1, 0)); for (size_t k = 0; k < 3; ++k) { m = ja_A * (*rot_)[(*it).to_i].jacobian(tr_B, k); ret.entry(n * 2 , to * 4 + 1 + k, m(0, 0)); ret.entry(n * 2 + 1, to * 4 + 1 + k, m(1, 0)); } } } return ret; } Matrix identity() const { if (flag == false) { Matrix ret(4, 4, 0.0); ret.identitied(); return ret; } Matrix ret((*rot_).size() * 4, (*rot_).size() * 4, 0.0); ret.identitied(); return ret; } }; struct Myself { double t_; Myself(): t_(5.0) { } Myself(Myself const& m): t_(m.t_) { } ~Myself() { } }; Self const self; public: BundleAdjustment_LM(): self() { } BundleAdjustment_LM(BundleAdjustment_LM const& b): self(b.self, Self::COPY_FROM) { } ~BundleAdjustment_LM() { } BundleAdjustment_LM& copyFrom(BundleAdjustment_LM const& b) { self().copyFrom(b.self); return *this; } BundleAdjustment_LM& referenceFrom(BundleAdjustment_LM const& b) { self().referenceFrom(b.self); return *this; } double threshold() const { return self->t_; } double threshold(double t) { self()->t_ = t; return threshold(); } bool adjustEye(std::vector >* seq) const { // check size_t N = (*seq).size(); for (size_t i = 0; i < N; ++i) { if ( (*seq)[i].flag & CAN_OFFSET ) return false; if (!((*seq)[i].flag & CAN_ROTATE)) return false; if (!((*seq)[i].flag & CAN_ZOOM )) return false; } // get all pairs typedef typename Camera::FixedPoints2D::IdentityPointsMapIterK FPS_K; std::vector beg(N), end(N); FPS_K it1, it2; for (size_t i = 0; i < N; ++i) { beg[i] = (*seq)[i].eye->camera().fixedPoints2D().identityPoints().begin(); end[i] = (*seq)[i].eye->camera().fixedPoints2D().identityPoints().end (); } std::vector > > all_pairs(N); for (size_t i = 0; i < N; ++i) { all_pairs[i].resize(N); for (size_t j = 0; j < N; ++j) { if (i == j) continue; for (it1 = beg[i], it2 = beg[j]; it1 != end[i] && it2 != end[j]; ) { if (it1->first < it2->first) ++it1; else if(it1->first > it2->first) ++it2; else { MatchPair tmp; tmp.from_i = i; tmp.from_m = it1->second.matrix(); tmp.from_m.rows(3, -(*seq)[i].eye->camera().photo().focal()); tmp. to_i = j; tmp. to_m = it2->second.matrix(); tmp. to_m.rows(3, -(*seq)[j].eye->camera().photo().focal()); all_pairs[i][j].push_back(tmp); ++it1; ++it2; } } } } // std::vector pairs; std::vector > rot; std::vector > pho; std::vector sum (N, 0); std::vector big (N, 0); std::vector real(N); std::vector rev (N); // first!! int best = -1, best_ct = -1; for (size_t i = 0; i < N; ++i) { int d = 0; for (size_t j = 0; j < N; ++j) { d += all_pairs[i][j].size(); } if (best_ct < d) { best_ct = d; best = i; } real[i] = i; big [i] = i; } for (size_t i = 0; i < N; ++i) { // update else real[i] = best; rev[best] = i; for (size_t j = 0; j < N; ++j) { if ((int)j == best) { sum[j] = -1; continue; } if (sum[j] < 0) continue; sum[j] += all_pairs[best][j].size(); if (all_pairs[j][big[j]].size() < all_pairs[j][best].size()) big[j] = best; } // add me printf("%d same as %d\n", best, big[best]); if (big[best] == best) { rot.push_back((*seq)[big[best]].eye->camera() .rotation()); pho.push_back((*seq)[big[best]].eye->camera().photo().projection()); } else { rot.push_back(rot[rev[big[best]]]); pho.push_back(pho[rev[big[best]]]); } for (size_t j = 0; j < N; ++j) { if (sum[j] >= 0) continue; for (size_t k = 0, K = all_pairs[best][j].size(); k < K; ++k) { all_pairs[best][j][k].from_i = rev[all_pairs[best][j][k].from_i]; all_pairs[best][j][k]. to_i = rev[all_pairs[best][j][k]. to_i]; pairs.push_back(all_pairs[best][j][k]); } for (size_t k = 0, K = all_pairs[j][best].size(); k < K; ++k) { all_pairs[j][best][k].from_i = rev[all_pairs[j][best][k].from_i]; all_pairs[j][best][k]. to_i = rev[all_pairs[j][best][k]. to_i]; pairs.push_back(all_pairs[j][best][k]); } } for (size_t j = 0; j < N; ++j) { printf("%4d ", sum[j]); } printf("\n"); for (size_t j = 0; j < N; ++j) { printf("%4d ", big[j]); } printf("\n"); for (size_t j = 0; j < N; ++j) { printf("%4d ", real[j]); } printf("\n"); printf("\n"); // bundle adjustment if (i > 0) { NoOffsetController ct1(&pairs, &rot, &pho, false); ct1.residure(levenbergMarquardtTraining(ct1, ct1.init(), 7.3, 1.0, squ(threshold()) * pairs.size(), 7, 1000)); /* NoOffsetController ct2(&pairs, &rot, &pho, true); ct2.residure(levenbergMarquardtTraining(ct2, ct2.init(), 0.1 * pairs.size(), 1.0, squ(threshold()) * pairs.size(), 7, 1000)); // */ } // find next best_ct = 0; for (size_t j = 0; j < N; ++j) { if (best_ct < sum[j]) { best = j; best_ct = sum[j]; } } getchar(); //if (i == N - 2) break; } // feedback for (size_t i = 0; i < N; ++i) { int id = real[i]; (*seq)[id].eye->cameraGet() .rotation (rot[i]); (*seq)[id].eye->cameraGet().photoGet().projection(pho[i]); //if (i == N - 2) break; } return true; } bool adjustFixedPoint(std::vector >* seq) const { return false; } bool write(FILE* f, bool bin, unsigned int fg) const { return false; } bool read(FILE* f, bool bin, unsigned int fg) const { return false; } ObjBase* create() const { return new BundleAdjustment_LM; } ObjBase* copyFrom(ObjBase const* o) { return &(copyFrom(*(BundleAdjustment_LM const*)o)); } char const* ctype() const { return typeid(*this).name(); } std::string type() const { return std::string(ctype()); } }; } // meow #endif // BundleAdjustment_LM_H__