From 058e3f087e4db827e0dcb2b8ea662fa7cdc1ff6b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 25 Sep 2014 17:01:06 +0600 Subject: Tracking: Decouple C-API module into more granular files This way maintaining the C-API is a bit less tedious job and makes code cleaner to follow. Should be no functional changes. --- extern/libmv/CMakeLists.txt | 24 +- extern/libmv/SConscript | 5 +- extern/libmv/bundle.sh | 33 +- extern/libmv/intern/camera_intrinsics.cc | 354 +++++++++ extern/libmv/intern/camera_intrinsics.h | 138 ++++ extern/libmv/intern/detector.cc | 148 ++++ extern/libmv/intern/detector.h | 77 ++ extern/libmv/intern/homography.cc | 59 ++ extern/libmv/intern/homography.h | 43 ++ extern/libmv/intern/image.cc | 272 +++++++ extern/libmv/intern/image.h | 99 +++ extern/libmv/intern/logging.cc | 55 ++ extern/libmv/intern/logging.h | 47 ++ extern/libmv/intern/reconstruction.cc | 530 +++++++++++++ extern/libmv/intern/reconstruction.h | 99 +++ extern/libmv/intern/region.h | 43 ++ extern/libmv/intern/stub.cc | 330 +++++++++ extern/libmv/intern/track_region.cc | 177 +++++ extern/libmv/intern/track_region.h | 81 ++ extern/libmv/intern/tracks.cc | 52 ++ extern/libmv/intern/tracks.h | 51 ++ extern/libmv/intern/utildefines.h | 62 ++ extern/libmv/libmv-capi.cc | 1185 ------------------------------ extern/libmv/libmv-capi.h | 187 +---- extern/libmv/libmv-capi_intern.h | 59 -- extern/libmv/libmv-capi_stub.cc | 293 -------- extern/libmv/libmv-util.cc | 309 -------- extern/libmv/libmv-util.h | 69 -- 28 files changed, 2771 insertions(+), 2110 deletions(-) create mode 100644 extern/libmv/intern/camera_intrinsics.cc create mode 100644 extern/libmv/intern/camera_intrinsics.h create mode 100644 extern/libmv/intern/detector.cc create mode 100644 extern/libmv/intern/detector.h create mode 100644 extern/libmv/intern/homography.cc create mode 100644 extern/libmv/intern/homography.h create mode 100644 extern/libmv/intern/image.cc create mode 100644 extern/libmv/intern/image.h create mode 100644 extern/libmv/intern/logging.cc create mode 100644 extern/libmv/intern/logging.h create mode 100644 extern/libmv/intern/reconstruction.cc create mode 100644 extern/libmv/intern/reconstruction.h create mode 100644 extern/libmv/intern/region.h create mode 100644 extern/libmv/intern/stub.cc create mode 100644 extern/libmv/intern/track_region.cc create mode 100644 extern/libmv/intern/track_region.h create mode 100644 extern/libmv/intern/tracks.cc create mode 100644 extern/libmv/intern/tracks.h create mode 100644 extern/libmv/intern/utildefines.h delete mode 100644 extern/libmv/libmv-capi.cc delete mode 100644 extern/libmv/libmv-capi_intern.h delete mode 100644 extern/libmv/libmv-capi_stub.cc delete mode 100644 extern/libmv/libmv-util.cc delete mode 100644 extern/libmv/libmv-util.h (limited to 'extern/libmv') diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt index 9030ae9c1ed..d482819c2ce 100644 --- a/extern/libmv/CMakeLists.txt +++ b/extern/libmv/CMakeLists.txt @@ -35,12 +35,10 @@ set(INC_SYS set(SRC libmv-capi.h - libmv-capi_intern.h ) if(WITH_LIBMV) add_definitions( - -DWITH_LIBMV -DWITH_LIBMV_GUARDED_ALLOC -DGOOGLE_GLOG_DLL_DECL= -DLIBMV_NO_FAST_DETECTOR= @@ -73,8 +71,14 @@ if(WITH_LIBMV) ) list(APPEND SRC - libmv-capi.cc - libmv-util.cc + intern/camera_intrinsics.cc + intern/detector.cc + intern/homography.cc + intern/image.cc + intern/logging.cc + intern/reconstruction.cc + intern/track_region.cc + intern/tracks.cc libmv/base/aligned_malloc.cc libmv/image/array_nd.cc libmv/image/convolve.cc @@ -109,7 +113,15 @@ if(WITH_LIBMV) libmv/tracking/track_region.cc libmv/tracking/trklt_region_tracker.cc - libmv-util.h + + intern/camera_intrinsics.h + intern/detector.h + intern/homography.h + intern/image.h + intern/logging.h + intern/reconstruction.h + intern/track_region.h + intern/tracks.h libmv/base/aligned_malloc.h libmv/base/id_generator.h libmv/base/scoped_ptr.h @@ -217,7 +229,7 @@ if(WITH_LIBMV) endif() else() list(APPEND SRC - libmv-capi_stub.cc + intern/stub.cc ) endif() diff --git a/extern/libmv/SConscript b/extern/libmv/SConscript index 6156dd45146..857d7dec7d4 100644 --- a/extern/libmv/SConscript +++ b/extern/libmv/SConscript @@ -24,11 +24,10 @@ if env['WITH_BF_LIBMV']: defs.append('CERES_TR1_SHARED_PTR') defs.append('GOOGLE_GLOG_DLL_DECL=') - defs.append('WITH_LIBMV') defs.append('WITH_LIBMV_GUARDED_ALLOC') defs.append('LIBMV_NO_FAST_DETECTOR') - src = env.Glob('*.cc') + src = env.Glob('intern/*.cc') src += env.Glob('libmv/base/*.cc') src += env.Glob('libmv/image/*.cc') src += env.Glob('libmv/multiview/*.cc') @@ -52,7 +51,7 @@ if env['WITH_BF_LIBMV']: src += env.Glob("third_party/glog/src/*.cc") incs += ' ./third_party/glog/src' else: - src = env.Glob("libmv-capi_stub.cc") + src = env.Glob("intern/stub.cc") src = [src for src in src if src.find('_test.cc') == -1] diff --git a/extern/libmv/bundle.sh b/extern/libmv/bundle.sh index 0560ab0acd2..d394d2cd8c5 100755 --- a/extern/libmv/bundle.sh +++ b/extern/libmv/bundle.sh @@ -7,7 +7,7 @@ else exit 1 fi -BRANCH="devel" +BRANCH="master" repo="git://git.blender.org/libmv.git" tmp=`mktemp -d` @@ -128,12 +128,10 @@ set(INC_SYS set(SRC libmv-capi.h - libmv-capi_intern.h ) if(WITH_LIBMV) add_definitions( - -DWITH_LIBMV -DWITH_LIBMV_GUARDED_ALLOC -DGOOGLE_GLOG_DLL_DECL= -DLIBMV_NO_FAST_DETECTOR= @@ -166,11 +164,29 @@ if(WITH_LIBMV) ) list(APPEND SRC - libmv-capi.cc - libmv-util.cc + intern/camera_intrinsics.cc + intern/detector.cc + intern/frame_accessor.cc + intern/homography.cc + intern/image.cc + intern/logging.cc + intern/reconstruction.cc + intern/track_region.cc + intern/tracks.cc + intern/tracksN.cc ${sources} ${third_sources} - libmv-util.h + + intern/camera_intrinsics.h + intern/detector.h + intern/frame_accessor.h + intern/homography.h + intern/image.h + intern/logging.h + intern/reconstruction.h + intern/track_region.h + intern/tracks.h + intern/tracksN.h ${headers} ${third_headers} @@ -287,11 +303,10 @@ if env['WITH_BF_LIBMV']: defs.append('CERES_TR1_SHARED_PTR') defs.append('GOOGLE_GLOG_DLL_DECL=') - defs.append('WITH_LIBMV') defs.append('WITH_LIBMV_GUARDED_ALLOC') defs.append('LIBMV_NO_FAST_DETECTOR') - src = env.Glob('*.cc') + src = env.Glob('intern/*.cc') $src incs += ' ../Eigen3 third_party/gflags third_party/glog/src third_party/ceres/include third_party/ceres/config ../../intern/guardedalloc' @@ -309,7 +324,7 @@ ${win_src} src += env.Glob("third_party/glog/src/*.cc") incs += ' ./third_party/glog/src' else: - src = env.Glob("libmv-capi_stub.cc") + src = env.Glob("intern/stub.cc") src = [src for src in src if src.find('_test.cc') == -1] 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(orig_intrinsics); + new_intrinsics = LIBMV_OBJECT_NEW(PolynomialCameraIntrinsics, + *polynomial_intrinsics); + break; + } + case libmv::DISTORTION_MODEL_DIVISION: + { + const DivisionCameraIntrinsics *division_intrinsics = + static_cast(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(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(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(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(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& 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 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 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 +#include + +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 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::max(); + for (int i = 1; i < keyframes.size(); i++) { + EuclideanReconstruction reconstruction; + int current_keyframe = keyframes[i]; + libmv::vector 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 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 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 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 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 +#include + +/* ************ 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_ diff --git a/extern/libmv/libmv-capi.cc b/extern/libmv/libmv-capi.cc deleted file mode 100644 index 82143d50fbf..00000000000 --- a/extern/libmv/libmv-capi.cc +++ /dev/null @@ -1,1185 +0,0 @@ -/* - * ***** 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 ***** - */ - -#ifdef WITH_LIBMV - -/* 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 - -#include "libmv-capi.h" -#include "libmv-util.h" - -#include - -#include "libmv-capi_intern.h" -#include "libmv/logging/logging.h" -#include "libmv/multiview/homography.h" -#include "libmv/tracking/track_region.h" -#include "libmv/simple_pipeline/callbacks.h" -#include "libmv/simple_pipeline/tracks.h" -#include "libmv/simple_pipeline/initialize_reconstruction.h" -#include "libmv/simple_pipeline/bundle.h" -#include "libmv/simple_pipeline/detect.h" -#include "libmv/simple_pipeline/pipeline.h" -#include "libmv/simple_pipeline/camera_intrinsics.h" -#include "libmv/simple_pipeline/modal_solver.h" -#include "libmv/simple_pipeline/reconstruction_scale.h" -#include "libmv/simple_pipeline/keyframe_selection.h" - -#ifdef _MSC_VER -# define snprintf _snprintf -#endif - -using libmv::CameraIntrinsics; -using libmv::DetectOptions; -using libmv::DivisionCameraIntrinsics; -using libmv::EuclideanCamera; -using libmv::EuclideanPoint; -using libmv::EuclideanReconstruction; -using libmv::EuclideanScaleToUnity; -using libmv::Feature; -using libmv::FloatImage; -using libmv::Marker; -using libmv::PolynomialCameraIntrinsics; -using libmv::ProgressUpdateCallback; -using libmv::Tracks; -using libmv::TrackRegionOptions; -using libmv::TrackRegionResult; - -using libmv::Detect; -using libmv::EuclideanBundle; -using libmv::EuclideanCompleteReconstruction; -using libmv::EuclideanReconstructTwoFrames; -using libmv::EuclideanReprojectionError; -using libmv::TrackRegion; -using libmv::SamplePlanarPatch; - -typedef struct libmv_Tracks libmv_Tracks; -typedef struct libmv_Reconstruction libmv_Reconstruction; -typedef struct libmv_Features libmv_Features; -typedef struct libmv_CameraIntrinsics libmv_CameraIntrinsics; - -struct libmv_Reconstruction { - EuclideanReconstruction reconstruction; - - /* used for per-track average error calculation after reconstruction */ - Tracks tracks; - CameraIntrinsics *intrinsics; - - double error; -}; - -struct libmv_Features { - int count; - Feature *features; -}; - -/* ************ Logging ************ */ - -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); -} - -/* ************ Planar tracker ************ */ - -/* TrackRegion */ -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; - - 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; - - if (options->image1_mask) { - libmv_floatBufferToImage(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_floatBufferToImage(image1, - image1_width, image1_height, 1, - &old_patch); - libmv_floatBufferToImage(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; -} - -void libmv_samplePlanarPatch(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_floatBufferToImage(image, width, height, channels, &libmv_image); - - if (mask) { - libmv_floatBufferToImage(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_imageToFloatBuffer(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_byteBufferToImage(image, width, height, channels, &libmv_image); - - if (mask) { - libmv_floatBufferToImage(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_imageToByteBuffer(libmv_patch, patch); -} - -/* ************ Tracks ************ */ - -libmv_Tracks *libmv_tracksNew(void) -{ - Tracks *libmv_tracks = LIBMV_OBJECT_NEW(Tracks); - - return (libmv_Tracks *) libmv_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); -} - -/* ************ Reconstruction ************ */ - -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 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::max(); - for (int i = 1; i < keyframes.size(); i++) { - EuclideanReconstruction reconstruction; - int current_keyframe = keyframes[i]; - - libmv::vector 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; -} - -} // 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 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 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 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; -} - -/* ************ Feature detector ************ */ - -static libmv_Features *libmv_featuresFromVector( - const libmv::vector &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; -} - -static 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; -} - -libmv_Features *libmv_detectFeaturesByte( - const unsigned char *image_buffer, - int width, int height, - int channels, - libmv_DetectOptions *options) -{ - // Prepare the image. - FloatImage image; - libmv_byteBufferToImage(image_buffer, width, height, channels, &image); - - // Configure detector. - DetectOptions detector_options; - libmv_convertDetectorOptions(options, &detector_options); - - // Run the detector. - libmv::vector 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_floatBufferToImage(image_buffer, width, height, channels, &image); - - // Configure detector. - DetectOptions detector_options; - libmv_convertDetectorOptions(options, &detector_options); - - // Run the detector. - libmv::vector 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; -} - -/* ************ Camera intrinsics ************ */ - -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 *libmvIntrinsics) -{ - const CameraIntrinsics *orig_intrinsics = - (const CameraIntrinsics *) libmvIntrinsics; - - CameraIntrinsics *new_intrinsics = NULL; - - switch (orig_intrinsics->GetDistortionModelType()) { - case libmv::DISTORTION_MODEL_POLYNOMIAL: - { - const PolynomialCameraIntrinsics *polynomial_intrinsics = - static_cast(orig_intrinsics); - new_intrinsics = LIBMV_OBJECT_NEW(PolynomialCameraIntrinsics, - *polynomial_intrinsics); - break; - } - case libmv::DISTORTION_MODEL_DIVISION: - { - const DivisionCameraIntrinsics *division_intrinsics = - static_cast(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 *libmvIntrinsics) -{ - LIBMV_OBJECT_DELETE(libmvIntrinsics, 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(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(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, - unsigned char *src, unsigned char *dst, int width, int height, - float overscan, int channels) -{ - CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics; - camera_intrinsics->UndistortBuffer(src, - width, height, overscan, channels, - dst); -} - -void libmv_cameraIntrinsicsUndistortFloat( - const libmv_CameraIntrinsics *libmvIntrinsics, - float *src, float *dst, int width, int height, - float overscan, int channels) -{ - CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmvIntrinsics; - intrinsics->UndistortBuffer(src, - width, height, overscan, channels, - dst); -} - -void libmv_cameraIntrinsicsDistortByte( - const libmv_CameraIntrinsics *libmvIntrinsics, - unsigned char *src, unsigned char *dst, int width, int height, - float overscan, int channels) -{ - CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmvIntrinsics; - intrinsics->DistortBuffer(src, - width, height, overscan, channels, - dst); -} - -void libmv_cameraIntrinsicsDistortFloat( - const libmv_CameraIntrinsics *libmvIntrinsics, - float *src, float *dst, int width, int height, - float overscan, int channels) -{ - CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmvIntrinsics; - intrinsics->DistortBuffer(src, - width, height, overscan, channels, - dst); -} - -void libmv_cameraIntrinsicsApply( - const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options, - double x, double y, double *x1, double *y1) -{ - /* do a lens undistortion 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 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); - } -} - -void libmv_homography2DFromCorrespondencesEuc(double (*x1)[2], - 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)); -} - -#endif diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h index 5cd9936723b..524f1822bc7 100644 --- a/extern/libmv/libmv-capi.h +++ b/extern/libmv/libmv-capi.h @@ -27,180 +27,13 @@ #ifndef LIBMV_C_API_H #define LIBMV_C_API_H -#ifdef __cplusplus -extern "C" { -#endif - -struct libmv_Tracks; -struct libmv_Reconstruction; -struct libmv_Features; -struct libmv_CameraIntrinsics; - -/* Logging */ -void libmv_initLogging(const char *argv0); -void libmv_startDebugLogging(void); -void libmv_setLoggingVerbosity(int verbosity); - -/* Planar tracker */ -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; - -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); -void libmv_samplePlanarPatch(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); - -/* Tracks */ -struct libmv_Tracks *libmv_tracksNew(void); -void libmv_tracksDestroy(struct libmv_Tracks *libmv_tracks); -void libmv_tracksInsert(struct libmv_Tracks *libmv_tracks, int image, int track, double x, double y, double weight); - -/* Reconstruction */ -#define LIBMV_REFINE_FOCAL_LENGTH (1 << 0) -#define LIBMV_REFINE_PRINCIPAL_POINT (1 << 1) -#define LIBMV_REFINE_RADIAL_DISTORTION_K1 (1 << 2) -#define LIBMV_REFINE_RADIAL_DISTORTION_K2 (1 << 4) - -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; - -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); - -struct libmv_Reconstruction *libmv_solveReconstruction(const struct 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); -struct libmv_Reconstruction *libmv_solveModal(const struct 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(struct libmv_Reconstruction *libmv_reconstruction); -int libmv_reprojectionPointForTrack(const struct libmv_Reconstruction *libmv_reconstruction, int track, double pos[3]); -double libmv_reprojectionErrorForTrack(const struct libmv_Reconstruction *libmv_reconstruction, int track); -double libmv_reprojectionErrorForImage(const struct libmv_Reconstruction *libmv_reconstruction, int image); -int libmv_reprojectionCameraForImage(const struct libmv_Reconstruction *libmv_reconstruction, - int image, double mat[4][4]); -double libmv_reprojectionError(const struct libmv_Reconstruction *libmv_reconstruction); -struct libmv_CameraIntrinsics *libmv_reconstructionExtractIntrinsics(struct libmv_Reconstruction *libmv_Reconstruction); - -/* Feature detector */ -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; - -struct libmv_Features *libmv_detectFeaturesByte(const unsigned char *image_buffer, - int width, int height, int channels, - libmv_DetectOptions *options); -struct libmv_Features *libmv_detectFeaturesFloat(const float *image_buffer, - int width, int height, int channels, - libmv_DetectOptions *options); - -void libmv_featuresDestroy(struct libmv_Features *libmv_features); -int libmv_countFeatures(const struct libmv_Features *libmv_features); -void libmv_getFeature(const struct libmv_Features *libmv_features, int number, double *x, double *y, double *score, - double *size); - -/* Camera intrinsics */ -struct libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew( - const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options); -struct libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy(const struct libmv_CameraIntrinsics *libmv_intrinsics); -void libmv_cameraIntrinsicsDestroy(struct libmv_CameraIntrinsics *libmv_intrinsics); -void libmv_cameraIntrinsicsUpdate(const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options, - struct libmv_CameraIntrinsics *libmv_intrinsics); -void libmv_cameraIntrinsicsSetThreads(struct libmv_CameraIntrinsics *libmv_intrinsics, int threads); -void libmv_cameraIntrinsicsExtractOptions( - const struct libmv_CameraIntrinsics *libmv_intrinsics, - struct libmv_CameraIntrinsicsOptions *camera_intrinsics_options); -void libmv_cameraIntrinsicsUndistortByte(const struct libmv_CameraIntrinsics *libmv_intrinsics, - unsigned char *src, unsigned char *dst, int width, int height, - float overscan, int channels); -void libmv_cameraIntrinsicsUndistortFloat(const struct libmv_CameraIntrinsics *libmv_intrinsics, - float *src, float *dst, int width, int height, - float overscan, int channels); -void libmv_cameraIntrinsicsDistortByte(const struct libmv_CameraIntrinsics *libmv_intrinsics, - unsigned char *src, unsigned char *dst, int width, int height, - float overscan, int channels); -void libmv_cameraIntrinsicsDistortFloat(const struct libmv_CameraIntrinsics *libmv_intrinsics, - float *src, float *dst, int width, int height, - float overscan, int channels); -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); - -void libmv_homography2DFromCorrespondencesEuc(double (*x1)[2], double (*x2)[2], int num_points, double H[3][3]); - -#ifdef __cplusplus -} -#endif - -#endif // LIBMV_C_API_H +#include "intern/camera_intrinsics.h" +#include "intern/detector.h" +#include "intern/homography.h" +#include "intern/image.h" +#include "intern/logging.h" +#include "intern/reconstruction.h" +#include "intern/track_region.h" +#include "intern/tracks.h" + +#endif // LIBMV_C_API_H diff --git a/extern/libmv/libmv-capi_intern.h b/extern/libmv/libmv-capi_intern.h deleted file mode 100644 index 90087c52a6c..00000000000 --- a/extern/libmv/libmv-capi_intern.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * ***** 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_INTERN_H -#define LIBMV_C_API_INTERN_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_INTERN_H diff --git a/extern/libmv/libmv-capi_stub.cc b/extern/libmv/libmv-capi_stub.cc deleted file mode 100644 index 36a3bc7ddee..00000000000 --- a/extern/libmv/libmv-capi_stub.cc +++ /dev/null @@ -1,293 +0,0 @@ -/* - * ***** 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 ***** - */ - -#ifndef WITH_LIBMV - -#include "libmv-capi.h" - -#include -#include - -/* ************ 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_samplePlanarPatch(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 ************ */ - -struct libmv_Tracks *libmv_tracksNew(void) -{ - return NULL; -} - -void libmv_tracksInsert(struct libmv_Tracks * /*libmv_tracks*/, int /*image*/, - int /*track*/, double /*x*/, double /*y*/, double /*weight*/) -{ -} - -void libmv_tracksDestroy(struct libmv_Tracks * /*libmv_tracks*/) -{ -} - -/* ************ Reconstruction solver ************ */ - -struct libmv_Reconstruction *libmv_solveReconstruction(const struct 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; -} - -struct libmv_Reconstruction *libmv_solveModal(const struct 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 struct libmv_Reconstruction * /*libmv_reconstruction*/, - int /*track*/, double /*pos*/[3]) -{ - return 0; -} - -double libmv_reprojectionErrorForTrack(const struct libmv_Reconstruction * /*libmv_reconstruction*/, int /*track*/) -{ - return 0.0; -} - -double libmv_reprojectionErrorForImage(const struct libmv_Reconstruction * /*libmv_reconstruction*/, int /*image*/) -{ - return 0.0; -} - -int libmv_reprojectionCameraForImage(const struct libmv_Reconstruction * /*libmv_reconstruction*/, int /*image*/, - double /*mat*/[4][4]) -{ - return 0; -} - -double libmv_reprojectionError(const struct libmv_Reconstruction * /*libmv_reconstruction*/) -{ - return 0.0; -} - -void libmv_reconstructionDestroy(struct libmv_Reconstruction * /*libmv_reconstruction*/) -{ -} - -/* ************ feature detector ************ */ - -struct 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 struct libmv_Features * /*libmv_features*/) -{ - return 0; -} - -void libmv_getFeature(const struct 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 ************ */ - -struct libmv_CameraIntrinsics *libmv_reconstructionExtractIntrinsics( - struct libmv_Reconstruction * /*libmv_reconstruction*/) -{ - return NULL; -} - -struct libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew( - const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/) -{ - return NULL; -} - -struct libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy(const libmv_CameraIntrinsics * /*libmvIntrinsics*/) -{ - return NULL; -} - -void libmv_cameraIntrinsicsDestroy(struct libmv_CameraIntrinsics * /*libmvIntrinsics*/) -{ -} - -void libmv_cameraIntrinsicsUpdate(const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/, - struct libmv_CameraIntrinsics * /*libmv_intrinsics*/) -{ -} - -void libmv_cameraIntrinsicsSetThreads(struct 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 struct libmv_CameraIntrinsics * /*libmv_intrinsics*/, - unsigned char *src, unsigned char *dst, int width, int height, - float overscan, int channels) -{ - memcpy(dst, src, channels * width * height * sizeof(unsigned char)); -} - -void libmv_cameraIntrinsicsUndistortFloat(const struct libmv_CameraIntrinsics * /*libmvIntrinsics*/, - float *src, float *dst, int width, int height, float overscan, int channels) -{ - memcpy(dst, src, channels * width * height * sizeof(float)); -} - -void libmv_cameraIntrinsicsDistortByte(const struct libmv_CameraIntrinsics *libmvIntrinsics, - unsigned char *src, unsigned char *dst, int width, int height, - float overscan, int channels) -{ - memcpy(dst, src, channels * width * height * sizeof(unsigned char)); -} - -void libmv_cameraIntrinsicsDistortFloat(const struct libmv_CameraIntrinsics *libmvIntrinsics, - float *src, float *dst, int width, int height, float overscan, int channels) -{ - memcpy(dst, src, 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(double (* /* x1 */)[2], 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; -} - -#endif // ifndef WITH_LIBMV diff --git a/extern/libmv/libmv-util.cc b/extern/libmv/libmv-util.cc deleted file mode 100644 index f969417d6c1..00000000000 --- a/extern/libmv/libmv-util.cc +++ /dev/null @@ -1,309 +0,0 @@ -/* - * ***** 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 ***** - */ - -#include "libmv-util.h" -#include "libmv-capi_intern.h" - -#include -#include - -using libmv::CameraIntrinsics; -using libmv::DivisionCameraIntrinsics; -using libmv::EuclideanCamera; -using libmv::EuclideanPoint; -using libmv::FloatImage; -using libmv::Marker; -using libmv::PolynomialCameraIntrinsics; -using libmv::Tracks; - -/* Image <-> buffers conversion */ - -void libmv_byteBufferToImage(const unsigned char *buf, - int width, int height, int channels, - FloatImage *image) -{ - int x, y, k, a = 0; - - image->Resize(height, width, channels); - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - for (k = 0; k < channels; k++) { - (*image)(y, x, k) = (float)buf[a++] / 255.0f; - } - } - } -} - -void libmv_floatBufferToImage(const float *buf, - 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) = buf[a++]; - } - } - } -} - -void libmv_imageToFloatBuffer(const FloatImage &image, - float *buf) -{ - 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++) { - buf[a++] = image(y, x, k); - } - } - } -} - -void libmv_imageToByteBuffer(const libmv::FloatImage &image, - unsigned char *buf) -{ - 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++) { - buf[a++] = image(y, x, k) * 255.0f; - } - } - } -} - -/* Debugging */ - -static void 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) { - return; - } - - /* 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; - } - - png_init_io(png_ptr, fp); - - /* write header */ - if (setjmp(png_jmpbuf(png_ptr))) { - fclose(fp); - return; - } - - 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; - } - - png_write_image(png_ptr, row_pointers); - - /* end write */ - if (setjmp(png_jmpbuf(png_ptr))) { - fclose(fp); - return; - } - - png_write_end(png_ptr, NULL); - - fclose(fp); -} - -void 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 a = 0; - char buf[128]; - snprintf(buf, sizeof(buf), "%s_%02d.png", prefix, ++a); - savePNGImage(row_pointers, - image.Width(), image.Height(), 8, - PNG_COLOR_TYPE_RGBA, - buf); - } - - for (y = 0; y < image.Height(); y++) { - delete [] row_pointers[y]; - } - delete [] row_pointers; -} - -/* Camera intrinsics utility functions */ - -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(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(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; -} - -/* Reconstruction utilities */ - -void libmv_getNormalizedTracks(const Tracks &tracks, - const CameraIntrinsics &camera_intrinsics, - Tracks *normalized_tracks) -{ - libmv::vector 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); - } -} - -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; -} diff --git a/extern/libmv/libmv-util.h b/extern/libmv/libmv-util.h deleted file mode 100644 index d755f98d06d..00000000000 --- a/extern/libmv/libmv-util.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * ***** 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_UTIL_H -#define LIBMV_UTIL_H - -#include "libmv-capi.h" -#include "libmv/image/image.h" -#include "libmv/simple_pipeline/camera_intrinsics.h" -#include "libmv/simple_pipeline/tracks.h" -#include "libmv/simple_pipeline/reconstruction.h" - -void libmv_byteBufferToImage(const unsigned char *buf, - int width, int height, int channels, - libmv::FloatImage *image); - -void libmv_floatBufferToImage(const float *buf, - int width, int height, int channels, - libmv::FloatImage *image); - -void libmv_imageToFloatBuffer(const libmv::FloatImage &image, - float *buf); - -void libmv_imageToByteBuffer(const libmv::FloatImage &image, - unsigned char *buf); - -void libmv_saveImage(const libmv::FloatImage &image, - const char *prefix, - int x0, int y0); - -void libmv_cameraIntrinsicsFillFromOptions( - const libmv_CameraIntrinsicsOptions *camera_intrinsics_options, - libmv::CameraIntrinsics *camera_intrinsics); - -libmv::CameraIntrinsics *libmv_cameraIntrinsicsCreateFromOptions( - const libmv_CameraIntrinsicsOptions *camera_intrinsics_options); - -void libmv_getNormalizedTracks(const libmv::Tracks &tracks, - const libmv::CameraIntrinsics &camera_intrinsics, - libmv::Tracks *normalized_tracks); - -libmv::Marker libmv_projectMarker(const libmv::EuclideanPoint &point, - const libmv::EuclideanCamera &camera, - const libmv::CameraIntrinsics &intrinsics); - -#endif -- cgit v1.2.3