Blender V5.0
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
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 private:
86 // This structure contains an offset in both x,y directions
87 // in an optimized way sawing some bytes per pixel in the memory.
88 //
89 // TODO(sergey): This is rather questionable optimizations, memory
90 // is cheap nowadays and storing offset in such a way implies much
91 // more operations comparing to using bare floats.
92 struct Offset {
93 // Integer part of the offset.
94 short ix, iy;
95
96 // Float part of an offset, to get a real float value divide this
97 // value by 255.
98 unsigned char fx, fy;
99 };
100
101 // Compute coordinate lookup grid using a giver warp functor.
102 //
103 // width and height corresponds to a size of buffer which will
104 // be warped later.
105 template <typename WarpFunction>
106 void Compute(const CameraIntrinsics& intrinsics,
107 int width,
108 int height,
109 double overscan);
110
111 // This is a buffer which contains per-pixel offset of the
112 // pixels from input buffer to correspond the warping function.
113 Offset* offset_;
114
115 // Dimensions of the image this lookup grid processes.
116 int width_, height_;
117
118 // Overscan of the image being processed by this grid.
119 double overscan_;
120};
121
122} // namespace internal
123
125 public:
128 virtual ~CameraIntrinsics() {}
129
131
132 int image_width() const { return image_width_; }
133 int image_height() const { return image_height_; }
134
135 const Mat3& K() const { return K_; }
136
137 double focal_length() const { return K_(0, 0); }
138 double focal_length_x() const { return K_(0, 0); }
139 double focal_length_y() const { return K_(1, 1); }
140
141 double principal_point_x() const { return K_(0, 2); }
142 double principal_point_y() const { return K_(1, 2); }
143
144 // Set the image size in pixels.
145 // Image is the size of image camera intrinsics were calibrated with.
146 void SetImageSize(int width, int height);
147
148 // Set the entire calibration matrix at once.
149 void SetK(const Mat3 new_k);
150
151 // Set both x and y focal length in pixels.
152 void SetFocalLength(double focal_x, double focal_y);
153
154 // Set principal point in pixels.
155 void SetPrincipalPoint(double cx, double cy);
156
157 // Convert image space coordinates to normalized.
158 void ImageSpaceToNormalized(double image_x,
159 double image_y,
160 double* normalized_x,
161 double* normalized_y) const;
162
163 // Convert normalized coordinates to image space.
164 void NormalizedToImageSpace(double normalized_x,
165 double normalized_y,
166 double* image_x,
167 double* image_y) const;
168
169 // Apply camera intrinsics to the normalized point to get image coordinates.
170 //
171 // This applies the lens distortion to a point which is in normalized
172 // camera coordinates (i.e. the principal point is at (0, 0)) to get image
173 // coordinates in pixels.
174 virtual void ApplyIntrinsics(double normalized_x,
175 double normalized_y,
176 double* image_x,
177 double* image_y) const = 0;
178
179 // Invert camera intrinsics on the image point to get normalized coordinates.
180 //
181 // This reverses the effect of lens distortion on a point which is in image
182 // coordinates to get normalized camera coordinates.
183 virtual void InvertIntrinsics(double image_x,
184 double image_y,
185 double* normalized_x,
186 double* normalized_y) const = 0;
187
188 virtual void Pack(PackedIntrinsics* packed_intrinsics) const;
189 virtual void Unpack(const PackedIntrinsics& packed_intrinsics);
190
191 // Distort an image using the current camera instrinsics
192 //
193 // The distorted image is computed in output_buffer using samples from
194 // input_buffer. Both buffers should be width x height x channels sized.
195 //
196 // Overscan is a percentage value of how much overcan the image have.
197 // For example overscal value of 0.2 means 20% of overscan in the
198 // buffers.
199 //
200 // Overscan is usually used in cases when one need to distort an image
201 // and don't have a barrel in the distorted buffer. For example, when
202 // one need to render properly distorted FullHD frame without barrel
203 // visible. For such cases renderers usually renders bigger images and
204 // crops them after the distortion.
205 //
206 // This method is templated to be able to distort byte and float buffers
207 // without having separate methods for this two types. So basically only
208 //
209 // But in fact PixelType might be any type for which multiplication by
210 // a scalar and addition are implemented. For example PixelType might be
211 // Vec3 as well.
212 template <typename PixelType>
213 void DistortBuffer(const PixelType* input_buffer,
214 int width,
215 int height,
216 double overscan,
217 int channels,
218 PixelType* output_buffer);
219
220 // Undistort an image using the current camera instrinsics
221 //
222 // The undistorted image is computed in output_buffer using samples from
223 // input_buffer. Both buffers should be width x height x channels sized.
224 //
225 // Overscan is a percentage value of how much overcan the image have.
226 // For example overscal value of 0.2 means 20% of overscan in the
227 // buffers.
228 //
229 // Overscan is usually used in cases when one need to distort an image
230 // and don't have a barrel in the distorted buffer. For example, when
231 // one need to render properly distorted FullHD frame without barrel
232 // visible. For such cases renderers usually renders bigger images and
233 // crops them after the distortion.
234 //
235 // This method is templated to be able to distort byte and float buffers
236 // without having separate methods for this two types. So basically only
237 //
238 // But in fact PixelType might be any type for which multiplication by
239 // a scalar and addition are implemented. For example PixelType might be
240 // Vec3 as well.
241 template <typename PixelType>
242 void UndistortBuffer(const PixelType* input_buffer,
243 int width,
244 int height,
245 double overscan,
246 int channels,
247 PixelType* output_buffer);
248
249 private:
250 // This is the size of the image. This is necessary to, for example, handle
251 // the case of processing a scaled image.
252 int image_width_;
253 int image_height_;
254
255 // The traditional intrinsics matrix from x = K[R|t]X.
256 Mat3 K_;
257
258 // Coordinate lookup grids for distortion and undistortion.
260 internal::LookupWarpGrid undistort_;
261
262 protected:
263 // Reset lookup grids after changing the distortion model.
264 void ResetLookupGrids();
265};
266
268 public:
269 // This constants defines an offset of corresponding coefficients
270 // in the parameters_ array.
271 enum {
277
278 // This defines the size of array which we need to have in order
279 // to store all the coefficients.
281 };
282
285
289
290 double k1() const { return parameters_[OFFSET_K1]; }
291 double k2() const { return parameters_[OFFSET_K2]; }
292 double k3() const { return parameters_[OFFSET_K3]; }
293 double p1() const { return parameters_[OFFSET_P1]; }
294 double p2() const { return parameters_[OFFSET_P2]; }
295
296 // Set radial distortion coeffcients.
297 void SetRadialDistortion(double k1, double k2, double k3);
298
299 // Set tangential distortion coeffcients.
300 void SetTangentialDistortion(double p1, double p2);
301
302 // Apply camera intrinsics to the normalized point to get image coordinates.
303 //
304 // This applies the lens distortion to a point which is in normalized
305 // camera coordinates (i.e. the principal point is at (0, 0)) to get image
306 // coordinates in pixels.
307 void ApplyIntrinsics(double normalized_x,
308 double normalized_y,
309 double* image_x,
310 double* image_y) const override;
311
312 // Invert camera intrinsics on the image point to get normalized coordinates.
313 //
314 // This reverses the effect of lens distortion on a point which is in image
315 // coordinates to get normalized camera coordinates.
316 void InvertIntrinsics(double image_x,
317 double image_y,
318 double* normalized_x,
319 double* normalized_y) const override;
320
321 virtual void Pack(PackedIntrinsics* packed_intrinsics) const override;
322 virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override;
323
324 private:
325 // OpenCV's distortion model with third order polynomial radial distortion
326 // terms and second order tangential distortion. The distortion is applied to
327 // the normalized coordinates before the focal length, which makes them
328 // independent of image size.
329 double parameters_[NUM_PARAMETERS];
330};
331
333 public:
334 // This constants defines an offset of corresponding coefficients
335 // in the parameters_ array.
336 enum {
339
340 // This defines the size of array which we need to have in order
341 // to store all the coefficients.
343 };
344
347
351
352 double k1() const { return parameters_[OFFSET_K1]; }
353 double k2() const { return parameters_[OFFSET_K2]; }
354
355 // Set radial distortion coeffcients.
356 void SetDistortion(double k1, double k2);
357
358 // Apply camera intrinsics to the normalized point to get image coordinates.
359 //
360 // This applies the lens distortion to a point which is in normalized
361 // camera coordinates (i.e. the principal point is at (0, 0)) to get image
362 // coordinates in pixels.
363 void ApplyIntrinsics(double normalized_x,
364 double normalized_y,
365 double* image_x,
366 double* image_y) const override;
367
368 // Invert camera intrinsics on the image point to get normalized coordinates.
369 //
370 // This reverses the effect of lens distortion on a point which is in image
371 // coordinates to get normalized camera coordinates.
372 void InvertIntrinsics(double image_x,
373 double image_y,
374 double* normalized_x,
375 double* normalized_y) const override;
376
377 virtual void Pack(PackedIntrinsics* packed_intrinsics) const override;
378 virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override;
379
380 private:
381 // Double-parameter division distortion model.
382 double parameters_[NUM_PARAMETERS];
383};
384
386 public:
387 // This constants defines an offset of corresponding coefficients
388 // in the parameters_ array.
389 enum {
392
393 // This defines the size of array which we need to have in order
394 // to store all the coefficients.
396 };
397
400
404
405 double k1() const { return parameters_[OFFSET_K1]; }
406 double k2() const { return parameters_[OFFSET_K2]; }
407
408 // Set radial distortion coeffcients.
409 void SetDistortion(double k1, double k2);
410
411 // Apply camera intrinsics to the normalized point to get image coordinates.
412 //
413 // This applies the lens distortion to a point which is in normalized
414 // camera coordinates (i.e. the principal point is at (0, 0)) to get image
415 // coordinates in pixels.
416 void ApplyIntrinsics(double normalized_x,
417 double normalized_y,
418 double* image_x,
419 double* image_y) const override;
420
421 // Invert camera intrinsics on the image point to get normalized coordinates.
422 //
423 // This reverses the effect of lens distortion on a point which is in image
424 // coordinates to get normalized camera coordinates.
425 void InvertIntrinsics(double image_x,
426 double image_y,
427 double* normalized_x,
428 double* normalized_y) const override;
429
430 virtual void Pack(PackedIntrinsics* packed_intrinsics) const override;
431 virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override;
432
433 private:
434 // Double-parameter division distortion model.
435 double parameters_[NUM_PARAMETERS];
436};
437
439 public:
440 // This constants defines an offset of corresponding coefficients
441 // in the parameters_ array.
442 enum {
449
450 // This defines the size of array which we need to have in order
451 // to store all the coefficients.
453 };
454
457
461
462 double k1() const { return parameters_[OFFSET_K1]; }
463 double k2() const { return parameters_[OFFSET_K2]; }
464 double k3() const { return parameters_[OFFSET_K3]; }
465 double k4() const { return parameters_[OFFSET_K4]; }
466 double p1() const { return parameters_[OFFSET_P1]; }
467 double p2() const { return parameters_[OFFSET_P2]; }
468
469 // Set radial distortion coeffcients.
470 void SetRadialDistortion(double k1, double k2, double k3, double k4);
471
472 // Set tangential distortion coeffcients.
473 void SetTangentialDistortion(double p1, double p2);
474
475 // Apply camera intrinsics to the normalized point to get image coordinates.
476 //
477 // This applies the lens distortion to a point which is in normalized
478 // camera coordinates (i.e. the principal point is at (0, 0)) to get image
479 // coordinates in pixels.
480 void ApplyIntrinsics(double normalized_x,
481 double normalized_y,
482 double* image_x,
483 double* image_y) const override;
484
485 // Invert camera intrinsics on the image point to get normalized coordinates.
486 //
487 // This reverses the effect of lens distortion on a point which is in image
488 // coordinates to get normalized camera coordinates.
489 void InvertIntrinsics(double image_x,
490 double image_y,
491 double* normalized_x,
492 double* normalized_y) const override;
493
494 virtual void Pack(PackedIntrinsics* packed_intrinsics) const override;
495 virtual void Unpack(const PackedIntrinsics& packed_intrinsics) override;
496
497 private:
498 double parameters_[NUM_PARAMETERS];
499};
500
502std::ostream& operator<<(std::ostream& os, const CameraIntrinsics& intrinsics);
503
504} // namespace libmv
505
506// Include implementation of all templated methods here,
507// so they're visible to the compiler.
509
510#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:75
@ DISTORTION_MODEL_POLYNOMIAL
@ DISTORTION_MODEL_DIVISION
@ DISTORTION_MODEL_BROWN
@ DISTORTION_MODEL_NUKE