Blender  V2.93
libmv/simple_pipeline/camera_intrinsics.h
Go to the documentation of this file.
1 // Copyright (c) 2011 libmv authors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to
5 // deal in the Software without restriction, including without limitation the
6 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 // sell copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 // IN THE SOFTWARE.
20 
21 #ifndef LIBMV_SIMPLE_PIPELINE_CAMERA_INTRINSICS_H_
22 #define LIBMV_SIMPLE_PIPELINE_CAMERA_INTRINSICS_H_
23 
24 #include <iostream>
25 #include <string>
26 
27 #include <Eigen/Core>
28 
29 #include "libmv/numeric/numeric.h"
31 
32 namespace libmv {
33 
34 class CameraIntrinsics;
35 class PackedIntrinsics;
36 
37 namespace internal {
38 
39 // This class is responsible to store a lookup grid to perform
40 // image warping using this lookup grid. Such a magic is needed
41 // to make (un)distortion as fast as possible in cases multiple
42 // images are to be processed.
44  public:
48 
49  // Width and height og the image, measured in pixels.
50  int width() const { return width_; }
51  int height() const { return height_; }
52 
53  // Overscan factor of the image, so that
54  // - 0.0 is overscan of 0 pixels,
55  // - 1.0 is overscan of image weight pixels in horizontal direction
56  // and image height pixels in vertical direction.
57  double overscan() const { return overscan_; }
58 
59  // Update lookup grid in order to be sure it's calculated for
60  // given image width, height and overscan.
61  //
62  // See comment for CameraIntrinsics::DistortBuffer to get more
63  // details about what overscan is.
64  template <typename WarpFunction>
65  void Update(const CameraIntrinsics& intrinsics,
66  int width,
67  int height,
68  double overscan);
69 
70  // Apply coordinate lookup grid on a giver input buffer.
71  //
72  // See comment for CameraIntrinsics::DistortBuffer to get more
73  // details about template type.
74  template <typename PixelType>
75  void Apply(const PixelType* input_buffer,
76  int width,
77  int height,
78  int channels,
79  PixelType* output_buffer);
80 
81  // Reset lookup grids.
82  // This will tag the grid for update without re-computing it.
83  void Reset();
84 
85  // Set number of threads used for threaded buffer distortion/undistortion.
86  void SetThreads(int threads);
87 
88  private:
89  // This structure contains an offset in both x,y directions
90  // in an optimized way sawing some bytes per pixel in the memory.
91  //
92  // TODO(sergey): This is rather questionable optimizations, memory
93  // is cheap nowadays and storing offset in such a way implies much
94  // more operations comparing to using bare floats.
95  struct Offset {
96  // Integer part of the offset.
97  short ix, iy;
98 
99  // Float part of an offset, to get a real float value divide this
100  // value by 255.
101  unsigned char fx, fy;
102  };
103 
104  // Compute coordinate lookup grid using a giver warp functor.
105  //
106  // width and height corresponds to a size of buffer which will
107  // be warped later.
108  template <typename WarpFunction>
109  void Compute(const CameraIntrinsics& intrinsics,
110  int width,
111  int height,
112  double overscan);
113 
114  // This is a buffer which contains per-pixel offset of the
115  // pixels from input buffer to correspond the warping function.
116  Offset* offset_;
117 
118  // Dimensions of the image this lookup grid processes.
119  int width_, height_;
120 
121  // Overscan of the image being processed by this grid.
122  double overscan_;
123 
124  // Number of threads which will be used for buffer istortion/undistortion.
125  int threads_;
126 };
127 
128 } // namespace internal
129 
131  public:
134  virtual ~CameraIntrinsics() {}
135 
137 
138  int image_width() const { return image_width_; }
139  int image_height() const { return image_height_; }
140 
141  const Mat3& K() const { return K_; }
142 
143  double focal_length() const { return K_(0, 0); }
144  double focal_length_x() const { return K_(0, 0); }
145  double focal_length_y() const { return K_(1, 1); }
146 
147  double principal_point_x() const { return K_(0, 2); }
148  double principal_point_y() const { return K_(1, 2); }
149 
150  // Set the image size in pixels.
151  // Image is the size of image camera intrinsics were calibrated with.
152  void SetImageSize(int width, int height);
153 
154  // Set the entire calibration matrix at once.
155  void SetK(const Mat3 new_k);
156 
157  // Set both x and y focal length in pixels.
158  void SetFocalLength(double focal_x, double focal_y);
159 
160  // Set principal point in pixels.
161  void SetPrincipalPoint(double cx, double cy);
162 
163  // Set number of threads used for threaded buffer distortion/undistortion.
164  void SetThreads(int threads);
165 
166  // Convert image space coordinates to normalized.
167  void ImageSpaceToNormalized(double image_x,
168  double image_y,
169  double* normalized_x,
170  double* normalized_y) const;
171 
172  // Convert normalized coordinates to image space.
173  void NormalizedToImageSpace(double normalized_x,
174  double normalized_y,
175  double* image_x,
176  double* image_y) const;
177 
178  // Apply camera intrinsics to the normalized point to get image coordinates.
179  //
180  // This applies the lens distortion to a point which is in normalized
181  // camera coordinates (i.e. the principal point is at (0, 0)) to get image
182  // coordinates in pixels.
183  virtual void ApplyIntrinsics(double normalized_x,
184  double normalized_y,
185  double* image_x,
186  double* image_y) const = 0;
187 
188  // Invert camera intrinsics on the image point to get normalized coordinates.
189  //
190  // This reverses the effect of lens distortion on a point which is in image
191  // coordinates to get normalized camera coordinates.
192  virtual void InvertIntrinsics(double image_x,
193  double image_y,
194  double* normalized_x,
195  double* normalized_y) const = 0;
196 
197  virtual void Pack(PackedIntrinsics* packed_intrinsics) const;
198  virtual void Unpack(const PackedIntrinsics& packed_intrinsics);
199 
200  // Distort an image using the current camera instrinsics
201  //
202  // The distorted image is computed in output_buffer using samples from
203  // input_buffer. Both buffers should be width x height x channels sized.
204  //
205  // Overscan is a percentage value of how much overcan the image have.
206  // For example overscal value of 0.2 means 20% of overscan in the
207  // buffers.
208  //
209  // Overscan is usually used in cases when one need to distort an image
210  // and don't have a barrel in the distorted buffer. For example, when
211  // one need to render properly distorted FullHD frame without barrel
212  // visible. For such cases renderers usually renders bigger images and
213  // crops them after the distortion.
214  //
215  // This method is templated to be able to distort byte and float buffers
216  // without having separate methods for this two types. So basically only
217  //
218  // But in fact PixelType might be any type for which multiplication by
219  // a scalar and addition are implemented. For example PixelType might be
220  // Vec3 as well.
221  template <typename PixelType>
222  void DistortBuffer(const PixelType* input_buffer,
223  int width,
224  int height,
225  double overscan,
226  int channels,
227  PixelType* output_buffer);
228 
229  // Undistort an image using the current camera instrinsics
230  //
231  // The undistorted image is computed in output_buffer using samples from
232  // input_buffer. Both buffers should be width x height x channels sized.
233  //
234  // Overscan is a percentage value of how much overcan the image have.
235  // For example overscal value of 0.2 means 20% of overscan in the
236  // buffers.
237  //
238  // Overscan is usually used in cases when one need to distort an image
239  // and don't have a barrel in the distorted buffer. For example, when
240  // one need to render properly distorted FullHD frame without barrel
241  // visible. For such cases renderers usually renders bigger images and
242  // crops them after the distortion.
243  //
244  // This method is templated to be able to distort byte and float buffers
245  // without having separate methods for this two types. So basically only
246  //
247  // But in fact PixelType might be any type for which multiplication by
248  // a scalar and addition are implemented. For example PixelType might be
249  // Vec3 as well.
250  template <typename PixelType>
251  void UndistortBuffer(const PixelType* input_buffer,
252  int width,
253  int height,
254  double overscan,
255  int channels,
256  PixelType* output_buffer);
257 
258  private:
259  // This is the size of the image. This is necessary to, for example, handle
260  // the case of processing a scaled image.
261  int image_width_;
262  int image_height_;
263 
264  // The traditional intrinsics matrix from x = K[R|t]X.
265  Mat3 K_;
266 
267  // Coordinate lookup grids for distortion and undistortion.
268  internal::LookupWarpGrid distort_;
269  internal::LookupWarpGrid undistort_;
270 
271  protected:
272  // Reset lookup grids after changing the distortion model.
273  void ResetLookupGrids();
274 };
275 
277  public:
278  // This constants defines an offset of corresponding coefficients
279  // in the parameters_ array.
280  enum {
286 
287  // This defines the size of array which we need to have in order
288  // to store all the coefficients.
290  };
291 
294 
297  }
298 
299  double k1() const { return parameters_[OFFSET_K1]; }
300  double k2() const { return parameters_[OFFSET_K2]; }
301  double k3() const { return parameters_[OFFSET_K3]; }
302  double p1() const { return parameters_[OFFSET_P1]; }
303  double p2() const { return parameters_[OFFSET_P2]; }
304 
305  // Set radial distortion coeffcients.
306  void SetRadialDistortion(double k1, double k2, double k3);
307 
308  // Set tangential distortion coeffcients.
309  void SetTangentialDistortion(double p1, double p2);
310 
311  // Apply camera intrinsics to the normalized point to get image coordinates.
312  //
313  // This applies the lens distortion to a point which is in normalized
314  // camera coordinates (i.e. the principal point is at (0, 0)) to get image
315  // coordinates in pixels.
316  void ApplyIntrinsics(double normalized_x,
317  double normalized_y,
318  double* image_x,
319  double* image_y) const override;
320 
321  // Invert camera intrinsics on the image point to get normalized coordinates.
322  //
323  // This reverses the effect of lens distortion on a point which is in image
324  // coordinates to get normalized camera coordinates.
325  void InvertIntrinsics(double image_x,
326  double image_y,
327  double* normalized_x,
328  double* normalized_y) const override;
329 
330  virtual void Pack(PackedIntrinsics* packed_intrinsics) const override;
331  virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override;
332 
333  private:
334  // OpenCV's distortion model with third order polynomial radial distortion
335  // terms and second order tangential distortion. The distortion is applied to
336  // the normalized coordinates before the focal length, which makes them
337  // independent of image size.
338  double parameters_[NUM_PARAMETERS];
339 };
340 
342  public:
343  // This constants defines an offset of corresponding coefficients
344  // in the parameters_ array.
345  enum {
348 
349  // This defines the size of array which we need to have in order
350  // to store all the coefficients.
352  };
353 
356 
359  }
360 
361  double k1() const { return parameters_[OFFSET_K1]; }
362  double k2() const { return parameters_[OFFSET_K2]; }
363 
364  // Set radial distortion coeffcients.
365  void SetDistortion(double k1, double k2);
366 
367  // Apply camera intrinsics to the normalized point to get image coordinates.
368  //
369  // This applies the lens distortion to a point which is in normalized
370  // camera coordinates (i.e. the principal point is at (0, 0)) to get image
371  // coordinates in pixels.
372  void ApplyIntrinsics(double normalized_x,
373  double normalized_y,
374  double* image_x,
375  double* image_y) const override;
376 
377  // Invert camera intrinsics on the image point to get normalized coordinates.
378  //
379  // This reverses the effect of lens distortion on a point which is in image
380  // coordinates to get normalized camera coordinates.
381  void InvertIntrinsics(double image_x,
382  double image_y,
383  double* normalized_x,
384  double* normalized_y) const override;
385 
386  virtual void Pack(PackedIntrinsics* packed_intrinsics) const override;
387  virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override;
388 
389  private:
390  // Double-parameter division distortion model.
391  double parameters_[NUM_PARAMETERS];
392 };
393 
395  public:
396  // This constants defines an offset of corresponding coefficients
397  // in the parameters_ array.
398  enum {
401 
402  // This defines the size of array which we need to have in order
403  // to store all the coefficients.
405  };
406 
409 
411  return DISTORTION_MODEL_NUKE;
412  }
413 
414  double k1() const { return parameters_[OFFSET_K1]; }
415  double k2() const { return parameters_[OFFSET_K2]; }
416 
417  // Set radial distortion coeffcients.
418  void SetDistortion(double k1, double k2);
419 
420  // Apply camera intrinsics to the normalized point to get image coordinates.
421  //
422  // This applies the lens distortion to a point which is in normalized
423  // camera coordinates (i.e. the principal point is at (0, 0)) to get image
424  // coordinates in pixels.
425  void ApplyIntrinsics(double normalized_x,
426  double normalized_y,
427  double* image_x,
428  double* image_y) const override;
429 
430  // Invert camera intrinsics on the image point to get normalized coordinates.
431  //
432  // This reverses the effect of lens distortion on a point which is in image
433  // coordinates to get normalized camera coordinates.
434  void InvertIntrinsics(double image_x,
435  double image_y,
436  double* normalized_x,
437  double* normalized_y) const override;
438 
439  virtual void Pack(PackedIntrinsics* packed_intrinsics) const override;
440  virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override;
441 
442  private:
443  // Double-parameter division distortion model.
444  double parameters_[NUM_PARAMETERS];
445 };
446 
448  public:
449  // This constants defines an offset of corresponding coefficients
450  // in the parameters_ array.
451  enum {
458 
459  // This defines the size of array which we need to have in order
460  // to store all the coefficients.
462  };
463 
466 
468  return DISTORTION_MODEL_BROWN;
469  }
470 
471  double k1() const { return parameters_[OFFSET_K1]; }
472  double k2() const { return parameters_[OFFSET_K2]; }
473  double k3() const { return parameters_[OFFSET_K3]; }
474  double k4() const { return parameters_[OFFSET_K4]; }
475  double p1() const { return parameters_[OFFSET_P1]; }
476  double p2() const { return parameters_[OFFSET_P2]; }
477 
478  // Set radial distortion coeffcients.
479  void SetRadialDistortion(double k1, double k2, double k3, double k4);
480 
481  // Set tangential distortion coeffcients.
482  void SetTangentialDistortion(double p1, double p2);
483 
484  // Apply camera intrinsics to the normalized point to get image coordinates.
485  //
486  // This applies the lens distortion to a point which is in normalized
487  // camera coordinates (i.e. the principal point is at (0, 0)) to get image
488  // coordinates in pixels.
489  void ApplyIntrinsics(double normalized_x,
490  double normalized_y,
491  double* image_x,
492  double* image_y) const override;
493 
494  // Invert camera intrinsics on the image point to get normalized coordinates.
495  //
496  // This reverses the effect of lens distortion on a point which is in image
497  // coordinates to get normalized camera coordinates.
498  void InvertIntrinsics(double image_x,
499  double image_y,
500  double* normalized_x,
501  double* normalized_y) const override;
502 
503  virtual void Pack(PackedIntrinsics* packed_intrinsics) const override;
504  virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override;
505 
506  private:
507  double parameters_[NUM_PARAMETERS];
508 };
509 
511 std::ostream& operator<<(std::ostream& os, const CameraIntrinsics& intrinsics);
512 
513 } // namespace libmv
514 
515 // Include implementation of all templated methods here,
516 // so they're visible to the compiler.
518 
519 #endif // LIBMV_SIMPLE_PIPELINE_CAMERA_INTRINSICS_H_
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
DistortionModelType GetDistortionModelType() const override
void ApplyIntrinsics(double normalized_x, double normalized_y, double *image_x, double *image_y) const override
virtual void Unpack(const PackedIntrinsics &packed_intrinsics) override
virtual void Pack(PackedIntrinsics *packed_intrinsics) const override
void SetRadialDistortion(double k1, double k2, double k3, double k4)
void InvertIntrinsics(double image_x, double image_y, double *normalized_x, double *normalized_y) const override
virtual void ApplyIntrinsics(double normalized_x, double normalized_y, double *image_x, double *image_y) const =0
void DistortBuffer(const PixelType *input_buffer, int width, int height, double overscan, int channels, PixelType *output_buffer)
void SetFocalLength(double focal_x, double focal_y)
void NormalizedToImageSpace(double normalized_x, double normalized_y, double *image_x, double *image_y) const
virtual void InvertIntrinsics(double image_x, double image_y, double *normalized_x, double *normalized_y) const =0
virtual void Unpack(const PackedIntrinsics &packed_intrinsics)
virtual void Pack(PackedIntrinsics *packed_intrinsics) const
void UndistortBuffer(const PixelType *input_buffer, int width, int height, double overscan, int channels, PixelType *output_buffer)
virtual DistortionModelType GetDistortionModelType() const =0
void ImageSpaceToNormalized(double image_x, double image_y, double *normalized_x, double *normalized_y) const
virtual void Unpack(const PackedIntrinsics &packed_intrinsics) override
virtual void Pack(PackedIntrinsics *packed_intrinsics) const override
void InvertIntrinsics(double image_x, double image_y, double *normalized_x, double *normalized_y) const override
DistortionModelType GetDistortionModelType() const override
void ApplyIntrinsics(double normalized_x, double normalized_y, double *image_x, double *image_y) const override
virtual void Pack(PackedIntrinsics *packed_intrinsics) const override
DistortionModelType GetDistortionModelType() const override
void InvertIntrinsics(double image_x, double image_y, double *normalized_x, double *normalized_y) const override
virtual void Unpack(const PackedIntrinsics &packed_intrinsics) override
void ApplyIntrinsics(double normalized_x, double normalized_y, double *image_x, double *image_y) const override
virtual void Pack(PackedIntrinsics *packed_intrinsics) const override
void InvertIntrinsics(double image_x, double image_y, double *normalized_x, double *normalized_y) const override
virtual void Unpack(const PackedIntrinsics &packed_intrinsics) override
void SetRadialDistortion(double k1, double k2, double k3)
void ApplyIntrinsics(double normalized_x, double normalized_y, double *image_x, double *image_y) const override
DistortionModelType GetDistortionModelType() const override
void Apply(const PixelType *input_buffer, int width, int height, int channels, PixelType *output_buffer)
void Update(const CameraIntrinsics &intrinsics, int width, int height, double overscan)
StackEntry * from
ListBase threads
list of all thread for every CPUDevice in cpudevices a thread exists.
std::ostream & operator<<(std::ostream &os, const CameraIntrinsics &intrinsics)
A human-readable representation of the camera intrinsic parameters.
Eigen::Matrix< double, 3, 3 > Mat3
Definition: numeric.h:72
@ DISTORTION_MODEL_POLYNOMIAL
@ DISTORTION_MODEL_DIVISION
@ DISTORTION_MODEL_BROWN
@ DISTORTION_MODEL_NUKE
Definition: msgfmt.c:181