Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/libmv/intern')
-rw-r--r--extern/libmv/intern/camera_intrinsics.cc354
-rw-r--r--extern/libmv/intern/camera_intrinsics.h138
-rw-r--r--extern/libmv/intern/detector.cc148
-rw-r--r--extern/libmv/intern/detector.h77
-rw-r--r--extern/libmv/intern/homography.cc59
-rw-r--r--extern/libmv/intern/homography.h43
-rw-r--r--extern/libmv/intern/image.cc272
-rw-r--r--extern/libmv/intern/image.h99
-rw-r--r--extern/libmv/intern/logging.cc55
-rw-r--r--extern/libmv/intern/logging.h47
-rw-r--r--extern/libmv/intern/reconstruction.cc530
-rw-r--r--extern/libmv/intern/reconstruction.h99
-rw-r--r--extern/libmv/intern/region.h43
-rw-r--r--extern/libmv/intern/stub.cc330
-rw-r--r--extern/libmv/intern/track_region.cc177
-rw-r--r--extern/libmv/intern/track_region.h81
-rw-r--r--extern/libmv/intern/tracks.cc52
-rw-r--r--extern/libmv/intern/tracks.h51
-rw-r--r--extern/libmv/intern/utildefines.h62
19 files changed, 2717 insertions, 0 deletions
diff --git a/extern/libmv/intern/camera_intrinsics.cc b/extern/libmv/intern/camera_intrinsics.cc
new file mode 100644
index 00000000000..e8b99970ff7
--- /dev/null
+++ b/extern/libmv/intern/camera_intrinsics.cc
@@ -0,0 +1,354 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "intern/camera_intrinsics.h"
+#include "intern/utildefines.h"
+#include "libmv/simple_pipeline/camera_intrinsics.h"
+
+using libmv::CameraIntrinsics;
+using libmv::DivisionCameraIntrinsics;
+using libmv::PolynomialCameraIntrinsics;
+
+libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew(
+ const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options) {
+ CameraIntrinsics *camera_intrinsics =
+ libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options);
+ return (libmv_CameraIntrinsics *) camera_intrinsics;
+}
+
+libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy(
+ const libmv_CameraIntrinsics* libmv_intrinsics) {
+ const CameraIntrinsics *orig_intrinsics =
+ (const CameraIntrinsics *) libmv_intrinsics;
+
+ CameraIntrinsics *new_intrinsics = NULL;
+ switch (orig_intrinsics->GetDistortionModelType()) {
+ case libmv::DISTORTION_MODEL_POLYNOMIAL:
+ {
+ const PolynomialCameraIntrinsics *polynomial_intrinsics =
+ static_cast<const PolynomialCameraIntrinsics*>(orig_intrinsics);
+ new_intrinsics = LIBMV_OBJECT_NEW(PolynomialCameraIntrinsics,
+ *polynomial_intrinsics);
+ break;
+ }
+ case libmv::DISTORTION_MODEL_DIVISION:
+ {
+ const DivisionCameraIntrinsics *division_intrinsics =
+ static_cast<const DivisionCameraIntrinsics*>(orig_intrinsics);
+ new_intrinsics = LIBMV_OBJECT_NEW(DivisionCameraIntrinsics,
+ *division_intrinsics);
+ break;
+ }
+ default:
+ assert(!"Unknown distortion model");
+ }
+ return (libmv_CameraIntrinsics *) new_intrinsics;
+}
+
+void libmv_cameraIntrinsicsDestroy(libmv_CameraIntrinsics* libmv_intrinsics) {
+ LIBMV_OBJECT_DELETE(libmv_intrinsics, CameraIntrinsics);
+}
+
+void libmv_cameraIntrinsicsUpdate(
+ const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
+ libmv_CameraIntrinsics* libmv_intrinsics) {
+ CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics;
+
+ double focal_length = libmv_camera_intrinsics_options->focal_length;
+ double principal_x = libmv_camera_intrinsics_options->principal_point_x;
+ double principal_y = libmv_camera_intrinsics_options->principal_point_y;
+ int image_width = libmv_camera_intrinsics_options->image_width;
+ int image_height = libmv_camera_intrinsics_options->image_height;
+
+ /* Try avoid unnecessary updates, so pre-computed distortion grids
+ * are not freed.
+ */
+
+ if (camera_intrinsics->focal_length() != focal_length) {
+ camera_intrinsics->SetFocalLength(focal_length, focal_length);
+ }
+
+ if (camera_intrinsics->principal_point_x() != principal_x ||
+ camera_intrinsics->principal_point_y() != principal_y) {
+ camera_intrinsics->SetPrincipalPoint(principal_x, principal_y);
+ }
+
+ if (camera_intrinsics->image_width() != image_width ||
+ camera_intrinsics->image_height() != image_height) {
+ camera_intrinsics->SetImageSize(image_width, image_height);
+ }
+
+ switch (libmv_camera_intrinsics_options->distortion_model) {
+ case LIBMV_DISTORTION_MODEL_POLYNOMIAL:
+ {
+ assert(camera_intrinsics->GetDistortionModelType() ==
+ libmv::DISTORTION_MODEL_POLYNOMIAL);
+
+ PolynomialCameraIntrinsics *polynomial_intrinsics =
+ (PolynomialCameraIntrinsics *) camera_intrinsics;
+
+ double k1 = libmv_camera_intrinsics_options->polynomial_k1;
+ double k2 = libmv_camera_intrinsics_options->polynomial_k2;
+ double k3 = libmv_camera_intrinsics_options->polynomial_k3;
+
+ if (polynomial_intrinsics->k1() != k1 ||
+ polynomial_intrinsics->k2() != k2 ||
+ polynomial_intrinsics->k3() != k3) {
+ polynomial_intrinsics->SetRadialDistortion(k1, k2, k3);
+ }
+ break;
+ }
+
+ case LIBMV_DISTORTION_MODEL_DIVISION:
+ {
+ assert(camera_intrinsics->GetDistortionModelType() ==
+ libmv::DISTORTION_MODEL_DIVISION);
+
+ DivisionCameraIntrinsics *division_intrinsics =
+ (DivisionCameraIntrinsics *) camera_intrinsics;
+
+ double k1 = libmv_camera_intrinsics_options->division_k1;
+ double k2 = libmv_camera_intrinsics_options->division_k2;
+
+ if (division_intrinsics->k1() != k1 ||
+ division_intrinsics->k2() != k2) {
+ division_intrinsics->SetDistortion(k1, k2);
+ }
+
+ break;
+ }
+
+ default:
+ assert(!"Unknown distortion model");
+ }
+}
+
+void libmv_cameraIntrinsicsSetThreads(libmv_CameraIntrinsics* libmv_intrinsics,
+ int threads) {
+ CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics;
+ camera_intrinsics->SetThreads(threads);
+}
+
+void libmv_cameraIntrinsicsExtractOptions(
+ const libmv_CameraIntrinsics* libmv_intrinsics,
+ libmv_CameraIntrinsicsOptions* camera_intrinsics_options) {
+ const CameraIntrinsics *camera_intrinsics =
+ (const CameraIntrinsics *) libmv_intrinsics;
+
+ // Fill in options which are common for all distortion models.
+ camera_intrinsics_options->focal_length = camera_intrinsics->focal_length();
+ camera_intrinsics_options->principal_point_x =
+ camera_intrinsics->principal_point_x();
+ camera_intrinsics_options->principal_point_y =
+ camera_intrinsics->principal_point_y();
+
+ camera_intrinsics_options->image_width = camera_intrinsics->image_width();
+ camera_intrinsics_options->image_height = camera_intrinsics->image_height();
+
+ switch (camera_intrinsics->GetDistortionModelType()) {
+ case libmv::DISTORTION_MODEL_POLYNOMIAL:
+ {
+ const PolynomialCameraIntrinsics *polynomial_intrinsics =
+ static_cast<const PolynomialCameraIntrinsics *>(camera_intrinsics);
+ camera_intrinsics_options->distortion_model =
+ LIBMV_DISTORTION_MODEL_POLYNOMIAL;
+ camera_intrinsics_options->polynomial_k1 = polynomial_intrinsics->k1();
+ camera_intrinsics_options->polynomial_k2 = polynomial_intrinsics->k2();
+ camera_intrinsics_options->polynomial_k3 = polynomial_intrinsics->k3();
+ camera_intrinsics_options->polynomial_p1 = polynomial_intrinsics->p1();
+ camera_intrinsics_options->polynomial_p1 = polynomial_intrinsics->p2();
+ break;
+ }
+
+ case libmv::DISTORTION_MODEL_DIVISION:
+ {
+ const DivisionCameraIntrinsics *division_intrinsics =
+ static_cast<const DivisionCameraIntrinsics *>(camera_intrinsics);
+ camera_intrinsics_options->distortion_model =
+ LIBMV_DISTORTION_MODEL_DIVISION;
+ camera_intrinsics_options->division_k1 = division_intrinsics->k1();
+ camera_intrinsics_options->division_k2 = division_intrinsics->k2();
+ break;
+ }
+
+ default:
+ assert(!"Uknown distortion model");
+ }
+}
+
+void libmv_cameraIntrinsicsUndistortByte(
+ const libmv_CameraIntrinsics* libmv_intrinsics,
+ const unsigned char *source_image,
+ int width,
+ int height,
+ float overscan,
+ int channels,
+ unsigned char* destination_image) {
+ CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics;
+ camera_intrinsics->UndistortBuffer(source_image,
+ width, height,
+ overscan,
+ channels,
+ destination_image);
+}
+
+void libmv_cameraIntrinsicsUndistortFloat(
+ const libmv_CameraIntrinsics* libmv_intrinsics,
+ const float* source_image,
+ int width,
+ int height,
+ float overscan,
+ int channels,
+ float* destination_image) {
+ CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics;
+ intrinsics->UndistortBuffer(source_image,
+ width, height,
+ overscan,
+ channels,
+ destination_image);
+}
+
+void 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) {
+ CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics;
+ intrinsics->DistortBuffer(source_image,
+ width, height,
+ overscan,
+ channels,
+ destination_image);
+}
+
+void libmv_cameraIntrinsicsDistortFloat(
+ const libmv_CameraIntrinsics* libmv_intrinsics,
+ float* source_image,
+ int width,
+ int height,
+ float overscan,
+ int channels,
+ float* destination_image) {
+ CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics;
+ intrinsics->DistortBuffer(source_image,
+ width, height,
+ overscan,
+ channels,
+ destination_image);
+}
+
+void libmv_cameraIntrinsicsApply(
+ const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
+ double x,
+ double y,
+ double* x1,
+ double* y1) {
+ /* Do a lens distortion if focal length is non-zero only. */
+ if (libmv_camera_intrinsics_options->focal_length) {
+ CameraIntrinsics* camera_intrinsics =
+ libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options);
+ camera_intrinsics->ApplyIntrinsics(x, y, x1, y1);
+ LIBMV_OBJECT_DELETE(camera_intrinsics, CameraIntrinsics);
+ }
+}
+
+void libmv_cameraIntrinsicsInvert(
+ const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
+ double x,
+ double y,
+ double* x1,
+ double* y1) {
+ /* Do a lens un-distortion if focal length is non-zero only/ */
+ if (libmv_camera_intrinsics_options->focal_length) {
+ CameraIntrinsics *camera_intrinsics =
+ libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options);
+ camera_intrinsics->InvertIntrinsics(x, y, x1, y1);
+ LIBMV_OBJECT_DELETE(camera_intrinsics, CameraIntrinsics);
+ }
+}
+
+static void libmv_cameraIntrinsicsFillFromOptions(
+ const libmv_CameraIntrinsicsOptions* camera_intrinsics_options,
+ CameraIntrinsics* camera_intrinsics) {
+ camera_intrinsics->SetFocalLength(camera_intrinsics_options->focal_length,
+ camera_intrinsics_options->focal_length);
+
+ camera_intrinsics->SetPrincipalPoint(
+ camera_intrinsics_options->principal_point_x,
+ camera_intrinsics_options->principal_point_y);
+
+ camera_intrinsics->SetImageSize(camera_intrinsics_options->image_width,
+ camera_intrinsics_options->image_height);
+
+ switch (camera_intrinsics_options->distortion_model) {
+ case LIBMV_DISTORTION_MODEL_POLYNOMIAL:
+ {
+ PolynomialCameraIntrinsics *polynomial_intrinsics =
+ static_cast<PolynomialCameraIntrinsics*>(camera_intrinsics);
+
+ polynomial_intrinsics->SetRadialDistortion(
+ camera_intrinsics_options->polynomial_k1,
+ camera_intrinsics_options->polynomial_k2,
+ camera_intrinsics_options->polynomial_k3);
+
+ break;
+ }
+
+ case LIBMV_DISTORTION_MODEL_DIVISION:
+ {
+ DivisionCameraIntrinsics *division_intrinsics =
+ static_cast<DivisionCameraIntrinsics*>(camera_intrinsics);
+
+ division_intrinsics->SetDistortion(
+ camera_intrinsics_options->division_k1,
+ camera_intrinsics_options->division_k2);
+ break;
+ }
+
+ default:
+ assert(!"Unknown distortion model");
+ }
+}
+
+CameraIntrinsics* libmv_cameraIntrinsicsCreateFromOptions(
+ const libmv_CameraIntrinsicsOptions* camera_intrinsics_options) {
+ CameraIntrinsics *camera_intrinsics = NULL;
+ switch (camera_intrinsics_options->distortion_model) {
+ case LIBMV_DISTORTION_MODEL_POLYNOMIAL:
+ camera_intrinsics = LIBMV_OBJECT_NEW(PolynomialCameraIntrinsics);
+ break;
+ case LIBMV_DISTORTION_MODEL_DIVISION:
+ camera_intrinsics = LIBMV_OBJECT_NEW(DivisionCameraIntrinsics);
+ break;
+ default:
+ assert(!"Unknown distortion model");
+ }
+ libmv_cameraIntrinsicsFillFromOptions(camera_intrinsics_options, camera_intrinsics);
+ return camera_intrinsics;
+}
diff --git a/extern/libmv/intern/camera_intrinsics.h b/extern/libmv/intern/camera_intrinsics.h
new file mode 100644
index 00000000000..9910d16a108
--- /dev/null
+++ b/extern/libmv/intern/camera_intrinsics.h
@@ -0,0 +1,138 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef LIBMV_C_API_CAMERA_INTRINSICS_H_
+#define LIBMV_C_API_CAMERA_INTRINSICS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct libmv_CameraIntrinsics libmv_CameraIntrinsics;
+
+enum {
+ LIBMV_DISTORTION_MODEL_POLYNOMIAL = 0,
+ LIBMV_DISTORTION_MODEL_DIVISION = 1,
+};
+
+typedef struct libmv_CameraIntrinsicsOptions {
+ // Common settings of all distortion models.
+ int distortion_model;
+ int image_width, image_height;
+ double focal_length;
+ double principal_point_x, principal_point_y;
+
+ // Radial distortion model.
+ double polynomial_k1, polynomial_k2, polynomial_k3;
+ double polynomial_p1, polynomial_p2;
+
+ // Division distortion model.
+ double division_k1, division_k2;
+} libmv_CameraIntrinsicsOptions;
+
+libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew(
+ const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options);
+
+libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy(
+ const libmv_CameraIntrinsics* libmv_intrinsics);
+
+void libmv_cameraIntrinsicsDestroy(libmv_CameraIntrinsics* libmv_intrinsics);
+void libmv_cameraIntrinsicsUpdate(
+ const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
+ libmv_CameraIntrinsics* libmv_intrinsics);
+
+void libmv_cameraIntrinsicsSetThreads(libmv_CameraIntrinsics* libmv_intrinsics,
+ int threads);
+
+void libmv_cameraIntrinsicsExtractOptions(
+ const libmv_CameraIntrinsics* libmv_intrinsics,
+ libmv_CameraIntrinsicsOptions* camera_intrinsics_options);
+
+void libmv_cameraIntrinsicsUndistortByte(
+ const libmv_CameraIntrinsics* libmv_intrinsics,
+ const unsigned char *source_image,
+ int width,
+ int height,
+ float overscan,
+ int channels,
+ unsigned char* destination_image);
+
+void libmv_cameraIntrinsicsUndistortFloat(
+ const libmv_CameraIntrinsics* libmv_intrinsics,
+ const float* source_image,
+ int width,
+ int height,
+ float overscan,
+ int channels,
+ float* destination_image);
+
+void 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);
+
+void libmv_cameraIntrinsicsDistortFloat(
+ const libmv_CameraIntrinsics* libmv_intrinsics,
+ float* source_image,
+ int width,
+ int height,
+ float overscan,
+ int channels,
+ float* destination_image);
+
+void libmv_cameraIntrinsicsApply(
+ const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
+ double x,
+ double y,
+ double* x1,
+ double* y1);
+
+void libmv_cameraIntrinsicsInvert(
+ const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
+ double x,
+ double y,
+ double* x1,
+ double* y1);
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+
+namespace libmv {
+ class CameraIntrinsics;
+}
+
+libmv::CameraIntrinsics* libmv_cameraIntrinsicsCreateFromOptions(
+ const libmv_CameraIntrinsicsOptions* camera_intrinsics_options);
+#endif
+
+#endif // LIBMV_C_API_CAMERA_INTRINSICS_H_
diff --git a/extern/libmv/intern/detector.cc b/extern/libmv/intern/detector.cc
new file mode 100644
index 00000000000..8abc9014115
--- /dev/null
+++ b/extern/libmv/intern/detector.cc
@@ -0,0 +1,148 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "intern/detector.h"
+#include "intern/image.h"
+#include "intern/utildefines.h"
+#include "libmv/simple_pipeline/detect.h"
+
+using libmv::Detect;
+using libmv::DetectOptions;
+using libmv::Feature;
+using libmv::FloatImage;
+
+struct libmv_Features {
+ int count;
+ Feature* features;
+};
+
+namespace {
+
+libmv_Features *libmv_featuresFromVector(
+ const libmv::vector<Feature>& features) {
+ libmv_Features* libmv_features = LIBMV_STRUCT_NEW(libmv_Features, 1);
+ int count = features.size();
+ if (count) {
+ libmv_features->features = LIBMV_STRUCT_NEW(Feature, count);
+ for (int i = 0; i < count; i++) {
+ libmv_features->features[i] = features.at(i);
+ }
+ } else {
+ libmv_features->features = NULL;
+ }
+ libmv_features->count = count;
+ return libmv_features;
+}
+
+void libmv_convertDetectorOptions(libmv_DetectOptions *options,
+ DetectOptions *detector_options) {
+ switch (options->detector) {
+#define LIBMV_CONVERT(the_detector) \
+ case LIBMV_DETECTOR_ ## the_detector: \
+ detector_options->type = DetectOptions::the_detector; \
+ break;
+ LIBMV_CONVERT(FAST)
+ LIBMV_CONVERT(MORAVEC)
+ LIBMV_CONVERT(HARRIS)
+#undef LIBMV_CONVERT
+ }
+ detector_options->margin = options->margin;
+ detector_options->min_distance = options->min_distance;
+ detector_options->fast_min_trackness = options->fast_min_trackness;
+ detector_options->moravec_max_count = options->moravec_max_count;
+ detector_options->moravec_pattern = options->moravec_pattern;
+ detector_options->harris_threshold = options->harris_threshold;
+}
+
+} // namespace
+
+libmv_Features *libmv_detectFeaturesByte(const unsigned char* image_buffer,
+ int width,
+ int height,
+ int channels,
+ libmv_DetectOptions* options) {
+ // Prepare the image.
+ FloatImage image;
+ libmv_byteBufferToFloatImage(image_buffer, width, height, channels, &image);
+
+ // Configure detector.
+ DetectOptions detector_options;
+ libmv_convertDetectorOptions(options, &detector_options);
+
+ // Run the detector.
+ libmv::vector<Feature> detected_features;
+ Detect(image, detector_options, &detected_features);
+
+ // Convert result to C-API.
+ libmv_Features* result = libmv_featuresFromVector(detected_features);
+ return result;
+}
+
+libmv_Features* libmv_detectFeaturesFloat(const float* image_buffer,
+ int width,
+ int height,
+ int channels,
+ libmv_DetectOptions* options) {
+ // Prepare the image.
+ FloatImage image;
+ libmv_floatBufferToFloatImage(image_buffer, width, height, channels, &image);
+
+ // Configure detector.
+ DetectOptions detector_options;
+ libmv_convertDetectorOptions(options, &detector_options);
+
+ // Run the detector.
+ libmv::vector<Feature> detected_features;
+ Detect(image, detector_options, &detected_features);
+
+ // Convert result to C-API.
+ libmv_Features* result = libmv_featuresFromVector(detected_features);
+ return result;
+}
+
+void libmv_featuresDestroy(libmv_Features* libmv_features) {
+ if (libmv_features->features) {
+ LIBMV_STRUCT_DELETE(libmv_features->features);
+ }
+ LIBMV_STRUCT_DELETE(libmv_features);
+}
+
+int libmv_countFeatures(const libmv_Features* libmv_features) {
+ return libmv_features->count;
+}
+
+void libmv_getFeature(const libmv_Features* libmv_features,
+ int number,
+ double* x,
+ double* y,
+ double* score,
+ double* size) {
+ Feature &feature = libmv_features->features[number];
+ *x = feature.x;
+ *y = feature.y;
+ *score = feature.score;
+ *size = feature.size;
+}
diff --git a/extern/libmv/intern/detector.h b/extern/libmv/intern/detector.h
new file mode 100644
index 00000000000..f72b0dd8d6e
--- /dev/null
+++ b/extern/libmv/intern/detector.h
@@ -0,0 +1,77 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef LIBMV_C_API_DETECTOR_H_
+#define LIBMV_C_API_DETECTOR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct libmv_Features libmv_Features;
+
+enum {
+ LIBMV_DETECTOR_FAST,
+ LIBMV_DETECTOR_MORAVEC,
+ LIBMV_DETECTOR_HARRIS,
+};
+
+typedef struct libmv_DetectOptions {
+ int detector;
+ int margin;
+ int min_distance;
+ int fast_min_trackness;
+ int moravec_max_count;
+ unsigned char *moravec_pattern;
+ double harris_threshold;
+} libmv_DetectOptions;
+
+libmv_Features* libmv_detectFeaturesByte(const unsigned char* image_buffer,
+ int width,
+ int height,
+ int channels,
+ libmv_DetectOptions* options);
+
+libmv_Features* libmv_detectFeaturesFloat(const float* image_buffer,
+ int width,
+ int height,
+ int channels,
+ libmv_DetectOptions* options);
+
+void libmv_featuresDestroy(libmv_Features* libmv_features);
+int libmv_countFeatures(const libmv_Features* libmv_features);
+void libmv_getFeature(const libmv_Features* libmv_features,
+ int number,
+ double* x,
+ double* y,
+ double* score,
+ double* size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LIBMV_C_API_DETECTOR_H_
diff --git a/extern/libmv/intern/homography.cc b/extern/libmv/intern/homography.cc
new file mode 100644
index 00000000000..6b61bd9ab42
--- /dev/null
+++ b/extern/libmv/intern/homography.cc
@@ -0,0 +1,59 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "intern/homography.h"
+#include "intern/utildefines.h"
+#include "libmv/logging/logging.h"
+#include "libmv/multiview/homography.h"
+
+void libmv_homography2DFromCorrespondencesEuc(/* const */ double (*x1)[2],
+ /* const */ double (*x2)[2],
+ int num_points,
+ double H[3][3]) {
+ libmv::Mat x1_mat, x2_mat;
+ libmv::Mat3 H_mat;
+
+ x1_mat.resize(2, num_points);
+ x2_mat.resize(2, num_points);
+
+ for (int i = 0; i < num_points; i++) {
+ x1_mat.col(i) = libmv::Vec2(x1[i][0], x1[i][1]);
+ x2_mat.col(i) = libmv::Vec2(x2[i][0], x2[i][1]);
+ }
+
+ LG << "x1: " << x1_mat;
+ LG << "x2: " << x2_mat;
+
+ libmv::EstimateHomographyOptions options;
+ libmv::EstimateHomography2DFromCorrespondences(x1_mat,
+ x2_mat,
+ options,
+ &H_mat);
+
+ LG << "H: " << H_mat;
+
+ memcpy(H, H_mat.data(), 9 * sizeof(double));
+}
diff --git a/extern/libmv/intern/homography.h b/extern/libmv/intern/homography.h
new file mode 100644
index 00000000000..175108e8171
--- /dev/null
+++ b/extern/libmv/intern/homography.h
@@ -0,0 +1,43 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef LIBMV_C_API_HOMOGRAPHY_H_
+#define LIBMV_C_API_HOMOGRAPHY_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void libmv_homography2DFromCorrespondencesEuc(/* const */ double (*x1)[2],
+ /* const */ double (*x2)[2],
+ int num_points,
+ double H[3][3]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LIBMV_C_API_HOMOGRAPHY_H_
diff --git a/extern/libmv/intern/image.cc b/extern/libmv/intern/image.cc
new file mode 100644
index 00000000000..7e623bdbec7
--- /dev/null
+++ b/extern/libmv/intern/image.cc
@@ -0,0 +1,272 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "intern/image.h"
+#include "intern/utildefines.h"
+#include "libmv/tracking/track_region.h"
+
+#include <cassert>
+#include <png.h>
+
+using libmv::FloatImage;
+using libmv::SamplePlanarPatch;
+
+void libmv_floatImaheDestroy(libmv_FloatImage *image) {
+ delete [] image->buffer;
+}
+
+/* Image <-> buffers conversion */
+
+void libmv_byteBufferToFloatImage(const unsigned char* buffer,
+ int width,
+ int height,
+ int channels,
+ FloatImage* image) {
+ image->Resize(height, width, channels);
+ for (int y = 0, a = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ for (int k = 0; k < channels; k++) {
+ (*image)(y, x, k) = (float)buffer[a++] / 255.0f;
+ }
+ }
+ }
+}
+
+void libmv_floatBufferToFloatImage(const float* buffer,
+ int width,
+ int height,
+ int channels,
+ FloatImage* image) {
+ image->Resize(height, width, channels);
+ for (int y = 0, a = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ for (int k = 0; k < channels; k++) {
+ (*image)(y, x, k) = buffer[a++];
+ }
+ }
+ }
+}
+
+void libmv_floatImageToFloatBuffer(const FloatImage &image,
+ float* buffer) {
+ for (int y = 0, a = 0; y < image.Height(); y++) {
+ for (int x = 0; x < image.Width(); x++) {
+ for (int k = 0; k < image.Depth(); k++) {
+ buffer[a++] = image(y, x, k);
+ }
+ }
+ }
+}
+
+void libmv_floatImageToByteBuffer(const libmv::FloatImage &image,
+ unsigned char* buffer) {
+ for (int y = 0, a= 0; y < image.Height(); y++) {
+ for (int x = 0; x < image.Width(); x++) {
+ for (int k = 0; k < image.Depth(); k++) {
+ buffer[a++] = image(y, x, k) * 255.0f;
+ }
+ }
+ }
+}
+
+static bool savePNGImage(png_bytep* row_pointers,
+ int width,
+ int height,
+ int depth,
+ int color_type,
+ const char* file_name) {
+ png_infop info_ptr;
+ png_structp png_ptr;
+ FILE *fp = fopen(file_name, "wb");
+
+ if (fp == NULL) {
+ return false;
+ }
+
+ /* Initialize stuff */
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ info_ptr = png_create_info_struct(png_ptr);
+
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ fclose(fp);
+ return false;
+ }
+
+ png_init_io(png_ptr, fp);
+
+ /* Write PNG header. */
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ fclose(fp);
+ return false;
+ }
+
+ png_set_IHDR(png_ptr,
+ info_ptr,
+ width,
+ height,
+ depth,
+ color_type,
+ PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE,
+ PNG_FILTER_TYPE_BASE);
+
+ png_write_info(png_ptr, info_ptr);
+
+ /* Write bytes/ */
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ fclose(fp);
+ return false;
+ }
+
+ png_write_image(png_ptr, row_pointers);
+
+ /* End write/ */
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ fclose(fp);
+ return false;
+ }
+
+ png_write_end(png_ptr, NULL);
+ fclose(fp);
+
+ return true;
+}
+
+bool libmv_saveImage(const FloatImage& image,
+ const char* prefix,
+ int x0,
+ int y0) {
+ int x, y;
+ png_bytep *row_pointers;
+
+ assert(image.Depth() == 1);
+
+ row_pointers = new png_bytep[image.Height()];
+
+ for (y = 0; y < image.Height(); y++) {
+ row_pointers[y] = new png_byte[4 * image.Width()];
+
+ for (x = 0; x < image.Width(); x++) {
+ if (x0 == x && image.Height() - y0 - 1 == y) {
+ row_pointers[y][x * 4 + 0] = 255;
+ row_pointers[y][x * 4 + 1] = 0;
+ row_pointers[y][x * 4 + 2] = 0;
+ row_pointers[y][x * 4 + 3] = 255;
+ } else {
+ float pixel = image(image.Height() - y - 1, x, 0);
+ row_pointers[y][x * 4 + 0] = pixel * 255;
+ row_pointers[y][x * 4 + 1] = pixel * 255;
+ row_pointers[y][x * 4 + 2] = pixel * 255;
+ row_pointers[y][x * 4 + 3] = 255;
+ }
+ }
+ }
+
+ static int image_counter = 0;
+ char file_name[128];
+ snprintf(file_name, sizeof(file_name),
+ "%s_%02d.png",
+ prefix, ++image_counter);
+ bool result = savePNGImage(row_pointers,
+ image.Width(),
+ image.Height(),
+ 8,
+ PNG_COLOR_TYPE_RGBA,
+ file_name);
+
+ for (y = 0; y < image.Height(); y++) {
+ delete [] row_pointers[y];
+ }
+ delete [] row_pointers;
+
+ return result;
+}
+
+void libmv_samplePlanarPatchFloat(const float* image,
+ int width,
+ int height,
+ int channels,
+ const double* xs,
+ const double* ys,
+ int num_samples_x,
+ int num_samples_y,
+ const float* mask,
+ float* patch,
+ double* warped_position_x,
+ double* warped_position_y) {
+ FloatImage libmv_image, libmv_patch, libmv_mask;
+ FloatImage *libmv_mask_for_sample = NULL;
+
+ libmv_floatBufferToFloatImage(image, width, height, channels, &libmv_image);
+
+ if (mask) {
+ libmv_floatBufferToFloatImage(mask, width, height, 1, &libmv_mask);
+ libmv_mask_for_sample = &libmv_mask;
+ }
+
+ SamplePlanarPatch(libmv_image,
+ xs, ys,
+ num_samples_x, num_samples_y,
+ libmv_mask_for_sample,
+ &libmv_patch,
+ warped_position_x,
+ warped_position_y);
+
+ libmv_floatImageToFloatBuffer(libmv_patch, patch);
+}
+
+ void libmv_samplePlanarPatchByte(const unsigned char* image,
+ int width,
+ int height,
+ int channels,
+ const double* xs,
+ const double* ys,
+ int num_samples_x,
+ int num_samples_y,
+ const float* mask,
+ unsigned char* patch,
+ double* warped_position_x,
+ double* warped_position_y) {
+ libmv::FloatImage libmv_image, libmv_patch, libmv_mask;
+ libmv::FloatImage *libmv_mask_for_sample = NULL;
+
+ libmv_byteBufferToFloatImage(image, width, height, channels, &libmv_image);
+
+ if (mask) {
+ libmv_floatBufferToFloatImage(mask, width, height, 1, &libmv_mask);
+ libmv_mask_for_sample = &libmv_mask;
+ }
+
+ libmv::SamplePlanarPatch(libmv_image,
+ xs, ys,
+ num_samples_x, num_samples_y,
+ libmv_mask_for_sample,
+ &libmv_patch,
+ warped_position_x,
+ warped_position_y);
+
+ libmv_floatImageToByteBuffer(libmv_patch, patch);
+}
diff --git a/extern/libmv/intern/image.h b/extern/libmv/intern/image.h
new file mode 100644
index 00000000000..9936e748b9d
--- /dev/null
+++ b/extern/libmv/intern/image.h
@@ -0,0 +1,99 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef LIBMV_IMAGE_H_
+#define LIBMV_IMAGE_H_
+
+#ifdef __cplusplus
+# include "libmv/image/image.h"
+void libmv_byteBufferToFloatImage(const unsigned char* buffer,
+ int width,
+ int height,
+ int channels,
+ libmv::FloatImage* image);
+
+void libmv_floatBufferToFloatImage(const float* buffer,
+ int width,
+ int height,
+ int channels,
+ libmv::FloatImage* image);
+
+void libmv_floatImageToFloatBuffer(const libmv::FloatImage& image,
+ float *buffer);
+
+void libmv_floatImageToByteBuffer(const libmv::FloatImage& image,
+ unsigned char* buffer);
+
+bool libmv_saveImage(const libmv::FloatImage& image,
+ const char* prefix,
+ int x0,
+ int y0);
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct libmv_FloatImage {
+ float *buffer;
+ int width;
+ int height;
+ int channels;
+} libmv_FloatImage;
+
+void libmv_floatImaheDestroy(libmv_FloatImage *image);
+
+void libmv_samplePlanarPatchFloat(const float* image,
+ int width,
+ int height,
+ int channels,
+ const double* xs,
+ const double* ys,
+ int num_samples_x,
+ int num_samples_y,
+ const float* mask,
+ float* patch,
+ double* warped_position_x,
+ double* warped_position_y);
+
+ void libmv_samplePlanarPatchByte(const unsigned char* image,
+ int width,
+ int height,
+ int channels,
+ const double* xs,
+ const double* ys,
+ int num_samples_x,
+ int num_samples_y,
+ const float* mask,
+ unsigned char* patch,
+ double* warped_position_x,
+ double* warped_position_y);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LIBMV_IMAGE_H_
diff --git a/extern/libmv/intern/logging.cc b/extern/libmv/intern/logging.cc
new file mode 100644
index 00000000000..4ab2d91c8b4
--- /dev/null
+++ b/extern/libmv/intern/logging.cc
@@ -0,0 +1,55 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "intern/logging.h"
+#include "intern/utildefines.h"
+#include "libmv/logging/logging.h"
+
+void libmv_initLogging(const char* argv0) {
+ // Make it so FATAL messages are always print into console.
+ char severity_fatal[32];
+ snprintf(severity_fatal, sizeof(severity_fatal), "%d",
+ google::GLOG_FATAL);
+
+ google::InitGoogleLogging(argv0);
+ google::SetCommandLineOption("logtostderr", "1");
+ google::SetCommandLineOption("v", "0");
+ google::SetCommandLineOption("stderrthreshold", severity_fatal);
+ google::SetCommandLineOption("minloglevel", severity_fatal);
+}
+
+void libmv_startDebugLogging(void) {
+ google::SetCommandLineOption("logtostderr", "1");
+ google::SetCommandLineOption("v", "2");
+ google::SetCommandLineOption("stderrthreshold", "1");
+ google::SetCommandLineOption("minloglevel", "0");
+}
+
+void libmv_setLoggingVerbosity(int verbosity) {
+ char val[10];
+ snprintf(val, sizeof(val), "%d", verbosity);
+ google::SetCommandLineOption("v", val);
+}
diff --git a/extern/libmv/intern/logging.h b/extern/libmv/intern/logging.h
new file mode 100644
index 00000000000..479ed3d6288
--- /dev/null
+++ b/extern/libmv/intern/logging.h
@@ -0,0 +1,47 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef LIBMV_C_API_LOGGING_H_
+#define LIBMV_C_API_LOGGING_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Initialize GLog logging.
+void libmv_initLogging(const char* argv0);
+
+// Switch Glog to debug logging level.
+void libmv_startDebugLogging(void);
+
+// Set GLog logging verbosity level.
+void libmv_setLoggingVerbosity(int verbosity);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LIBMV_C_API_LOGGING_H_
diff --git a/extern/libmv/intern/reconstruction.cc b/extern/libmv/intern/reconstruction.cc
new file mode 100644
index 00000000000..eb3677fd206
--- /dev/null
+++ b/extern/libmv/intern/reconstruction.cc
@@ -0,0 +1,530 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "intern/reconstruction.h"
+#include "intern/camera_intrinsics.h"
+#include "intern/tracks.h"
+#include "intern/utildefines.h"
+
+#include "libmv/logging/logging.h"
+#include "libmv/simple_pipeline/bundle.h"
+#include "libmv/simple_pipeline/keyframe_selection.h"
+#include "libmv/simple_pipeline/initialize_reconstruction.h"
+#include "libmv/simple_pipeline/modal_solver.h"
+#include "libmv/simple_pipeline/pipeline.h"
+#include "libmv/simple_pipeline/reconstruction_scale.h"
+#include "libmv/simple_pipeline/tracks.h"
+
+using libmv::CameraIntrinsics;
+using libmv::EuclideanCamera;
+using libmv::EuclideanPoint;
+using libmv::EuclideanReconstruction;
+using libmv::EuclideanScaleToUnity;
+using libmv::Marker;
+using libmv::ProgressUpdateCallback;
+
+using libmv::PolynomialCameraIntrinsics;
+using libmv::Tracks;
+using libmv::EuclideanBundle;
+using libmv::EuclideanCompleteReconstruction;
+using libmv::EuclideanReconstructTwoFrames;
+using libmv::EuclideanReprojectionError;
+
+struct libmv_Reconstruction {
+ EuclideanReconstruction reconstruction;
+
+ /* Used for per-track average error calculation after reconstruction */
+ Tracks tracks;
+ CameraIntrinsics *intrinsics;
+
+ double error;
+};
+
+namespace {
+
+class ReconstructUpdateCallback : public ProgressUpdateCallback {
+ public:
+ ReconstructUpdateCallback(
+ reconstruct_progress_update_cb progress_update_callback,
+ void *callback_customdata) {
+ progress_update_callback_ = progress_update_callback;
+ callback_customdata_ = callback_customdata;
+ }
+
+ void invoke(double progress, const char* message) {
+ if (progress_update_callback_) {
+ progress_update_callback_(callback_customdata_, progress, message);
+ }
+ }
+ protected:
+ reconstruct_progress_update_cb progress_update_callback_;
+ void* callback_customdata_;
+};
+
+void libmv_solveRefineIntrinsics(
+ const Tracks &tracks,
+ const int refine_intrinsics,
+ const int bundle_constraints,
+ reconstruct_progress_update_cb progress_update_callback,
+ void* callback_customdata,
+ EuclideanReconstruction* reconstruction,
+ CameraIntrinsics* intrinsics) {
+ /* only a few combinations are supported but trust the caller/ */
+ int bundle_intrinsics = 0;
+
+ if (refine_intrinsics & LIBMV_REFINE_FOCAL_LENGTH) {
+ bundle_intrinsics |= libmv::BUNDLE_FOCAL_LENGTH;
+ }
+ if (refine_intrinsics & LIBMV_REFINE_PRINCIPAL_POINT) {
+ bundle_intrinsics |= libmv::BUNDLE_PRINCIPAL_POINT;
+ }
+ if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K1) {
+ bundle_intrinsics |= libmv::BUNDLE_RADIAL_K1;
+ }
+ if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K2) {
+ bundle_intrinsics |= libmv::BUNDLE_RADIAL_K2;
+ }
+
+ progress_update_callback(callback_customdata, 1.0, "Refining solution");
+
+ EuclideanBundleCommonIntrinsics(tracks,
+ bundle_intrinsics,
+ bundle_constraints,
+ reconstruction,
+ intrinsics);
+}
+
+void finishReconstruction(
+ const Tracks &tracks,
+ const CameraIntrinsics &camera_intrinsics,
+ libmv_Reconstruction *libmv_reconstruction,
+ reconstruct_progress_update_cb progress_update_callback,
+ void *callback_customdata) {
+ EuclideanReconstruction &reconstruction =
+ libmv_reconstruction->reconstruction;
+
+ /* Reprojection error calculation. */
+ progress_update_callback(callback_customdata, 1.0, "Finishing solution");
+ libmv_reconstruction->tracks = tracks;
+ libmv_reconstruction->error = EuclideanReprojectionError(tracks,
+ reconstruction,
+ camera_intrinsics);
+}
+
+bool selectTwoKeyframesBasedOnGRICAndVariance(
+ Tracks& tracks,
+ Tracks& normalized_tracks,
+ CameraIntrinsics& camera_intrinsics,
+ int& keyframe1,
+ int& keyframe2) {
+ libmv::vector<int> keyframes;
+
+ /* Get list of all keyframe candidates first. */
+ SelectKeyframesBasedOnGRICAndVariance(normalized_tracks,
+ camera_intrinsics,
+ keyframes);
+
+ if (keyframes.size() < 2) {
+ LG << "Not enough keyframes detected by GRIC";
+ return false;
+ } else if (keyframes.size() == 2) {
+ keyframe1 = keyframes[0];
+ keyframe2 = keyframes[1];
+ return true;
+ }
+
+ /* Now choose two keyframes with minimal reprojection error after initial
+ * reconstruction choose keyframes with the least reprojection error after
+ * solving from two candidate keyframes.
+ *
+ * In fact, currently libmv returns single pair only, so this code will
+ * not actually run. But in the future this could change, so let's stay
+ * prepared.
+ */
+ int previous_keyframe = keyframes[0];
+ double best_error = std::numeric_limits<double>::max();
+ for (int i = 1; i < keyframes.size(); i++) {
+ EuclideanReconstruction reconstruction;
+ int current_keyframe = keyframes[i];
+ libmv::vector<Marker> keyframe_markers =
+ normalized_tracks.MarkersForTracksInBothImages(previous_keyframe,
+ current_keyframe);
+
+ Tracks keyframe_tracks(keyframe_markers);
+
+ /* get a solution from two keyframes only */
+ EuclideanReconstructTwoFrames(keyframe_markers, &reconstruction);
+ EuclideanBundle(keyframe_tracks, &reconstruction);
+ EuclideanCompleteReconstruction(keyframe_tracks,
+ &reconstruction,
+ NULL);
+
+ double current_error = EuclideanReprojectionError(tracks,
+ reconstruction,
+ camera_intrinsics);
+
+ LG << "Error between " << previous_keyframe
+ << " and " << current_keyframe
+ << ": " << current_error;
+
+ if (current_error < best_error) {
+ best_error = current_error;
+ keyframe1 = previous_keyframe;
+ keyframe2 = current_keyframe;
+ }
+
+ previous_keyframe = current_keyframe;
+ }
+
+ return true;
+}
+
+Marker libmv_projectMarker(const EuclideanPoint& point,
+ const EuclideanCamera& camera,
+ const CameraIntrinsics& intrinsics) {
+ libmv::Vec3 projected = camera.R * point.X + camera.t;
+ projected /= projected(2);
+
+ libmv::Marker reprojected_marker;
+ intrinsics.ApplyIntrinsics(projected(0), projected(1),
+ &reprojected_marker.x,
+ &reprojected_marker.y);
+
+ reprojected_marker.image = camera.image;
+ reprojected_marker.track = point.track;
+ return reprojected_marker;
+}
+
+void libmv_getNormalizedTracks(const Tracks &tracks,
+ const CameraIntrinsics &camera_intrinsics,
+ Tracks *normalized_tracks)
+{
+ libmv::vector<Marker> markers = tracks.AllMarkers();
+ for (int i = 0; i < markers.size(); ++i) {
+ Marker &marker = markers[i];
+ camera_intrinsics.InvertIntrinsics(marker.x, marker.y,
+ &marker.x, &marker.y);
+ normalized_tracks->Insert(marker.image,
+ marker.track,
+ marker.x, marker.y,
+ marker.weight);
+ }
+}
+
+} // namespace
+
+libmv_Reconstruction *libmv_solveReconstruction(
+ const libmv_Tracks* libmv_tracks,
+ const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
+ libmv_ReconstructionOptions* libmv_reconstruction_options,
+ reconstruct_progress_update_cb progress_update_callback,
+ void* callback_customdata) {
+ libmv_Reconstruction *libmv_reconstruction =
+ LIBMV_OBJECT_NEW(libmv_Reconstruction);
+
+ Tracks &tracks = *((Tracks *) libmv_tracks);
+ EuclideanReconstruction &reconstruction =
+ libmv_reconstruction->reconstruction;
+
+ ReconstructUpdateCallback update_callback =
+ ReconstructUpdateCallback(progress_update_callback,
+ callback_customdata);
+
+ /* Retrieve reconstruction options from C-API to libmv API. */
+ CameraIntrinsics *camera_intrinsics;
+ camera_intrinsics = libmv_reconstruction->intrinsics =
+ libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options);
+
+ /* Invert the camera intrinsics/ */
+ Tracks normalized_tracks;
+ libmv_getNormalizedTracks(tracks, *camera_intrinsics, &normalized_tracks);
+
+ /* keyframe selection. */
+ int keyframe1 = libmv_reconstruction_options->keyframe1,
+ keyframe2 = libmv_reconstruction_options->keyframe2;
+
+ if (libmv_reconstruction_options->select_keyframes) {
+ LG << "Using automatic keyframe selection";
+
+ update_callback.invoke(0, "Selecting keyframes");
+
+ selectTwoKeyframesBasedOnGRICAndVariance(tracks,
+ normalized_tracks,
+ *camera_intrinsics,
+ keyframe1,
+ keyframe2);
+
+ /* so keyframes in the interface would be updated */
+ libmv_reconstruction_options->keyframe1 = keyframe1;
+ libmv_reconstruction_options->keyframe2 = keyframe2;
+ }
+
+ /* Actual reconstruction. */
+ LG << "frames to init from: " << keyframe1 << " " << keyframe2;
+
+ libmv::vector<Marker> keyframe_markers =
+ normalized_tracks.MarkersForTracksInBothImages(keyframe1, keyframe2);
+
+ LG << "number of markers for init: " << keyframe_markers.size();
+
+ update_callback.invoke(0, "Initial reconstruction");
+
+ EuclideanReconstructTwoFrames(keyframe_markers, &reconstruction);
+ EuclideanBundle(normalized_tracks, &reconstruction);
+ EuclideanCompleteReconstruction(normalized_tracks,
+ &reconstruction,
+ &update_callback);
+
+ /* Refinement/ */
+ if (libmv_reconstruction_options->refine_intrinsics) {
+ libmv_solveRefineIntrinsics(
+ tracks,
+ libmv_reconstruction_options->refine_intrinsics,
+ libmv::BUNDLE_NO_CONSTRAINTS,
+ progress_update_callback,
+ callback_customdata,
+ &reconstruction,
+ camera_intrinsics);
+ }
+
+ /* Set reconstruction scale to unity. */
+ EuclideanScaleToUnity(&reconstruction);
+
+ /* Finish reconstruction. */
+ finishReconstruction(tracks,
+ *camera_intrinsics,
+ libmv_reconstruction,
+ progress_update_callback,
+ callback_customdata);
+
+ return (libmv_Reconstruction *) libmv_reconstruction;
+}
+
+libmv_Reconstruction *libmv_solveModal(
+ const libmv_Tracks *libmv_tracks,
+ const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options,
+ const libmv_ReconstructionOptions *libmv_reconstruction_options,
+ reconstruct_progress_update_cb progress_update_callback,
+ void *callback_customdata) {
+ libmv_Reconstruction *libmv_reconstruction =
+ LIBMV_OBJECT_NEW(libmv_Reconstruction);
+
+ Tracks &tracks = *((Tracks *) libmv_tracks);
+ EuclideanReconstruction &reconstruction =
+ libmv_reconstruction->reconstruction;
+
+ ReconstructUpdateCallback update_callback =
+ ReconstructUpdateCallback(progress_update_callback,
+ callback_customdata);
+
+ /* Retrieve reconstruction options from C-API to libmv API. */
+ CameraIntrinsics *camera_intrinsics;
+ camera_intrinsics = libmv_reconstruction->intrinsics =
+ libmv_cameraIntrinsicsCreateFromOptions(
+ libmv_camera_intrinsics_options);
+
+ /* Invert the camera intrinsics. */
+ Tracks normalized_tracks;
+ libmv_getNormalizedTracks(tracks, *camera_intrinsics, &normalized_tracks);
+
+ /* Actual reconstruction. */
+ ModalSolver(normalized_tracks, &reconstruction, &update_callback);
+
+ PolynomialCameraIntrinsics empty_intrinsics;
+ EuclideanBundleCommonIntrinsics(normalized_tracks,
+ libmv::BUNDLE_NO_INTRINSICS,
+ libmv::BUNDLE_NO_TRANSLATION,
+ &reconstruction,
+ &empty_intrinsics);
+
+ /* Refinement. */
+ if (libmv_reconstruction_options->refine_intrinsics) {
+ libmv_solveRefineIntrinsics(
+ tracks,
+ libmv_reconstruction_options->refine_intrinsics,
+ libmv::BUNDLE_NO_TRANSLATION,
+ progress_update_callback, callback_customdata,
+ &reconstruction,
+ camera_intrinsics);
+ }
+
+ /* Finish reconstruction. */
+ finishReconstruction(tracks,
+ *camera_intrinsics,
+ libmv_reconstruction,
+ progress_update_callback,
+ callback_customdata);
+
+ return (libmv_Reconstruction *) libmv_reconstruction;
+}
+
+void libmv_reconstructionDestroy(libmv_Reconstruction *libmv_reconstruction) {
+ LIBMV_OBJECT_DELETE(libmv_reconstruction->intrinsics, CameraIntrinsics);
+ LIBMV_OBJECT_DELETE(libmv_reconstruction, libmv_Reconstruction);
+}
+
+int libmv_reprojectionPointForTrack(
+ const libmv_Reconstruction *libmv_reconstruction,
+ int track,
+ double pos[3]) {
+ const EuclideanReconstruction *reconstruction =
+ &libmv_reconstruction->reconstruction;
+ const EuclideanPoint *point =
+ reconstruction->PointForTrack(track);
+ if (point) {
+ pos[0] = point->X[0];
+ pos[1] = point->X[2];
+ pos[2] = point->X[1];
+ return 1;
+ }
+ return 0;
+}
+
+double libmv_reprojectionErrorForTrack(
+ const libmv_Reconstruction *libmv_reconstruction,
+ int track) {
+ const EuclideanReconstruction *reconstruction =
+ &libmv_reconstruction->reconstruction;
+ const CameraIntrinsics *intrinsics = libmv_reconstruction->intrinsics;
+ libmv::vector<Marker> markers =
+ libmv_reconstruction->tracks.MarkersForTrack(track);
+
+ int num_reprojected = 0;
+ double total_error = 0.0;
+
+ for (int i = 0; i < markers.size(); ++i) {
+ double weight = markers[i].weight;
+ const EuclideanCamera *camera =
+ reconstruction->CameraForImage(markers[i].image);
+ const EuclideanPoint *point =
+ reconstruction->PointForTrack(markers[i].track);
+
+ if (!camera || !point || weight == 0.0) {
+ continue;
+ }
+
+ num_reprojected++;
+
+ Marker reprojected_marker =
+ libmv_projectMarker(*point, *camera, *intrinsics);
+ double ex = (reprojected_marker.x - markers[i].x) * weight;
+ double ey = (reprojected_marker.y - markers[i].y) * weight;
+
+ total_error += sqrt(ex * ex + ey * ey);
+ }
+
+ return total_error / num_reprojected;
+}
+
+double libmv_reprojectionErrorForImage(
+ const libmv_Reconstruction *libmv_reconstruction,
+ int image) {
+ const EuclideanReconstruction *reconstruction =
+ &libmv_reconstruction->reconstruction;
+ const CameraIntrinsics *intrinsics = libmv_reconstruction->intrinsics;
+ libmv::vector<Marker> markers =
+ libmv_reconstruction->tracks.MarkersInImage(image);
+ const EuclideanCamera *camera = reconstruction->CameraForImage(image);
+ int num_reprojected = 0;
+ double total_error = 0.0;
+
+ if (!camera) {
+ return 0.0;
+ }
+
+ for (int i = 0; i < markers.size(); ++i) {
+ const EuclideanPoint *point =
+ reconstruction->PointForTrack(markers[i].track);
+
+ if (!point) {
+ continue;
+ }
+
+ num_reprojected++;
+
+ Marker reprojected_marker =
+ libmv_projectMarker(*point, *camera, *intrinsics);
+ double ex = (reprojected_marker.x - markers[i].x) * markers[i].weight;
+ double ey = (reprojected_marker.y - markers[i].y) * markers[i].weight;
+
+ total_error += sqrt(ex * ex + ey * ey);
+ }
+
+ return total_error / num_reprojected;
+}
+
+int libmv_reprojectionCameraForImage(
+ const libmv_Reconstruction *libmv_reconstruction,
+ int image,
+ double mat[4][4]) {
+ const EuclideanReconstruction *reconstruction =
+ &libmv_reconstruction->reconstruction;
+ const EuclideanCamera *camera =
+ reconstruction->CameraForImage(image);
+
+ if (camera) {
+ for (int j = 0; j < 3; ++j) {
+ for (int k = 0; k < 3; ++k) {
+ int l = k;
+
+ if (k == 1) {
+ l = 2;
+ } else if (k == 2) {
+ l = 1;
+ }
+
+ if (j == 2) {
+ mat[j][l] = -camera->R(j, k);
+ } else {
+ mat[j][l] = camera->R(j, k);
+ }
+ }
+ mat[j][3] = 0.0;
+ }
+
+ libmv::Vec3 optical_center = -camera->R.transpose() * camera->t;
+
+ mat[3][0] = optical_center(0);
+ mat[3][1] = optical_center(2);
+ mat[3][2] = optical_center(1);
+
+ mat[3][3] = 1.0;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+double libmv_reprojectionError(
+ const libmv_Reconstruction *libmv_reconstruction) {
+ return libmv_reconstruction->error;
+}
+
+libmv_CameraIntrinsics *libmv_reconstructionExtractIntrinsics(
+ libmv_Reconstruction *libmv_reconstruction) {
+ return (libmv_CameraIntrinsics *) libmv_reconstruction->intrinsics;
+}
diff --git a/extern/libmv/intern/reconstruction.h b/extern/libmv/intern/reconstruction.h
new file mode 100644
index 00000000000..744f4bafb0b
--- /dev/null
+++ b/extern/libmv/intern/reconstruction.h
@@ -0,0 +1,99 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef LIBMV_C_API_RECONSTRUCTION_H_
+#define LIBMV_C_API_RECONSTRUCTION_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct libmv_CameraIntrinsics libmv_CameraIntrinsics;
+typedef struct libmv_CameraIntrinsicsOptions libmv_CameraIntrinsicsOptions;
+typedef struct libmv_Reconstruction libmv_Reconstruction;
+typedef struct libmv_Tracks libmv_Tracks;
+
+enum {
+ LIBMV_REFINE_FOCAL_LENGTH = (1 << 0),
+ LIBMV_REFINE_PRINCIPAL_POINT = (1 << 1),
+ LIBMV_REFINE_RADIAL_DISTORTION_K1 = (1 << 2),
+ LIBMV_REFINE_RADIAL_DISTORTION_K2 = (1 << 4),
+};
+
+typedef struct libmv_ReconstructionOptions {
+ int select_keyframes;
+ int keyframe1, keyframe2;
+ int refine_intrinsics;
+} libmv_ReconstructionOptions;
+
+typedef void (*reconstruct_progress_update_cb) (void* customdata,
+ double progress,
+ const char* message);
+
+libmv_Reconstruction* libmv_solveReconstruction(
+ const libmv_Tracks* libmv_tracks,
+ const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
+ libmv_ReconstructionOptions* libmv_reconstruction_options,
+ reconstruct_progress_update_cb progress_update_callback,
+ void* callback_customdata);
+
+libmv_Reconstruction* libmv_solveModal(
+ const libmv_Tracks* libmv_tracks,
+ const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
+ const libmv_ReconstructionOptions* libmv_reconstruction_options,
+ reconstruct_progress_update_cb progress_update_callback,
+ void* callback_customdata);
+
+void libmv_reconstructionDestroy(libmv_Reconstruction* libmv_reconstruction);
+
+int libmv_reprojectionPointForTrack(
+ const libmv_Reconstruction* libmv_reconstruction,
+ int track,
+ double pos[3]);
+
+double libmv_reprojectionErrorForTrack(
+ const libmv_Reconstruction* libmv_reconstruction,
+ int track);
+
+double libmv_reprojectionErrorForImage(
+ const libmv_Reconstruction* libmv_reconstruction,
+ int image);
+
+int libmv_reprojectionCameraForImage(
+ const libmv_Reconstruction* libmv_reconstruction,
+ int image,
+ double mat[4][4]);
+
+double libmv_reprojectionError(const libmv_Reconstruction* libmv_reconstruction);
+
+libmv_CameraIntrinsics* libmv_reconstructionExtractIntrinsics(
+ libmv_Reconstruction *libmv_Reconstruction);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LIBMV_C_API_RECONSTRUCTION_H_
diff --git a/extern/libmv/intern/region.h b/extern/libmv/intern/region.h
new file mode 100644
index 00000000000..9f114bbad3b
--- /dev/null
+++ b/extern/libmv/intern/region.h
@@ -0,0 +1,43 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef LIBMV_C_API_REGION_H_
+#define LIBMV_C_API_REGION_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct libmv_Region {
+ float min[2];
+ float max[2];
+} libmv_Region;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LIBMV_C_API_REGION_H_
diff --git a/extern/libmv/intern/stub.cc b/extern/libmv/intern/stub.cc
new file mode 100644
index 00000000000..cd8bb8ab841
--- /dev/null
+++ b/extern/libmv/intern/stub.cc
@@ -0,0 +1,330 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "libmv-capi.h"
+
+#include <cstdlib>
+#include <cstring>
+
+/* ************ Logging ************ */
+
+void libmv_initLogging(const char * /*argv0*/) {
+}
+
+void libmv_startDebugLogging(void) {
+}
+
+void libmv_setLoggingVerbosity(int /*verbosity*/) {
+}
+
+/* ************ Planar tracker ************ */
+
+/* TrackRegion (new planar tracker) */
+int libmv_trackRegion(const libmv_TrackRegionOptions * /*options*/,
+ const float * /*image1*/,
+ int /*image1_width*/,
+ int /*image1_height*/,
+ const float * /*image2*/,
+ int /*image2_width*/,
+ int /*image2_height*/,
+ const double *x1,
+ const double *y1,
+ libmv_TrackRegionResult *result,
+ double *x2,
+ double *y2) {
+ /* Convert to doubles for the libmv api. The four corners and the center. */
+ for (int i = 0; i < 5; ++i) {
+ x2[i] = x1[i];
+ y2[i] = y1[i];
+ }
+
+ result->termination = -1;
+ result->termination_reason = "Built without libmv support";
+ result->correlation = 0.0;
+
+ return false;
+}
+
+void libmv_samplePlanarPatchFloat(const float * /*image*/,
+ int /*width*/,
+ int /*height*/,
+ int /*channels*/,
+ const double * /*xs*/,
+ const double * /*ys*/,
+ int /*num_samples_x*/,
+ int /*num_samples_y*/,
+ const float * /*mask*/,
+ float * /*patch*/,
+ double * /*warped_position_x*/,
+ double * /*warped_position_y*/) {
+ /* TODO(sergey): implement */
+}
+
+void libmv_samplePlanarPatchByte(const unsigned char * /*image*/,
+ int /*width*/,
+ int /*height*/,
+ int /*channels*/,
+ const double * /*xs*/,
+ const double * /*ys*/,
+ int /*num_samples_x*/, int /*num_samples_y*/,
+ const float * /*mask*/,
+ unsigned char * /*patch*/,
+ double * /*warped_position_x*/,
+ double * /*warped_position_y*/) {
+ /* TODO(sergey): implement */
+}
+
+/* ************ Tracks ************ */
+
+libmv_Tracks *libmv_tracksNew(void) {
+ return NULL;
+}
+
+void libmv_tracksInsert(libmv_Tracks * /*libmv_tracks*/,
+ int /*image*/,
+ int /*track*/,
+ double /*x*/,
+ double /*y*/,
+ double /*weight*/) {
+}
+
+void libmv_tracksDestroy(libmv_Tracks * /*libmv_tracks*/) {
+}
+
+/* ************ Reconstruction solver ************ */
+
+libmv_Reconstruction *libmv_solveReconstruction(
+ const libmv_Tracks * /*libmv_tracks*/,
+ const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/,
+ libmv_ReconstructionOptions * /*libmv_reconstruction_options*/,
+ reconstruct_progress_update_cb /*progress_update_callback*/,
+ void * /*callback_customdata*/) {
+ return NULL;
+}
+
+libmv_Reconstruction *libmv_solveModal(
+ const libmv_Tracks * /*libmv_tracks*/,
+ const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/,
+ const libmv_ReconstructionOptions * /*libmv_reconstruction_options*/,
+ reconstruct_progress_update_cb /*progress_update_callback*/,
+ void * /*callback_customdata*/) {
+ return NULL;
+}
+
+int libmv_reprojectionPointForTrack(
+ const libmv_Reconstruction * /*libmv_reconstruction*/,
+ int /*track*/,
+ double /*pos*/[3]) {
+ return 0;
+}
+
+double libmv_reprojectionErrorForTrack(
+ const libmv_Reconstruction * /*libmv_reconstruction*/,
+ int /*track*/) {
+ return 0.0;
+}
+
+double libmv_reprojectionErrorForImage(
+ const libmv_Reconstruction * /*libmv_reconstruction*/,
+ int /*image*/) {
+ return 0.0;
+}
+
+int libmv_reprojectionCameraForImage(
+ const libmv_Reconstruction * /*libmv_reconstruction*/,
+ int /*image*/,
+ double /*mat*/[4][4]) {
+ return 0;
+}
+
+double libmv_reprojectionError(
+ const libmv_Reconstruction * /*libmv_reconstruction*/) {
+ return 0.0;
+}
+
+void libmv_reconstructionDestroy(
+ struct libmv_Reconstruction * /*libmv_reconstruction*/) {
+}
+
+/* ************ Feature detector ************ */
+
+libmv_Features *libmv_detectFeaturesByte(const unsigned char */*image_buffer*/,
+ int /*width*/,
+ int /*height*/,
+ int /*channels*/,
+ libmv_DetectOptions */*options*/) {
+ return NULL;
+}
+
+struct libmv_Features *libmv_detectFeaturesFloat(
+ const float */*image_buffer*/,
+ int /*width*/,
+ int /*height*/,
+ int /*channels*/,
+ libmv_DetectOptions */*options*/) {
+ return NULL;
+}
+
+int libmv_countFeatures(const libmv_Features * /*libmv_features*/) {
+ return 0;
+}
+
+void libmv_getFeature(const libmv_Features * /*libmv_features*/,
+ int /*number*/,
+ double *x,
+ double *y,
+ double *score,
+ double *size) {
+ *x = 0.0;
+ *y = 0.0;
+ *score = 0.0;
+ *size = 0.0;
+}
+
+void libmv_featuresDestroy(struct libmv_Features * /*libmv_features*/) {
+}
+
+/* ************ Camera intrinsics ************ */
+
+libmv_CameraIntrinsics *libmv_reconstructionExtractIntrinsics(
+ libmv_Reconstruction * /*libmv_reconstruction*/) {
+ return NULL;
+}
+
+libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew(
+ const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/) {
+ return NULL;
+}
+
+libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy(
+ const libmv_CameraIntrinsics * /*libmvIntrinsics*/) {
+ return NULL;
+}
+
+void libmv_cameraIntrinsicsDestroy(
+ libmv_CameraIntrinsics * /*libmvIntrinsics*/) {
+}
+
+void libmv_cameraIntrinsicsUpdate(
+ const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/,
+ libmv_CameraIntrinsics * /*libmv_intrinsics*/) {
+}
+
+void libmv_cameraIntrinsicsSetThreads(
+ libmv_CameraIntrinsics * /*libmv_intrinsics*/,
+ int /*threads*/) {
+}
+
+void libmv_cameraIntrinsicsExtractOptions(
+ const libmv_CameraIntrinsics */*libmv_intrinsics*/,
+ libmv_CameraIntrinsicsOptions *camera_intrinsics_options) {
+ memset(camera_intrinsics_options, 0, sizeof(libmv_CameraIntrinsicsOptions));
+ camera_intrinsics_options->focal_length = 1.0;
+}
+
+void libmv_cameraIntrinsicsUndistortByte(
+ const libmv_CameraIntrinsics * /*libmv_intrinsics*/,
+ const unsigned char *source_image,
+ int width, int height,
+ float overscan, int channels,
+ unsigned char *destination_image) {
+ memcpy(destination_image, source_image,
+ channels * width * height * sizeof(unsigned char));
+}
+
+void libmv_cameraIntrinsicsUndistortFloat(
+ const libmv_CameraIntrinsics* /*libmv_intrinsics*/,
+ const float* source_image,
+ int width,
+ int height,
+ float overscan,
+ int channels,
+ float* destination_image) {
+ memcpy(destination_image, source_image,
+ channels * width * height * sizeof(float));
+}
+
+void 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) {
+ memcpy(destination_image, source_image,
+ channels * width * height * sizeof(unsigned char));
+}
+
+void libmv_cameraIntrinsicsDistortFloat(
+ const libmv_CameraIntrinsics* /*libmv_intrinsics*/,
+ float* source_image,
+ int width,
+ int height,
+ float overscan,
+ int channels,
+ float* destination_image) {
+ memcpy(destination_image, source_image,
+ channels * width * height * sizeof(float));
+}
+
+/* ************ utils ************ */
+
+void libmv_cameraIntrinsicsApply(
+ const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
+ double x,
+ double y,
+ double* x1,
+ double* y1) {
+ double focal_length = libmv_camera_intrinsics_options->focal_length;
+ double principal_x = libmv_camera_intrinsics_options->principal_point_x;
+ double principal_y = libmv_camera_intrinsics_options->principal_point_y;
+ *x1 = x * focal_length + principal_x;
+ *y1 = y * focal_length + principal_y;
+}
+
+void libmv_cameraIntrinsicsInvert(
+ const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
+ double x,
+ double y,
+ double* x1,
+ double* y1) {
+ double focal_length = libmv_camera_intrinsics_options->focal_length;
+ double principal_x = libmv_camera_intrinsics_options->principal_point_x;
+ double principal_y = libmv_camera_intrinsics_options->principal_point_y;
+ *x1 = (x - principal_x) / focal_length;
+ *y1 = (y - principal_y) / focal_length;
+}
+
+void libmv_homography2DFromCorrespondencesEuc(/* const */ double (*x1)[2],
+ /* const */ double (*x2)[2],
+ int num_points,
+ double H[3][3]) {
+ memset(H, 0, sizeof(double[3][3]));
+ H[0][0] = 1.0f;
+ H[1][1] = 1.0f;
+ H[2][2] = 1.0f;
+}
diff --git a/extern/libmv/intern/track_region.cc b/extern/libmv/intern/track_region.cc
new file mode 100644
index 00000000000..24fbc78c1a1
--- /dev/null
+++ b/extern/libmv/intern/track_region.cc
@@ -0,0 +1,177 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "intern/track_region.h"
+#include "intern/image.h"
+#include "intern/utildefines.h"
+#include "libmv/image/image.h"
+#include "libmv/tracking/track_region.h"
+
+/* define this to generate PNG images with content of search areas
+ tracking between which failed */
+#undef DUMP_FAILURE
+
+/* define this to generate PNG images with content of search areas
+ on every itteration of tracking */
+#undef DUMP_ALWAYS
+
+using libmv::FloatImage;
+using libmv::TrackRegionOptions;
+using libmv::TrackRegionResult;
+using libmv::TrackRegion;
+
+void libmv_configureTrackRegionOptions(
+ const libmv_TrackRegionOptions& options,
+ TrackRegionOptions* track_region_options) {
+ switch (options.motion_model) {
+#define LIBMV_CONVERT(the_model) \
+ case TrackRegionOptions::the_model: \
+ track_region_options->mode = TrackRegionOptions::the_model; \
+ break;
+ LIBMV_CONVERT(TRANSLATION)
+ LIBMV_CONVERT(TRANSLATION_ROTATION)
+ LIBMV_CONVERT(TRANSLATION_SCALE)
+ LIBMV_CONVERT(TRANSLATION_ROTATION_SCALE)
+ LIBMV_CONVERT(AFFINE)
+ LIBMV_CONVERT(HOMOGRAPHY)
+#undef LIBMV_CONVERT
+ }
+
+ track_region_options->minimum_correlation = options.minimum_correlation;
+ track_region_options->max_iterations = options.num_iterations;
+ track_region_options->sigma = options.sigma;
+ track_region_options->num_extra_points = 1;
+ track_region_options->image1_mask = NULL;
+ track_region_options->use_brute_initialization = options.use_brute;
+ /* TODO(keir): This will make some cases better, but may be a regression until
+ * the motion model is in. Since this is on trunk, enable it for now.
+ *
+ * TODO(sergey): This gives much worse results on mango footage (see 04_2e)
+ * so disabling for now for until proper prediction model is landed.
+ *
+ * The thing is, currently blender sends input coordinates as the guess to
+ * region tracker and in case of fast motion such an early out ruins the track.
+ */
+ track_region_options->attempt_refine_before_brute = false;
+ track_region_options->use_normalized_intensities = options.use_normalization;
+}
+
+void libmv_regionTrackergetResult(const TrackRegionResult& track_region_result,
+ libmv_TrackRegionResult* result) {
+ result->termination = (int) track_region_result.termination;
+ result->termination_reason = "";
+ result->correlation = track_region_result.correlation;
+}
+
+int libmv_trackRegion(const libmv_TrackRegionOptions* options,
+ const float* image1,
+ int image1_width,
+ int image1_height,
+ const float* image2,
+ int image2_width,
+ int image2_height,
+ const double* x1,
+ const double* y1,
+ libmv_TrackRegionResult* result,
+ double* x2,
+ double* y2) {
+ double xx1[5], yy1[5];
+ double xx2[5], yy2[5];
+ bool tracking_result = false;
+
+ // Convert to doubles for the libmv api. The four corners and the center.
+ for (int i = 0; i < 5; ++i) {
+ xx1[i] = x1[i];
+ yy1[i] = y1[i];
+ xx2[i] = x2[i];
+ yy2[i] = y2[i];
+ }
+
+ TrackRegionOptions track_region_options;
+ FloatImage image1_mask;
+
+ libmv_configureTrackRegionOptions(*options, &track_region_options);
+ if (options->image1_mask) {
+ libmv_floatBufferToFloatImage(options->image1_mask,
+ image1_width,
+ image1_height,
+ 1,
+ &image1_mask);
+
+ track_region_options.image1_mask = &image1_mask;
+ }
+
+ // Convert from raw float buffers to libmv's FloatImage.
+ FloatImage old_patch, new_patch;
+ libmv_floatBufferToFloatImage(image1,
+ image1_width,
+ image1_height,
+ 1,
+ &old_patch);
+ libmv_floatBufferToFloatImage(image2,
+ image2_width,
+ image2_height,
+ 1,
+ &new_patch);
+
+ TrackRegionResult track_region_result;
+ TrackRegion(old_patch, new_patch,
+ xx1, yy1,
+ track_region_options,
+ xx2, yy2,
+ &track_region_result);
+
+ // Convert to floats for the blender api.
+ for (int i = 0; i < 5; ++i) {
+ x2[i] = xx2[i];
+ y2[i] = yy2[i];
+ }
+
+ // TODO(keir): Update the termination string with failure details.
+ if (track_region_result.termination == TrackRegionResult::CONVERGENCE ||
+ track_region_result.termination == TrackRegionResult::NO_CONVERGENCE) {
+ tracking_result = true;
+ }
+
+ // Debug dump of patches.
+#if defined(DUMP_FAILURE) || defined(DUMP_ALWAYS)
+ bool need_dump = !tracking_result;
+
+# ifdef DUMP_ALWAYS
+ need_dump = true;
+# endif
+
+ if (need_dump) {
+ libmv_saveImage(old_patch, "old_patch", x1[4], y1[4]);
+ libmv_saveImage(new_patch, "new_patch", x2[4], y2[4]);
+ if (options->image1_mask) {
+ libmv_saveImage(image1_mask, "mask", x2[4], y2[4]);
+ }
+ }
+#endif
+
+ return tracking_result;
+}
diff --git a/extern/libmv/intern/track_region.h b/extern/libmv/intern/track_region.h
new file mode 100644
index 00000000000..95ec124c3e1
--- /dev/null
+++ b/extern/libmv/intern/track_region.h
@@ -0,0 +1,81 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef LIBMV_C_API_TRACK_REGION_H_
+#define LIBMV_C_API_TRACK_REGION_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct libmv_TrackRegionOptions {
+ int motion_model;
+ int num_iterations;
+ int use_brute;
+ int use_normalization;
+ double minimum_correlation;
+ double sigma;
+ float *image1_mask;
+} libmv_TrackRegionOptions;
+
+typedef struct libmv_TrackRegionResult {
+ int termination;
+ const char* termination_reason;
+ double correlation;
+} libmv_TrackRegionResult;
+
+#ifdef __cplusplus
+namespace libmv {
+ class TrackRegionOptions;
+ class TrackRegionResult;
+}
+void libmv_configureTrackRegionOptions(
+ const libmv_TrackRegionOptions& options,
+ libmv::TrackRegionOptions* track_region_options);
+
+void libmv_regionTrackergetResult(
+ const libmv::TrackRegionResult& track_region_result,
+ libmv_TrackRegionResult* result);
+#endif
+
+int libmv_trackRegion(const libmv_TrackRegionOptions* options,
+ const float* image1,
+ int image1_width,
+ int image1_height,
+ const float* image2,
+ int image2_width,
+ int image2_height,
+ const double* x1,
+ const double* y1,
+ libmv_TrackRegionResult* result,
+ double* x2,
+ double* y2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LIBMV_C_API_PLANAR_TRACKER_H_
diff --git a/extern/libmv/intern/tracks.cc b/extern/libmv/intern/tracks.cc
new file mode 100644
index 00000000000..9b032b0760a
--- /dev/null
+++ b/extern/libmv/intern/tracks.cc
@@ -0,0 +1,52 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "intern/tracks.h"
+#include "intern/utildefines.h"
+
+#include "libmv/simple_pipeline/tracks.h"
+
+using libmv::Marker;
+using libmv::Tracks;
+
+libmv_Tracks* libmv_tracksNew(void) {
+ Tracks* tracks = LIBMV_OBJECT_NEW(Tracks);
+
+ return (libmv_Tracks*) tracks;
+}
+
+void libmv_tracksDestroy(libmv_Tracks* libmv_tracks) {
+ LIBMV_OBJECT_DELETE(libmv_tracks, Tracks);
+}
+
+void libmv_tracksInsert(libmv_Tracks *libmv_tracks,
+ int image,
+ int track,
+ double x,
+ double y,
+ double weight) {
+ ((Tracks *) libmv_tracks)->Insert(image, track, x, y, weight);
+}
diff --git a/extern/libmv/intern/tracks.h b/extern/libmv/intern/tracks.h
new file mode 100644
index 00000000000..79f6cc99579
--- /dev/null
+++ b/extern/libmv/intern/tracks.h
@@ -0,0 +1,51 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef LIBMV_C_API_TRACKS_H_
+#define LIBMV_C_API_TRACKS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct libmv_Tracks libmv_Tracks;
+
+libmv_Tracks* libmv_tracksNew(void);
+
+void libmv_tracksDestroy(libmv_Tracks* libmv_tracks);
+
+void libmv_tracksInsert(libmv_Tracks* libmv_tracks,
+ int image,
+ int track,
+ double x,
+ double y,
+ double weight);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LIBMV_C_API_TRACKS_H_
diff --git a/extern/libmv/intern/utildefines.h b/extern/libmv/intern/utildefines.h
new file mode 100644
index 00000000000..7366b242cf7
--- /dev/null
+++ b/extern/libmv/intern/utildefines.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef LIBMV_C_API_UTILDEFINES_H_
+#define LIBMV_C_API_UTILDEFINES_H_
+
+#if defined(_MSC_VER)
+# define __func__ __FUNCTION__
+# define snprintf _snprintf
+#endif
+
+#ifdef WITH_LIBMV_GUARDED_ALLOC
+# include "MEM_guardedalloc.h"
+# define LIBMV_OBJECT_NEW OBJECT_GUARDED_NEW
+# define LIBMV_OBJECT_DELETE OBJECT_GUARDED_DELETE
+# define LIBMV_OBJECT_DELETE OBJECT_GUARDED_DELETE
+# define LIBMV_STRUCT_NEW(type, count) \
+ (type*)MEM_mallocN(sizeof(type) * count, __func__)
+# define LIBMV_STRUCT_DELETE(what) MEM_freeN(what)
+#else
+// Need this to keep libmv-capi potentially standalone.
+# if defined __GNUC__ || defined __sun
+# define LIBMV_OBJECT_NEW(type, args ...) \
+ new(malloc(sizeof(type))) type(args)
+# else
+# define LIBMV_OBJECT_NEW(type, ...) \
+ new(malloc(sizeof(type))) type(__VA_ARGS__)
+#endif
+# define LIBMV_OBJECT_DELETE(what, type) \
+ { \
+ if (what) { \
+ ((type*)(what))->~type(); \
+ free(what); \
+ } \
+ } (void)0
+# define LIBMV_STRUCT_NEW(type, count) (type*)malloc(sizeof(type) * count)
+# define LIBMV_STRUCT_DELETE(what) { if (what) free(what); } (void)0
+#endif
+
+#endif // LIBMV_C_API_UTILDEFINES_H_