File: SparseBundleCPU.h

package info (click to toggle)
colmap 3.5-1
  • links: PTS
  • area: main
  • in suites: buster
  • size: 20,564 kB
  • sloc: ansic: 170,595; cpp: 95,339; python: 2,335; makefile: 183; sh: 51
file content (286 lines) | stat: -rwxr-xr-x 8,468 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
////////////////////////////////////////////////////////////////////////////
//  File:       SparseBundleCPU.h
//  Author:       Changchang Wu (ccwu@cs.washington.edu)
//  Description :   interface of the CPU-version of multi-core bundle adjustment
//
//  Copyright (c) 2011  Changchang Wu (ccwu@cs.washington.edu)
//    and the University of Washington at Seattle
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public
//  License as published by the Free Software Foundation; either
//  Version 3 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  General Public License for more details.
//
////////////////////////////////////////////////////////////////////////////////

#if !defined(SPARSE_BUNDLE_CPU_H)
#define SPARSE_BUNDLE_CPU_H

// BYTE-ALIGNMENT for data allocation (16 required for SSE, 32 required for AVX)
// PREVIOUS version uses only SSE. The new version will include AVX.
// SO the alignment is increased from 16 to 32
#define VECTOR_ALIGNMENT 32
#define FLOAT_ALIGN 8
#define VECTOR_ALIGNMENT_MASK (VECTOR_ALIGNMENT - 1)
#define ALIGN_PTR(p) \
  ((((size_t)p) + VECTOR_ALIGNMENT_MASK) & (~VECTOR_ALIGNMENT_MASK))

namespace pba {

template <class Float>
class avec {
  bool _owner;
  Float* _data;
  Float* _last;
  size_t _size;
  size_t _capacity;

 public:
  static Float* allocate(size_t count) {
    size_t size = count * sizeof(Float);
#ifdef _MSC_VER
    Float* p = (Float*)_aligned_malloc(size, VECTOR_ALIGNMENT);
    if (p == NULL) throw std::bad_alloc();
    return p;
#else
    char* p = (char*)malloc(size + VECTOR_ALIGNMENT + 4);
    if (p == NULL) throw std::bad_alloc();
    char* p1 = p + 1;
    char* p2 =
        (char*)ALIGN_PTR(p1);  //(char*) (((((size_t)p1) + 15) >> 4) << 4);
    char* p3 = (p2 - 1);
    p3[0] = (p2 - p);
    return (Float*)p2;
#endif
  }
  static void deallocate(void* p) {
#ifdef _MSC_VER
    _aligned_free(p);
#else
    char* p3 = ((char*)p) - 1;
    free(((char*)p) - p3[0]);
#endif
  }

 public:
  avec() {
    _owner = true;
    _last = _data = NULL;
    _size = _capacity = 0;
  }
  avec(size_t count) {
    _data = allocate(count);
    _size = _capacity = count;
    _last = _data + count;
    _owner = true;
  }
  ~avec() {
    if (_data && _owner) deallocate(_data);
  }

  inline void resize(size_t newcount) {
    if (!_owner) {
      _data = _last = NULL;
      _capacity = _size = 0;
      _owner = true;
    }
    if (newcount <= _capacity) {
      _size = newcount;
      _last = _data + newcount;
    } else {
      if (_data && _owner) deallocate(_data);
      _data = allocate(newcount);
      _size = _capacity = newcount;
      _last = _data + newcount;
    }
  }

  inline void set(Float* data, size_t count) {
    if (_data && _owner) deallocate(_data);
    _data = data;
    _owner = false;
    _size = count;
    _last = _data + _size;
    _capacity = count;
  }
  inline void swap(avec<Float>& next) {
    bool _owner_bak = _owner;
    Float* _data_bak = _data;
    Float* _last_bak = _last;
    size_t _size_bak = _size;
    size_t _capa_bak = _capacity;

    _owner = next._owner;
    _data = next._data;
    _last = next._last;
    _size = next._size;
    _capacity = next._capacity;

    next._owner = _owner_bak;
    next._data = _data_bak;
    next._last = _last_bak;
    next._size = _size_bak;
    next._capacity = _capa_bak;
  }

  inline operator Float*() { return _size ? _data : NULL; }
  inline operator Float* const() const { return _data; }
  inline Float* begin() { return _size ? _data : NULL; }
  inline Float* data() { return _size ? _data : NULL; }
  inline Float* end() { return _last; }
  inline const Float* begin() const { return _size ? _data : NULL; }
  inline const Float* end() const { return _last; }
  inline size_t size() const { return _size; }
  inline size_t IsValid() const { return _size; }
  void SaveToFile(const char* name);
};

template <class Float>
class SparseBundleCPU : public ParallelBA, public ConfigBA {
 public:
  SparseBundleCPU(const int num_threads);

  typedef avec<Float> VectorF;
  typedef std::vector<int> VectorI;
  typedef float float_t;

