Templates -- Meow  1.1.4
A C++ template which is unable and also not allowed to compile to obj-file first.
BundleAdjustment_LM.h
Go to the documentation of this file.
1 #ifndef BundleAdjustment_LM_H__
2 #define BundleAdjustment_LM_H__
3 
4 #include "Eye.h"
5 
6 #include "BundleAdjustment.h"
7 
8 #include "../math/methods.h"
9 #include "../math/Vector.h"
10 #include "../math/Matrix.h"
11 #include "../math/utility.h"
12 
13 #include "../oo/ObjBase.h"
14 
15 #include <algorithm>
16 
17 namespace meow {
18 
19 template<class Pixel>
20 class BundleAdjustment_LM: public BundleAdjustment<Pixel> {
21 private:
22  struct MatchPair {
23  size_t from_i;
24  Matrix<double> from_m;
25  size_t to_i;
26  Matrix<double> to_m;
27  };
28 
29  class NoOffsetController {
30  private:
31  std::vector<MatchPair >* pairs_;
32  std::vector<Rotation3D <double> >* rot_;
33  std::vector<PhotoProjection<double> >* pho_;
35  bool flag;
36  public:
37  NoOffsetController(std::vector<MatchPair >* pairs,
38  std::vector<Rotation3D<double> >* rot,
39  std::vector<PhotoProjection<double> >* pho,
40  bool fg):
41  pairs_(pairs), rot_(rot), pho_(pho), bll_(3.0, 1.0), flag(fg) {
42  }
43  Vector<double> init() {
44  if (flag == false) {
45  Vector<double> v(4, 0.0);
46  int i = (*pho_).size() - 1, n = 0;
47  v.entry(n++, (*pho_)[i].focal());
48  v.entry(n++, (*rot_)[i].theta(0));
49  v.entry(n++, (*rot_)[i].theta(1));
50  v.entry(n++, (*rot_)[i].theta(2));
51  return v;
52  }
53  Vector<double> v((*rot_).size() * 4, 0.0);
54  for (size_t n = 0, i = 0, I = (*rot_).size(); i < I; ++i) {
55  v.entry(n++, (*pho_)[i].focal());
56  v.entry(n++, (*rot_)[i].theta(0));
57  v.entry(n++, (*rot_)[i].theta(1));
58  v.entry(n++, (*rot_)[i].theta(2));
59  }
60  return v;
61  }
62  Vector<double> residure(Vector<double> const& v) {
63  for (size_t n = 0, i = 0, I = (*rot_).size(); i < I; ++i) {
64  if (flag == false && i != I - 1) continue;
65  (*pho_)[i].focal(v(n++));
66  (*rot_)[i].theta(0, v(n++));
67  (*rot_)[i].theta(1, v(n++));
68  (*rot_)[i].theta(2, v(n++));
69  }
70  for (typename std::vector<MatchPair>::iterator
71  it = (*pairs_).begin(), ed = (*pairs_).end(); it != ed; ++it) {
72  (*it).from_m.entry(2, 0, -(*pho_)[(*it).from_i].focal());
73  (*it). to_m.entry(2, 0, -(*pho_)[(*it). to_i].focal());
74  }
75  //
76  Vector<double> ret((*pairs_).size() * 2, 0.0);
77  size_t n = 0;
78  for (typename std::vector<MatchPair>::iterator
79  it = (*pairs_).begin(), ed = (*pairs_).end(); it != ed; ++it, ++n) {
80  Matrix<double> tr(
81  (*it).to_m
82  -
83  (*pho_)[(*it).to_i].transformate(
84  (*rot_)[(*it).to_i].transformate(
85  (*rot_)[(*it).from_i].transformateInv(
86  bll_.transformate(
87  (*it).from_m
88  )
89  )
90  )
91  )
92  );
93  ret.entry(n * 2 , tr(0, 0));
94  ret.entry(n * 2 + 1, tr(1, 0));
95  }
96  //*
97  //for (size_t i = 0; i < ret.dimension(); i++) {
98  // printf("(%-9.1f ", ret(i));
99  // if (i % 8 == 7) printf("\n");
100  //}
101  //printf("\n");
102  printf("re = %20.5f ?? %f\n", ret.length2(), 25.0 * (*pairs_).size());
103  // */
104  return ret;
105  }
106  Matrix<double> jacobian() const {
107  Matrix<double> ret;
108  if (flag == false) {
109  ret.reset((*pairs_).size() * 2, 4, 0.0);
110  }
111  else {
112  ret.reset((*pairs_).size() * 2, (*rot_).size() * 4, 0.0);
113  }
114  size_t n = 0;
115  for (typename std::vector<MatchPair>::iterator
116  it = (*pairs_).begin(), ed = (*pairs_).end(); it != ed; ++it, ++n) {
117  Matrix<double> tr_A( bll_ .transformate((*it).from_m));
118  Matrix<double> tr_B((*rot_)[(*it).from_i].transformateInv(tr_A));
119  Matrix<double> tr_C((*rot_)[(*it). to_i].transformate (tr_B));
120  Matrix<double> ja_A((*pho_)[(*it). to_i].jacobian (tr_C));
121  Matrix<double> ja_B((*rot_)[(*it). to_i].jacobian (tr_B));
122  Matrix<double> ja_C((*rot_)[(*it).from_i].jacobianInv(tr_A));
123  Matrix<double> m;
124  int fr = (flag == false ? 0 : (*it).from_i);
125  int to = (flag == false ? 0 : (*it). to_i);
126  if (flag != false || (*it).from_i == (*rot_).size() - 1) {
127  m = ja_A * ja_B * ja_C * bll_.jacobian((*it).from_m).col(2);
128  ret.entry(n * 2 , fr * 4, m(0, 0));
129  ret.entry(n * 2 + 1, fr * 4, m(1, 0));
130  for (size_t k = 0; k < 3; ++k) {
131  m = ja_A * ja_B * (*rot_)[(*it).from_i].jacobianInv(tr_A, k);
132  ret.entry(n * 2 , fr * 4 + 1 + k, m(0, 0));
133  ret.entry(n * 2 + 1, fr * 4 + 1 + k, m(1, 0));
134  }
135  }
136  if (flag != false || (*it).to_i == (*rot_).size() - 1) {
137  m = (*pho_)[(*it).to_i].jacobian(tr_C, 0);
138  ret.entry(n * 2 , to * 4, m(0, 0));
139  ret.entry(n * 2 + 1, to * 4, m(1, 0));
140  for (size_t k = 0; k < 3; ++k) {
141  m = ja_A * (*rot_)[(*it).to_i].jacobian(tr_B, k);
142  ret.entry(n * 2 , to * 4 + 1 + k, m(0, 0));
143  ret.entry(n * 2 + 1, to * 4 + 1 + k, m(1, 0));
144  }
145  }
146  }
147  return ret;
148  }
149  Matrix<double> identity() const {
150  if (flag == false) {
151  Matrix<double> ret(4, 4, 0.0);
152  ret.identitied();
153  return ret;
154  }
155  Matrix<double> ret((*rot_).size() * 4, (*rot_).size() * 4, 0.0);
156  ret.identitied();
157  return ret;
158  }
159  };
160 
161  struct Myself {
162  double t_;
163 
164  Myself(): t_(5.0) {
165  }
166 
167  Myself(Myself const& m): t_(m.t_) {
168  }
169 
170  ~Myself() {
171  }
172  };
173 
174  Self<Myself> const self;
175 
176 public:
178  }
179 
181  self(b.self, Self<Myself>::COPY_FROM) {
182  }
183 
185  }
186 
188  self().copyFrom(b.self);
189  return *this;
190  }
191 
193  self().referenceFrom(b.self);
194  return *this;
195  }
196 
197  double threshold() const {
198  return self->t_;
199  }
200 
201  double threshold(double t) {
202  self()->t_ = t;
203  return threshold();
204  }
205 
206  bool adjustEye(std::vector<SceneInfo<Pixel> >* seq) const {
207  // check
208  size_t N = (*seq).size();
209  for (size_t i = 0; i < N; ++i) {
210  if ( (*seq)[i].flag & CAN_OFFSET ) return false;
211  if (!((*seq)[i].flag & CAN_ROTATE)) return false;
212  if (!((*seq)[i].flag & CAN_ZOOM )) return false;
213  }
214  // get all pairs
216  std::vector<FPS_K> beg(N), end(N);
217  FPS_K it1, it2;
218  for (size_t i = 0; i < N; ++i) {
219  beg[i] = (*seq)[i].eye->camera().fixedPoints2D().identityPoints().begin();
220  end[i] = (*seq)[i].eye->camera().fixedPoints2D().identityPoints().end ();
221  }
222  std::vector<std::vector<std::vector<MatchPair> > > all_pairs(N);
223  for (size_t i = 0; i < N; ++i) {
224  all_pairs[i].resize(N);
225  for (size_t j = 0; j < N; ++j) {
226  if (i == j) continue;
227  for (it1 = beg[i], it2 = beg[j]; it1 != end[i] && it2 != end[j]; ) {
228  if (it1->first < it2->first) ++it1;
229  else if(it1->first > it2->first) ++it2;
230  else {
231  MatchPair tmp;
232  tmp.from_i = i;
233  tmp.from_m = it1->second.matrix();
234  tmp.from_m.rows(3, -(*seq)[i].eye->camera().photo().focal());
235  tmp. to_i = j;
236  tmp. to_m = it2->second.matrix();
237  tmp. to_m.rows(3, -(*seq)[j].eye->camera().photo().focal());
238  all_pairs[i][j].push_back(tmp);
239  ++it1;
240  ++it2;
241  }
242  }
243  }
244  }
245  //
246  std::vector<MatchPair > pairs;
247  std::vector<Rotation3D <double> > rot;
248  std::vector<PhotoProjection<double> > pho;
249  std::vector<int > sum (N, 0);
250  std::vector<int > big (N, 0);
251  std::vector<int > real(N);
252  std::vector<int > rev (N);
253  // first!!
254  int best = -1, best_ct = -1;
255  for (size_t i = 0; i < N; ++i) {
256  int d = 0;
257  for (size_t j = 0; j < N; ++j) {
258  d += all_pairs[i][j].size();
259  }
260  if (best_ct < d) {
261  best_ct = d;
262  best = i;
263  }
264  real[i] = i;
265  big [i] = i;
266  }
267  for (size_t i = 0; i < N; ++i) {
268  // update else
269  real[i] = best;
270  rev[best] = i;
271  for (size_t j = 0; j < N; ++j) {
272  if ((int)j == best) {
273  sum[j] = -1;
274  continue;
275  }
276  if (sum[j] < 0) continue;
277  sum[j] += all_pairs[best][j].size();
278  if (all_pairs[j][big[j]].size() < all_pairs[j][best].size())
279  big[j] = best;
280  }
281  // add me
282  printf("%d same as %d\n", best, big[best]);
283  if (big[best] == best) {
284  rot.push_back((*seq)[big[best]].eye->camera() .rotation());
285  pho.push_back((*seq)[big[best]].eye->camera().photo().projection());
286  }
287  else {
288  rot.push_back(rot[rev[big[best]]]);
289  pho.push_back(pho[rev[big[best]]]);
290  }
291  for (size_t j = 0; j < N; ++j) {
292  if (sum[j] >= 0) continue;
293  for (size_t k = 0, K = all_pairs[best][j].size(); k < K; ++k) {
294  all_pairs[best][j][k].from_i = rev[all_pairs[best][j][k].from_i];
295  all_pairs[best][j][k]. to_i = rev[all_pairs[best][j][k]. to_i];
296  pairs.push_back(all_pairs[best][j][k]);
297  }
298  for (size_t k = 0, K = all_pairs[j][best].size(); k < K; ++k) {
299  all_pairs[j][best][k].from_i = rev[all_pairs[j][best][k].from_i];
300  all_pairs[j][best][k]. to_i = rev[all_pairs[j][best][k]. to_i];
301  pairs.push_back(all_pairs[j][best][k]);
302  }
303  }
304  for (size_t j = 0; j < N; ++j) { printf("%4d ", sum[j]); } printf("\n");
305  for (size_t j = 0; j < N; ++j) { printf("%4d ", big[j]); } printf("\n");
306  for (size_t j = 0; j < N; ++j) { printf("%4d ", real[j]); } printf("\n");
307  printf("\n");
308  // bundle adjustment
309  if (i > 0) {
310  NoOffsetController ct1(&pairs, &rot, &pho, false);
311  ct1.residure(levenbergMarquardtTraining(ct1, ct1.init(),
312  7.3, 1.0,
313  squ(threshold()) * pairs.size(),
314  7, 1000));
315  /*
316  NoOffsetController ct2(&pairs, &rot, &pho, true);
317  ct2.residure(levenbergMarquardtTraining(ct2, ct2.init(),
318  0.1 * pairs.size(), 1.0,
319  squ(threshold()) * pairs.size(),
320  7, 1000));
321  // */
322  }
323  // find next
324  best_ct = 0;
325  for (size_t j = 0; j < N; ++j) {
326  if (best_ct < sum[j]) {
327  best = j;
328  best_ct = sum[j];
329  }
330  }
331  getchar();
332  //if (i == N - 2) break;
333  }
334  // feedback
335  for (size_t i = 0; i < N; ++i) {
336  int id = real[i];
337  (*seq)[id].eye->cameraGet() .rotation (rot[i]);
338  (*seq)[id].eye->cameraGet().photoGet().projection(pho[i]);
339  //if (i == N - 2) break;
340  }
341  return true;
342  }
343 
344  bool adjustFixedPoint(std::vector<SceneInfo<Pixel> >* seq) const {
345  return false;
346  }
347 
348  bool write(FILE* f, bool bin, unsigned int fg) const {
349  return false;
350  }
351 
352  bool read(FILE* f, bool bin, unsigned int fg) const {
353  return false;
354  }
355 
356  ObjBase* create() const {
357  return new BundleAdjustment_LM;
358  }
359 
360  ObjBase* copyFrom(ObjBase const* o) {
361  return &(copyFrom(*(BundleAdjustment_LM const*)o));
362  }
363 
364  char const* ctype() const {
365  return typeid(*this).name();
366  }
367 
368  std::string type() const {
369  return std::string(ctype());
370  }
371 };
372 
373 } // meow
374 
375 #endif // BundleAdjustment_LM_H__
Matrix col(size_t c) const
Return the c -th column.
Definition: Matrix.h:260
Vector< Scalar > levenbergMarquardtTraining(Function &f, Vector< Scalar > const &init, Scalar const &init_mu, Scalar const &mu_pow, Scalar const &er_max, int retry_number, int counter)
Definition: methods.h:183
Scalar length2() const
same as (*this).dot(*this)
Definition: Vector.h:204
Scalar entry(size_t i) const
return i -th entry
Definition: Vector.h:125
char const * ctype() const
用C-style string回傳這個class的type name
std::string type() const
用std::string回傳這個class的type name
bool write(FILE *f, bool bin, unsigned int fg) const
將物件寫入檔案, 預設implement為直接回傳 false
BundleAdjustment_LM & referenceFrom(BundleAdjustment_LM const &b)
一切物件的Base, 並要求每個物件都要有read, write, create, ... 等功能
Definition: ObjBase.h:15
vector
Definition: Vector.h:19
ObjBase * copyFrom(ObjBase const *o)
複製, 預設使用operator=
bool adjustFixedPoint(std::vector< SceneInfo< Pixel > > *seq) const
BundleAdjustment_LM(BundleAdjustment_LM const &b)
bool read(FILE *f, bool bin, unsigned int fg) const
Matrix & identitied()
Let itself be an identity matrix.
Definition: Matrix.h:348
Entry entry(size_t r, size_t c) const
Access the entry at r x c.
Definition: Matrix.h:193
void reset(size_t r, size_t c, Entry const &e)
reset the size of the matrix to r x c with entry all be e
Definition: Matrix.h:107
bool adjustEye(std::vector< SceneInfo< Pixel > > *seq) const
IdentityPointsMap::const_iterator IdentityPointsMapIterK
BundleAdjustment_LM & copyFrom(BundleAdjustment_LM const &b)
ObjBase * create() const
回傳一個new出來的物件, 預設implement為直接回傳 NULL
T squ(T const &x)
x*x
Definition: utility.h:67