1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2011 Blender Foundation.
17  * All rights reserved.
18  */
19 
20 #include "intern/camera_intrinsics.h"
21 #include "intern/utildefines.h"
22 #include "libmv/simple_pipeline/camera_intrinsics.h"
23 
24 using libmv::CameraIntrinsics;
25 using libmv::DivisionCameraIntrinsics;
26 using libmv::PolynomialCameraIntrinsics;
27 using libmv::NukeCameraIntrinsics;
28 using libmv::BrownCameraIntrinsics;
29 
libmv_cameraIntrinsicsNew(const libmv_CameraIntrinsicsOptions * libmv_camera_intrinsics_options)30 libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew(
31     const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options) {
32   CameraIntrinsics *camera_intrinsics =
33     libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options);
34   return (libmv_CameraIntrinsics *) camera_intrinsics;
35 }
36 
libmv_cameraIntrinsicsCopy(const libmv_CameraIntrinsics * libmv_intrinsics)37 libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy(
38     const libmv_CameraIntrinsics* libmv_intrinsics) {
39   const CameraIntrinsics *orig_intrinsics =
40     (const CameraIntrinsics *) libmv_intrinsics;
41 
42   CameraIntrinsics *new_intrinsics = NULL;
43   switch (orig_intrinsics->GetDistortionModelType()) {
44     case libmv::DISTORTION_MODEL_POLYNOMIAL:
45       {
46         const PolynomialCameraIntrinsics *polynomial_intrinsics =
47           static_cast<const PolynomialCameraIntrinsics*>(orig_intrinsics);
48         new_intrinsics = LIBMV_OBJECT_NEW(PolynomialCameraIntrinsics,
49                                           *polynomial_intrinsics);
50         break;
51       }
52     case libmv::DISTORTION_MODEL_DIVISION:
53       {
54         const DivisionCameraIntrinsics *division_intrinsics =
55           static_cast<const DivisionCameraIntrinsics*>(orig_intrinsics);
56         new_intrinsics = LIBMV_OBJECT_NEW(DivisionCameraIntrinsics,
57                                           *division_intrinsics);
58         break;
59       }
60     case libmv::DISTORTION_MODEL_NUKE:
61       {
62         const NukeCameraIntrinsics *nuke_intrinsics =
63           static_cast<const NukeCameraIntrinsics*>(orig_intrinsics);
64         new_intrinsics = LIBMV_OBJECT_NEW(NukeCameraIntrinsics,
65                                           *nuke_intrinsics);
66         break;
67       }
68     case libmv::DISTORTION_MODEL_BROWN:
69       {
70         const BrownCameraIntrinsics *brown_intrinsics =
71           static_cast<const BrownCameraIntrinsics*>(orig_intrinsics);
72         new_intrinsics = LIBMV_OBJECT_NEW(BrownCameraIntrinsics,
73                                           *brown_intrinsics);
74         break;
75       }
76     default:
77       assert(!"Unknown distortion model");
78   }
79   return (libmv_CameraIntrinsics *) new_intrinsics;
80 }
81 
libmv_cameraIntrinsicsDestroy(libmv_CameraIntrinsics * libmv_intrinsics)82 void libmv_cameraIntrinsicsDestroy(libmv_CameraIntrinsics* libmv_intrinsics) {
83   LIBMV_OBJECT_DELETE(libmv_intrinsics, CameraIntrinsics);
84 }
85 
libmv_cameraIntrinsicsUpdate(const libmv_CameraIntrinsicsOptions * libmv_camera_intrinsics_options,libmv_CameraIntrinsics * libmv_intrinsics)86 void libmv_cameraIntrinsicsUpdate(
87     const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
88     libmv_CameraIntrinsics* libmv_intrinsics) {
89   CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics;
90 
91   double focal_length = libmv_camera_intrinsics_options->focal_length;
92   double principal_x = libmv_camera_intrinsics_options->principal_point_x;
93   double principal_y = libmv_camera_intrinsics_options->principal_point_y;
94   int image_width = libmv_camera_intrinsics_options->image_width;
95   int image_height = libmv_camera_intrinsics_options->image_height;
96 
97   /* Try avoid unnecessary updates, so pre-computed distortion grids
98    * are not freed.
99    */
100 
101   camera_intrinsics->SetThreads(libmv_camera_intrinsics_options->num_threads);
102 
103   if (camera_intrinsics->focal_length() != focal_length) {
104     camera_intrinsics->SetFocalLength(focal_length, focal_length);
105   }
106 
107   if (camera_intrinsics->principal_point_x() != principal_x ||
108       camera_intrinsics->principal_point_y() != principal_y) {
109     camera_intrinsics->SetPrincipalPoint(principal_x, principal_y);
110   }
111 
112   if (camera_intrinsics->image_width() != image_width ||
113       camera_intrinsics->image_height() != image_height) {
114     camera_intrinsics->SetImageSize(image_width, image_height);
115   }
116 
117   switch (libmv_camera_intrinsics_options->distortion_model) {
118     case LIBMV_DISTORTION_MODEL_POLYNOMIAL:
119       {
120         assert(camera_intrinsics->GetDistortionModelType() ==
121                libmv::DISTORTION_MODEL_POLYNOMIAL);
122 
123         PolynomialCameraIntrinsics *polynomial_intrinsics =
124           (PolynomialCameraIntrinsics *) camera_intrinsics;
125 
126         double k1 = libmv_camera_intrinsics_options->polynomial_k1;
127         double k2 = libmv_camera_intrinsics_options->polynomial_k2;
128         double k3 = libmv_camera_intrinsics_options->polynomial_k3;
129 
130         if (polynomial_intrinsics->k1() != k1 ||
131             polynomial_intrinsics->k2() != k2 ||
132             polynomial_intrinsics->k3() != k3) {
133           polynomial_intrinsics->SetRadialDistortion(k1, k2, k3);
134         }
135         break;
136       }
137 
138     case LIBMV_DISTORTION_MODEL_DIVISION:
139       {
140         assert(camera_intrinsics->GetDistortionModelType() ==
141                libmv::DISTORTION_MODEL_DIVISION);
142 
143         DivisionCameraIntrinsics *division_intrinsics =
144           (DivisionCameraIntrinsics *) camera_intrinsics;
145 
146         double k1 = libmv_camera_intrinsics_options->division_k1;
147         double k2 = libmv_camera_intrinsics_options->division_k2;
148 
149         if (division_intrinsics->k1() != k1 ||
150             division_intrinsics->k2() != k2) {
151           division_intrinsics->SetDistortion(k1, k2);
152         }
153 
154         break;
155       }
156 
157     case LIBMV_DISTORTION_MODEL_NUKE:
158       {
159         assert(camera_intrinsics->GetDistortionModelType() ==
160                libmv::DISTORTION_MODEL_NUKE);
161 
162         NukeCameraIntrinsics *nuke_intrinsics =
163           (NukeCameraIntrinsics *) camera_intrinsics;
164 
165         double k1 = libmv_camera_intrinsics_options->nuke_k1;
166         double k2 = libmv_camera_intrinsics_options->nuke_k2;
167 
168         if (nuke_intrinsics->k1() != k1 ||
169             nuke_intrinsics->k2() != k2) {
170           nuke_intrinsics->SetDistortion(k1, k2);
171         }
172 
173         break;
174       }
175 
176     case LIBMV_DISTORTION_MODEL_BROWN:
177       {
178         assert(camera_intrinsics->GetDistortionModelType() ==
179                libmv::DISTORTION_MODEL_BROWN);
180 
181         BrownCameraIntrinsics *brown_intrinsics =
182           (BrownCameraIntrinsics *) camera_intrinsics;
183 
184         double k1 = libmv_camera_intrinsics_options->brown_k1;
185         double k2 = libmv_camera_intrinsics_options->brown_k2;
186         double k3 = libmv_camera_intrinsics_options->brown_k3;
187         double k4 = libmv_camera_intrinsics_options->brown_k4;
188 
189         if (brown_intrinsics->k1() != k1 ||
190             brown_intrinsics->k2() != k2 ||
191             brown_intrinsics->k3() != k3 ||
192             brown_intrinsics->k4() != k4) {
193           brown_intrinsics->SetRadialDistortion(k1, k2, k3, k4);
194         }
195 
196         double p1 = libmv_camera_intrinsics_options->brown_p1;
197         double p2 = libmv_camera_intrinsics_options->brown_p2;
198 
199         if (brown_intrinsics->p1() != p1 || brown_intrinsics->p2() != p2) {
200           brown_intrinsics->SetTangentialDistortion(p1, p2);
201         }
202         break;
203       }
204 
205     default:
206       assert(!"Unknown distortion model");
207   }
208 }
209 
libmv_cameraIntrinsicsSetThreads(libmv_CameraIntrinsics * libmv_intrinsics,int threads)210 void libmv_cameraIntrinsicsSetThreads(libmv_CameraIntrinsics* libmv_intrinsics,
211                                       int threads) {
212   CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics;
213   camera_intrinsics->SetThreads(threads);
214 }
215 
libmv_cameraIntrinsicsExtractOptions(const libmv_CameraIntrinsics * libmv_intrinsics,libmv_CameraIntrinsicsOptions * camera_intrinsics_options)216 void libmv_cameraIntrinsicsExtractOptions(
217     const libmv_CameraIntrinsics* libmv_intrinsics,
218     libmv_CameraIntrinsicsOptions* camera_intrinsics_options) {
219   const CameraIntrinsics *camera_intrinsics =
220     (const CameraIntrinsics *) libmv_intrinsics;
221 
222   // Fill in options which are common for all distortion models.
223   camera_intrinsics_options->focal_length = camera_intrinsics->focal_length();
224   camera_intrinsics_options->principal_point_x =
225     camera_intrinsics->principal_point_x();
226   camera_intrinsics_options->principal_point_y =
227     camera_intrinsics->principal_point_y();
228 
229   camera_intrinsics_options->image_width = camera_intrinsics->image_width();
230   camera_intrinsics_options->image_height = camera_intrinsics->image_height();
231 
232   switch (camera_intrinsics->GetDistortionModelType()) {
233     case libmv::DISTORTION_MODEL_POLYNOMIAL:
234       {
235         const PolynomialCameraIntrinsics *polynomial_intrinsics =
236           static_cast<const PolynomialCameraIntrinsics *>(camera_intrinsics);
237         camera_intrinsics_options->distortion_model =
238           LIBMV_DISTORTION_MODEL_POLYNOMIAL;
239         camera_intrinsics_options->polynomial_k1 = polynomial_intrinsics->k1();
240         camera_intrinsics_options->polynomial_k2 = polynomial_intrinsics->k2();
241         camera_intrinsics_options->polynomial_k3 = polynomial_intrinsics->k3();
242         camera_intrinsics_options->polynomial_p1 = polynomial_intrinsics->p1();
243         camera_intrinsics_options->polynomial_p2 = polynomial_intrinsics->p2();
244         break;
245       }
246 
247     case libmv::DISTORTION_MODEL_DIVISION:
248       {
249         const DivisionCameraIntrinsics *division_intrinsics =
250           static_cast<const DivisionCameraIntrinsics *>(camera_intrinsics);
251         camera_intrinsics_options->distortion_model =
252           LIBMV_DISTORTION_MODEL_DIVISION;
253         camera_intrinsics_options->division_k1 = division_intrinsics->k1();
254         camera_intrinsics_options->division_k2 = division_intrinsics->k2();
255         break;
256       }
257 
258     case libmv::DISTORTION_MODEL_NUKE:
259       {
260         const NukeCameraIntrinsics *nuke_intrinsics =
261           static_cast<const NukeCameraIntrinsics *>(camera_intrinsics);
262         camera_intrinsics_options->distortion_model =
263           LIBMV_DISTORTION_MODEL_NUKE;
264         camera_intrinsics_options->nuke_k1 = nuke_intrinsics->k1();
265         camera_intrinsics_options->nuke_k2 = nuke_intrinsics->k2();
266         break;
267       }
268 
269     case libmv::DISTORTION_MODEL_BROWN:
270       {
271         const BrownCameraIntrinsics *brown_intrinsics =
272           static_cast<const BrownCameraIntrinsics *>(camera_intrinsics);
273         camera_intrinsics_options->distortion_model =
274           LIBMV_DISTORTION_MODEL_BROWN;
275         camera_intrinsics_options->brown_k1 = brown_intrinsics->k1();
276         camera_intrinsics_options->brown_k2 = brown_intrinsics->k2();
277         camera_intrinsics_options->brown_k3 = brown_intrinsics->k3();
278         camera_intrinsics_options->brown_k4 = brown_intrinsics->k4();
279         camera_intrinsics_options->brown_p1 = brown_intrinsics->p1();
280         camera_intrinsics_options->brown_p2 = brown_intrinsics->p2();
281         break;
282       }
283 
284     default:
285       assert(!"Unknown distortion model");
286   }
287 }
288 
libmv_cameraIntrinsicsUndistortByte(const libmv_CameraIntrinsics * libmv_intrinsics,const unsigned char * source_image,int width,int height,float overscan,int channels,unsigned char * destination_image)289 void libmv_cameraIntrinsicsUndistortByte(
290     const libmv_CameraIntrinsics* libmv_intrinsics,
291     const unsigned char *source_image,
292     int width,
293     int height,
294     float overscan,
295     int channels,
296     unsigned char* destination_image) {
297   CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics;
298   camera_intrinsics->UndistortBuffer(source_image,
299                                      width, height,
300                                      overscan,
301                                      channels,
302                                      destination_image);
303 }
304 
libmv_cameraIntrinsicsUndistortFloat(const libmv_CameraIntrinsics * libmv_intrinsics,const float * source_image,int width,int height,float overscan,int channels,float * destination_image)305 void libmv_cameraIntrinsicsUndistortFloat(
306     const libmv_CameraIntrinsics* libmv_intrinsics,
307     const float* source_image,
308     int width,
309     int height,
310     float overscan,
311     int channels,
312     float* destination_image) {
313   CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics;
314   intrinsics->UndistortBuffer(source_image,
315                               width, height,
316                               overscan,
317                               channels,
318                               destination_image);
319 }
320 
libmv_cameraIntrinsicsDistortByte(const struct libmv_CameraIntrinsics * libmv_intrinsics,const unsigned char * source_image,int width,int height,float overscan,int channels,unsigned char * destination_image)321 void libmv_cameraIntrinsicsDistortByte(
322     const struct libmv_CameraIntrinsics* libmv_intrinsics,
323     const unsigned char *source_image,
324     int width,
325     int height,
326     float overscan,
327     int channels,
328     unsigned char *destination_image) {
329   CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics;
330   intrinsics->DistortBuffer(source_image,
331                             width, height,
332                             overscan,
333                             channels,
334                             destination_image);
335 }
336 
libmv_cameraIntrinsicsDistortFloat(const libmv_CameraIntrinsics * libmv_intrinsics,float * source_image,int width,int height,float overscan,int channels,float * destination_image)337 void libmv_cameraIntrinsicsDistortFloat(
338     const libmv_CameraIntrinsics* libmv_intrinsics,
339     float* source_image,
340     int width,
341     int height,
342     float overscan,
343     int channels,
344     float* destination_image) {
345   CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics;
346   intrinsics->DistortBuffer(source_image,
347                             width, height,
348                             overscan,
349                             channels,
350                             destination_image);
351 }
352 
libmv_cameraIntrinsicsApply(const struct libmv_CameraIntrinsics * libmv_intrinsics,double x,double y,double * x1,double * y1)353 void libmv_cameraIntrinsicsApply(
354     const struct libmv_CameraIntrinsics* libmv_intrinsics,
355     double x,
356     double y,
357     double* x1,
358     double* y1) {
359   CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics;
360   intrinsics->ApplyIntrinsics(x, y, x1, y1);
361 }
362 
libmv_cameraIntrinsicsInvert(const struct libmv_CameraIntrinsics * libmv_intrinsics,double x,double y,double * x1,double * y1)363 void libmv_cameraIntrinsicsInvert(
364     const struct libmv_CameraIntrinsics* libmv_intrinsics,
365     double x,
366     double y,
367     double* x1,
368     double* y1) {
369   CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics;
370   intrinsics->InvertIntrinsics(x, y, x1, y1);
371 }
372 
libmv_cameraIntrinsicsFillFromOptions(const libmv_CameraIntrinsicsOptions * camera_intrinsics_options,CameraIntrinsics * camera_intrinsics)373 static void libmv_cameraIntrinsicsFillFromOptions(
374     const libmv_CameraIntrinsicsOptions* camera_intrinsics_options,
375     CameraIntrinsics* camera_intrinsics) {
376   camera_intrinsics->SetFocalLength(camera_intrinsics_options->focal_length,
377                                     camera_intrinsics_options->focal_length);
378 
379   camera_intrinsics->SetPrincipalPoint(
380       camera_intrinsics_options->principal_point_x,
381       camera_intrinsics_options->principal_point_y);
382 
383   camera_intrinsics->SetImageSize(camera_intrinsics_options->image_width,
384       camera_intrinsics_options->image_height);
385 
386   switch (camera_intrinsics_options->distortion_model) {
387     case LIBMV_DISTORTION_MODEL_POLYNOMIAL:
388       {
389         PolynomialCameraIntrinsics *polynomial_intrinsics =
390           static_cast<PolynomialCameraIntrinsics*>(camera_intrinsics);
391 
392         polynomial_intrinsics->SetRadialDistortion(
393             camera_intrinsics_options->polynomial_k1,
394             camera_intrinsics_options->polynomial_k2,
395             camera_intrinsics_options->polynomial_k3);
396 
397         break;
398       }
399 
400     case LIBMV_DISTORTION_MODEL_DIVISION:
401       {
402         DivisionCameraIntrinsics *division_intrinsics =
403           static_cast<DivisionCameraIntrinsics*>(camera_intrinsics);
404 
405         division_intrinsics->SetDistortion(
406             camera_intrinsics_options->division_k1,
407             camera_intrinsics_options->division_k2);
408         break;
409       }
410 
411     case LIBMV_DISTORTION_MODEL_NUKE:
412       {
413         NukeCameraIntrinsics *nuke_intrinsics =
414           static_cast<NukeCameraIntrinsics*>(camera_intrinsics);
415 
416         nuke_intrinsics->SetDistortion(
417             camera_intrinsics_options->nuke_k1,
418             camera_intrinsics_options->nuke_k2);
419         break;
420       }
421 
422     case LIBMV_DISTORTION_MODEL_BROWN:
423       {
424         BrownCameraIntrinsics *brown_intrinsics =
425           static_cast<BrownCameraIntrinsics*>(camera_intrinsics);
426 
427         brown_intrinsics->SetRadialDistortion(
428             camera_intrinsics_options->brown_k1,
429             camera_intrinsics_options->brown_k2,
430             camera_intrinsics_options->brown_k3,
431             camera_intrinsics_options->brown_k4);
432         brown_intrinsics->SetTangentialDistortion(
433           camera_intrinsics_options->brown_p1,
434           camera_intrinsics_options->brown_p2);
435 
436         break;
437       }
438 
439     default:
440       assert(!"Unknown distortion model");
441   }
442 }
443 
libmv_cameraIntrinsicsCreateFromOptions(const libmv_CameraIntrinsicsOptions * camera_intrinsics_options)444 CameraIntrinsics* libmv_cameraIntrinsicsCreateFromOptions(
445     const libmv_CameraIntrinsicsOptions* camera_intrinsics_options) {
446   CameraIntrinsics *camera_intrinsics = NULL;
447   switch (camera_intrinsics_options->distortion_model) {
448     case LIBMV_DISTORTION_MODEL_POLYNOMIAL:
449       camera_intrinsics = LIBMV_OBJECT_NEW(PolynomialCameraIntrinsics);
450       break;
451     case LIBMV_DISTORTION_MODEL_DIVISION:
452       camera_intrinsics = LIBMV_OBJECT_NEW(DivisionCameraIntrinsics);
453       break;
454     case LIBMV_DISTORTION_MODEL_NUKE:
455       camera_intrinsics = LIBMV_OBJECT_NEW(NukeCameraIntrinsics);
456       break;
457     case LIBMV_DISTORTION_MODEL_BROWN:
458       camera_intrinsics = LIBMV_OBJECT_NEW(BrownCameraIntrinsics);
459       break;
460     default:
461       assert(!"Unknown distortion model");
462   }
463   libmv_cameraIntrinsicsFillFromOptions(camera_intrinsics_options,
464                                         camera_intrinsics);
465   return camera_intrinsics;
466 }
467