 protected:  // cpu data
  int _num_camera;
  int _num_point;
  int _num_imgpt;
  CameraT* _camera_data;
  float* _point_data;

  ////////////////////////////////
  const float* _imgpt_data;
  const int* _camera_idx;
  const int* _point_idx;
  const int* _focal_mask;

  ///////////sumed square error
  float _projection_sse;

 protected:  // cuda data
  VectorF _cuCameraData;
  VectorF _cuCameraDataEX;
  VectorF _cuPointData;
  VectorF _cuPointDataEX;
  VectorF _cuMeasurements;
  VectorF _cuImageProj;
  VectorF _cuJacobianCamera;
  VectorF _cuJacobianPoint;
  VectorF _cuJacobianCameraT;
  VectorI _cuProjectionMap;
  VectorI _cuPointMeasurementMap;
  VectorI _cuCameraMeasurementMap;
  VectorI _cuCameraMeasurementList;
  VectorI _cuCameraMeasurementListT;

  //////////////////////////
  VectorF _cuBlockPC;
  VectorF _cuVectorSJ;

  /// LM normal    equation
  VectorF _cuVectorJtE;
  VectorF _cuVectorJJ;
  VectorF _cuVectorJX;
  VectorF _cuVectorXK;
  VectorF _cuVectorPK;
  VectorF _cuVectorZK;
  VectorF _cuVectorRK;

  //////////////////////////////////
 protected:
  int _num_imgpt_q;
  float _weight_q;
  VectorI _cuCameraQList;
  VectorI _cuCameraQMap;
  VectorF _cuCameraQMapW;
  VectorF _cuCameraQListW;

 protected:
  bool ProcessIndexCameraQ(std::vector<int>& qmap, std::vector<int>& qlist);
  void ProcessWeightCameraQ(std::vector<int>& cpnum, std::vector<int>& qmap,
                            Float* qmapw, Float* qlistw);

 protected:  // internal functions
  int ValidateInputData();
  int InitializeBundle();
  int GetParameterLength();
  void BundleAdjustment();
  void NormalizeData();
  void TransferDataToHost();
  void DenormalizeData();
  void NormalizeDataF();
  void NormalizeDataD();
  bool InitializeStorageForSFM();
  bool InitializeStorageForCG();

  void SaveBundleRecord(int iter, float res, float damping, float& g_norm,
                        float& g_inf);

 protected:
  void PrepareJacobianNormalization();
  void EvaluateJacobians();
  void ComputeJtE(VectorF& E, VectorF& JtE, int mode = 0);
  void ComputeJX(VectorF& X, VectorF& JX, int mode = 0);
  void ComputeDiagonal(VectorF& JJI);
  void ComputeBlockPC(float lambda, bool dampd);
  void ApplyBlockPC(VectorF& v, VectorF& pv, int mode = 0);
  float UpdateCameraPoint(VectorF& dx, VectorF& cuImageTempProj);
  float EvaluateProjection(VectorF& cam, VectorF& point, VectorF& proj);
  float EvaluateProjectionX(VectorF& cam, VectorF& point, VectorF& proj);
  float SaveUpdatedSystem(float residual_reduction, float dx_sqnorm,
                          float damping);
  float EvaluateDeltaNorm();
  int SolveNormalEquationPCGB(float lambda);
  int SolveNormalEquationPCGX(float lambda);
  int SolveNormalEquation(float lambda);
  void NonlinearOptimizeLM();
  void AdjustBundleAdjsutmentMode();
  void RunProfileSteps();
  void RunTestIterationLM(bool reduced);
  void DumpCooJacobian();

 private:
  static int FindProcessorCoreNum();

 public:
  virtual void AbortBundleAdjustment() { __abort_flag = true; }
  virtual int GetCurrentIteration() { return __current_iteration; }
  virtual void SetNextTimeBudget(int seconds) {
    __bundle_time_budget = seconds;
  }
  virtual void SetNextBundleMode(BundleModeT mode) {
    __bundle_mode_next = mode;
  }
  virtual void SetFixedIntrinsics(bool fixed) { __fixed_intrinsics = fixed; }
  virtual void EnableRadialDistortion(DistortionT type) {
    __use_radial_distortion = type;
  }
  virtual void ParseParam(int narg, char** argv) {
    ConfigBA::ParseParam(narg, argv);
  }
  virtual ConfigBA* GetInternalConfig() { return this; }

 public:
  SparseBundleCPU();
  virtual void SetCameraData(size_t ncam, CameraT* cams);
  virtual void SetPointData(size_t npoint, Point3D* pts);
  virtual void SetProjection(size_t nproj, const Point2D* imgpts,
                             const int* point_idx, const int* cam_idx);
  virtual void SetFocalMask(const int* fmask, float weight);
  virtual float GetMeanSquaredError();
  virtual int RunBundleAdjustment();
};

ParallelBA* NewSparseBundleCPU(bool dp, const int num_threads);

}  // namespace pba

#endif