Blender V4.3
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
31
32namespace libmv {
33
34class CameraIntrinsics;
35class PackedIntrinsics;
36
37namespace 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:
46 LookupWarpGrid(const LookupWarpGrid& from);
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.
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
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
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
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
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
511std::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_
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)
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