Blender V4.3
distortion_models.h
Go to the documentation of this file.
1// Copyright (c) 2014 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_DISTORTION_MODELS_H_
22#define LIBMV_SIMPLE_PIPELINE_DISTORTION_MODELS_H_
23
24#include <algorithm>
25
26namespace libmv {
27
34
35// Invert camera intrinsics on the image point to get normalized coordinates.
36// This inverts the radial lens distortion to a point which is in image pixel
37// coordinates to get normalized coordinates.
38void InvertPolynomialDistortionModel(const double focal_length_x,
39 const double focal_length_y,
40 const double principal_point_x,
41 const double principal_point_y,
42 const double k1,
43 const double k2,
44 const double k3,
45 const double p1,
46 const double p2,
47 const double image_x,
48 const double image_y,
49 double* normalized_x,
50 double* normalized_y);
51
52// Apply camera intrinsics to the normalized point to get image coordinates.
53// This applies the radial lens distortion to a point which is in normalized
54// camera coordinates (i.e. the principal point is at (0, 0)) to get image
55// coordinates in pixels. Templated for use with autodifferentiation.
56template <typename T>
57inline void ApplyPolynomialDistortionModel(const T& focal_length_x,
58 const T& focal_length_y,
59 const T& principal_point_x,
60 const T& principal_point_y,
61 const T& k1,
62 const T& k2,
63 const T& k3,
64 const T& p1,
65 const T& p2,
66 const T& normalized_x,
67 const T& normalized_y,
68 T* image_x,
69 T* image_y) {
70 T x = normalized_x;
71 T y = normalized_y;
72
73 // Apply distortion to the normalized points to get (xd, yd).
74 T r2 = x * x + y * y;
75 T r4 = r2 * r2;
76 T r6 = r4 * r2;
77 T r_coeff = (T(1) + k1 * r2 + k2 * r4 + k3 * r6);
78 T xd = x * r_coeff + T(2) * p1 * x * y + p2 * (r2 + T(2) * x * x);
79 T yd = y * r_coeff + T(2) * p2 * x * y + p1 * (r2 + T(2) * y * y);
80
81 // Apply focal length and principal point to get the final image coordinates.
82 *image_x = focal_length_x * xd + principal_point_x;
83 *image_y = focal_length_y * yd + principal_point_y;
84}
85
86// Invert camera intrinsics on the image point to get normalized coordinates.
87// This inverts the radial lens distortion to a point which is in image pixel
88// coordinates to get normalized coordinates.
89//
90// Uses division distortion model.
91void InvertDivisionDistortionModel(const double focal_length_x,
92 const double focal_length_y,
93 const double principal_point_x,
94 const double principal_point_y,
95 const double k1,
96 const double k2,
97 const double image_x,
98 const double image_y,
99 double* normalized_x,
100 double* normalized_y);
101
102// Apply camera intrinsics to the normalized point to get image coordinates.
103// This applies the radial lens distortion to a point which is in normalized
104// camera coordinates (i.e. the principal point is at (0, 0)) to get image
105// coordinates in pixels. Templated for use with autodifferentiation.
106//
107// Uses division distortion model.
108template <typename T>
109inline void ApplyDivisionDistortionModel(const T& focal_length_x,
110 const T& focal_length_y,
111 const T& principal_point_x,
112 const T& principal_point_y,
113 const T& k1,
114 const T& k2,
115 const T& normalized_x,
116 const T& normalized_y,
117 T* image_x,
118 T* image_y) {
119 T x = normalized_x;
120 T y = normalized_y;
121 T r2 = x * x + y * y;
122 T r4 = r2 * r2;
123
124 T xd = x / (T(1) + k1 * r2 + k2 * r4);
125 T yd = y / (T(1) + k1 * r2 + k2 * r4);
126
127 // Apply focal length and principal point to get the final image coordinates.
128 *image_x = focal_length_x * xd + principal_point_x;
129 *image_y = focal_length_y * yd + principal_point_y;
130}
131
132// Invert camera intrinsics on the image point to get normalized coordinates.
133// This inverts the radial lens distortion to a point which is in image pixel
134// coordinates to get normalized coordinates.
135//
136// Uses Nuke distortion model.
137template <typename T>
138void InvertNukeDistortionModel(const T& focal_length_x,
139 const T& focal_length_y,
140 const T& principal_point_x,
141 const T& principal_point_y,
142 const int image_width,
143 const int image_height,
144 const T& k1,
145 const T& k2,
146 const T& image_x,
147 const T& image_y,
148 T* normalized_x,
149 T* normalized_y) {
150 // According to the documentation:
151 //
152 // xu = xd / (1 + k0 * rd^2 + k1 * rd^4)
153 // yu = yd / (1 + k0 * rd^2 + k1 * rd^4)
154 //
155 // Legend:
156 // (xd, yd) are the distorted cartesian coordinates,
157 // (rd, phid) are the distorted polar coordinates,
158 // (xu, yu) are the undistorted cartesian coordinates,
159 // (ru, phiu) are the undistorted polar coordinates,
160 // the k-values are the distortion coefficients.
161 //
162 // The coordinate systems are relative to the distortion centre.
163
164 const int max_image_size = std::max(image_width, image_height);
165 const double max_half_image_size = max_image_size * 0.5;
166
167 if (max_half_image_size == 0.0) {
168 *normalized_x = image_x * max_half_image_size / focal_length_x;
169 *normalized_y = image_y * max_half_image_size / focal_length_y;
170 return;
171 }
172
173 const T xd = (image_x - principal_point_x) / max_half_image_size;
174 const T yd = (image_y - principal_point_y) / max_half_image_size;
175
176 T rd2 = xd * xd + yd * yd;
177 T rd4 = rd2 * rd2;
178 T r_coeff = T(1) / (T(1) + k1 * rd2 + k2 * rd4);
179 T xu = xd * r_coeff;
180 T yu = yd * r_coeff;
181
182 *normalized_x = xu * max_half_image_size / focal_length_x;
183 *normalized_y = yu * max_half_image_size / focal_length_y;
184}
185
186// Apply camera intrinsics to the normalized point to get image coordinates.
187// This applies the radial lens distortion to a point which is in normalized
188// camera coordinates (i.e. the principal point is at (0, 0)) to get image
189// coordinates in pixels. Templated for use with autodifferentiation.
190//
191// Uses Nuke distortion model.
192void ApplyNukeDistortionModel(const double focal_length_x,
193 const double focal_length_y,
194 const double principal_point_x,
195 const double principal_point_y,
196 const int image_width,
197 const int image_height,
198 const double k1,
199 const double k2,
200 const double normalized_x,
201 const double normalized_y,
202 double* image_x,
203 double* image_y);
204
205// Invert camera intrinsics on the image point to get normalized coordinates.
206// This inverts the radial lens distortion to a point which is in image pixel
207// coordinates to get normalized coordinates.
208void InvertBrownDistortionModel(const double focal_length_x,
209 const double focal_length_y,
210 const double principal_point_x,
211 const double principal_point_y,
212 const double k1,
213 const double k2,
214 const double k3,
215 const double k4,
216 const double p1,
217 const double p2,
218 const double image_x,
219 const double image_y,
220 double* normalized_x,
221 double* normalized_y);
222
223template <typename T>
224inline void ApplyBrownDistortionModel(const T& focal_length_x,
225 const T& focal_length_y,
226 const T& principal_point_x,
227 const T& principal_point_y,
228 const T& k1,
229 const T& k2,
230 const T& k3,
231 const T& k4,
232 const T& p1,
233 const T& p2,
234 const T& normalized_x,
235 const T& normalized_y,
236 T* image_x,
237 T* image_y) {
238 T x = normalized_x;
239 T y = normalized_y;
240
241 // Apply distortion to the normalized points to get (xd, yd).
242 T x2 = x * x;
243 T y2 = y * y;
244 T xy2 = T(2) * x * y;
245 T r2 = x2 + y2;
246 T r_coeff = T(1) + (((k4 * r2 + k3) * r2 + k2) * r2 + k1) * r2;
247 T tx = p1 * (r2 + T(2) * x2) + p2 * xy2;
248 T ty = p2 * (r2 + T(2) * y2) + p1 * xy2;
249 T xd = x * r_coeff + tx;
250 T yd = y * r_coeff + ty;
251
252 // Apply focal length and principal point to get the final image coordinates.
253 *image_x = focal_length_x * xd + principal_point_x;
254 *image_y = focal_length_y * yd + principal_point_y;
255} // namespace libmv
256
257} // namespace libmv
258
259#endif // LIBMV_SIMPLE_PIPELINE_DISTORTION_MODELS_H_
static constexpr int image_width
static constexpr int image_height
#define T
void InvertNukeDistortionModel(const T &focal_length_x, const T &focal_length_y, const T &principal_point_x, const T &principal_point_y, const int image_width, const int image_height, const T &k1, const T &k2, const T &image_x, const T &image_y, T *normalized_x, T *normalized_y)
void InvertPolynomialDistortionModel(const double focal_length_x, const double focal_length_y, const double principal_point_x, const double principal_point_y, const double k1, const double k2, const double k3, const double p1, const double p2, const double image_x, const double image_y, double *normalized_x, double *normalized_y)
void ApplyPolynomialDistortionModel(const T &focal_length_x, const T &focal_length_y, const T &principal_point_x, const T &principal_point_y, const T &k1, const T &k2, const T &k3, const T &p1, const T &p2, const T &normalized_x, const T &normalized_y, T *image_x, T *image_y)
void ApplyDivisionDistortionModel(const T &focal_length_x, const T &focal_length_y, const T &principal_point_x, const T &principal_point_y, const T &k1, const T &k2, const T &normalized_x, const T &normalized_y, T *image_x, T *image_y)
void ApplyNukeDistortionModel(const double focal_length_x, const double focal_length_y, const double principal_point_x, const double principal_point_y, const int image_width, const int image_height, const double k1, const double k2, const double normalized_x, const double normalized_y, double *image_x, double *image_y)
void InvertBrownDistortionModel(const double focal_length_x, const double focal_length_y, const double principal_point_x, const double principal_point_y, const double k1, const double k2, const double k3, const double k4, const double p1, const double p2, const double image_x, const double image_y, double *normalized_x, double *normalized_y)
void InvertDivisionDistortionModel(const double focal_length_x, const double focal_length_y, const double principal_point_x, const double principal_point_y, const double k1, const double k2, const double image_x, const double image_y, double *normalized_x, double *normalized_y)
@ DISTORTION_MODEL_POLYNOMIAL
@ DISTORTION_MODEL_DIVISION
@ DISTORTION_MODEL_BROWN
@ DISTORTION_MODEL_NUKE
void ApplyBrownDistortionModel(const T &focal_length_x, const T &focal_length_y, const T &principal_point_x, const T &principal_point_y, const T &k1, const T &k2, const T &k3, const T &k4, const T &p1, const T &p2, const T &normalized_x, const T &normalized_y, T *image_x, T *image_y)