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.
This commit is contained in:
Sergey Sharybin 2014-09-25 17:01:06 +06:00
parent 34abb614f1
commit 058e3f087e
28 changed files with 2749 additions and 2076 deletions

View File

@ -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()

View File

@ -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]

View File

@ -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]

354
extern/libmv/intern/camera_intrinsics.cc vendored Normal file
View File

@ -0,0 +1,354 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2011 Blender Foundation.
* All rights reserved.
*
* Contributor(s): Blender Foundation,
* Sergey Sharybin
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "intern/camera_intrinsics.h"
#include "intern/utildefines.h"
#include "libmv/simple_pipeline/camera_intrinsics.h"
using libmv::CameraIntrinsics;
using libmv::DivisionCameraIntrinsics;
using libmv::PolynomialCameraIntrinsics;
libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew(
const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options) {
CameraIntrinsics *camera_intrinsics =
libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options);
return (libmv_CameraIntrinsics *) camera_intrinsics;
}
libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy(
const libmv_CameraIntrinsics* libmv_intrinsics) {
const CameraIntrinsics *orig_intrinsics =
(const CameraIntrinsics *) libmv_intrinsics;
CameraIntrinsics *new_intrinsics = NULL;
switch (orig_intrinsics->GetDistortionModelType()) {
case libmv::DISTORTION_MODEL_POLYNOMIAL:
{
const PolynomialCameraIntrinsics *polynomial_intrinsics =
static_cast<const PolynomialCameraIntrinsics*>(orig_intrinsics);
new_intrinsics = LIBMV_OBJECT_NEW(PolynomialCameraIntrinsics,
*polynomial_intrinsics);
break;
}
case libmv::DISTORTION_MODEL_DIVISION:
{
const DivisionCameraIntrinsics *division_intrinsics =
static_cast<const DivisionCameraIntrinsics*>(orig_intrinsics);
new_intrinsics = LIBMV_OBJECT_NEW(DivisionCameraIntrinsics,
*division_intrinsics);
break;
}
default:
assert(!"Unknown distortion model");
}
return (libmv_CameraIntrinsics *) new_intrinsics;
}
void libmv_cameraIntrinsicsDestroy(libmv_CameraIntrinsics* libmv_intrinsics) {
LIBMV_OBJECT_DELETE(libmv_intrinsics, CameraIntrinsics);
}
void libmv_cameraIntrinsicsUpdate(
const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
libmv_CameraIntrinsics* libmv_intrinsics) {
CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics;
double focal_length = libmv_camera_intrinsics_options->focal_length;
double principal_x = libmv_camera_intrinsics_options->principal_point_x;
double principal_y = libmv_camera_intrinsics_options->principal_point_y;
int image_width = libmv_camera_intrinsics_options->image_width;
int image_height = libmv_camera_intrinsics_options->image_height;
/* Try avoid unnecessary updates, so pre-computed distortion grids
* are not freed.
*/
if (camera_intrinsics->focal_length() != focal_length) {
camera_intrinsics->SetFocalLength(focal_length, focal_length);
}
if (camera_intrinsics->principal_point_x() != principal_x ||
camera_intrinsics->principal_point_y() != principal_y) {
camera_intrinsics->SetPrincipalPoint(principal_x, principal_y);
}
if (camera_intrinsics->image_width() != image_width ||
camera_intrinsics->image_height() != image_height) {
camera_intrinsics->SetImageSize(image_width, image_height);
}
switch (libmv_camera_intrinsics_options->distortion_model) {
case LIBMV_DISTORTION_MODEL_POLYNOMIAL:
{
assert(camera_intrinsics->GetDistortionModelType() ==
libmv::DISTORTION_MODEL_POLYNOMIAL);
PolynomialCameraIntrinsics *polynomial_intrinsics =
(PolynomialCameraIntrinsics *) camera_intrinsics;
double k1 = libmv_camera_intrinsics_options->polynomial_k1;
double k2 = libmv_camera_intrinsics_options->polynomial_k2;
double k3 = libmv_camera_intrinsics_options->polynomial_k3;
if (polynomial_intrinsics->k1() != k1 ||
polynomial_intrinsics->k2() != k2 ||
polynomial_intrinsics->k3() != k3) {
polynomial_intrinsics->SetRadialDistortion(k1, k2, k3);
}
break;
}
case LIBMV_DISTORTION_MODEL_DIVISION:
{
assert(camera_intrinsics->GetDistortionModelType() ==
libmv::DISTORTION_MODEL_DIVISION);
DivisionCameraIntrinsics *division_intrinsics =
(DivisionCameraIntrinsics *) camera_intrinsics;
double k1 = libmv_camera_intrinsics_options->division_k1;
double k2 = libmv_camera_intrinsics_options->division_k2;
if (division_intrinsics->k1() != k1 ||
division_intrinsics->k2() != k2) {
division_intrinsics->SetDistortion(k1, k2);
}
break;
}
default:
assert(!"Unknown distortion model");
}
}
void libmv_cameraIntrinsicsSetThreads(libmv_CameraIntrinsics* libmv_intrinsics,
int threads) {
CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics;
camera_intrinsics->SetThreads(threads);
}
void libmv_cameraIntrinsicsExtractOptions(
const libmv_CameraIntrinsics* libmv_intrinsics,
libmv_CameraIntrinsicsOptions* camera_intrinsics_options) {
const CameraIntrinsics *camera_intrinsics =
(const CameraIntrinsics *) libmv_intrinsics;
// Fill in options which are common for all distortion models.
camera_intrinsics_options->focal_length = camera_intrinsics->focal_length();
camera_intrinsics_options->principal_point_x =
camera_intrinsics->principal_point_x();
camera_intrinsics_options->principal_point_y =
camera_intrinsics->principal_point_y();
camera_intrinsics_options->image_width = camera_intrinsics->image_width();
camera_intrinsics_options->image_height = camera_intrinsics->image_height();
switch (camera_intrinsics->GetDistortionModelType()) {
case libmv::DISTORTION_MODEL_POLYNOMIAL:
{
const PolynomialCameraIntrinsics *polynomial_intrinsics =
static_cast<const PolynomialCameraIntrinsics *>(camera_intrinsics);
camera_intrinsics_options->distortion_model =
LIBMV_DISTORTION_MODEL_POLYNOMIAL;
camera_intrinsics_options->polynomial_k1 = polynomial_intrinsics->k1();
camera_intrinsics_options->polynomial_k2 = polynomial_intrinsics->k2();
camera_intrinsics_options->polynomial_k3 = polynomial_intrinsics->k3();
camera_intrinsics_options->polynomial_p1 = polynomial_intrinsics->p1();
camera_intrinsics_options->polynomial_p1 = polynomial_intrinsics->p2();
break;
}
case libmv::DISTORTION_MODEL_DIVISION:
{
const DivisionCameraIntrinsics *division_intrinsics =
static_cast<const DivisionCameraIntrinsics *>(camera_intrinsics);
camera_intrinsics_options->distortion_model =
LIBMV_DISTORTION_MODEL_DIVISION;
camera_intrinsics_options->division_k1 = division_intrinsics->k1();
camera_intrinsics_options->division_k2 = division_intrinsics->k2();
break;
}
default:
assert(!"Uknown distortion model");
}
}
void libmv_cameraIntrinsicsUndistortByte(
const libmv_CameraIntrinsics* libmv_intrinsics,
const unsigned char *source_image,
int width,
int height,
float overscan,
int channels,
unsigned char* destination_image) {
CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics;
camera_intrinsics->UndistortBuffer(source_image,
width, height,
overscan,
channels,
destination_image);
}
void libmv_cameraIntrinsicsUndistortFloat(
const libmv_CameraIntrinsics* libmv_intrinsics,
const float* source_image,
int width,
int height,
float overscan,
int channels,
float* destination_image) {
CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics;
intrinsics->UndistortBuffer(source_image,
width, height,
overscan,
channels,
destination_image);
}
void libmv_cameraIntrinsicsDistortByte(
const struct libmv_CameraIntrinsics* libmv_intrinsics,
const unsigned char *source_image,
int width,
int height,
float overscan,
int channels,
unsigned char *destination_image) {
CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics;
intrinsics->DistortBuffer(source_image,
width, height,
overscan,
channels,
destination_image);
}
void libmv_cameraIntrinsicsDistortFloat(
const libmv_CameraIntrinsics* libmv_intrinsics,
float* source_image,
int width,
int height,
float overscan,
int channels,
float* destination_image) {
CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics;
intrinsics->DistortBuffer(source_image,
width, height,
overscan,
channels,
destination_image);
}
void libmv_cameraIntrinsicsApply(
const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
double x,
double y,
double* x1,
double* y1) {
/* Do a lens distortion if focal length is non-zero only. */
if (libmv_camera_intrinsics_options->focal_length) {
CameraIntrinsics* camera_intrinsics =
libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options);
camera_intrinsics->ApplyIntrinsics(x, y, x1, y1);
LIBMV_OBJECT_DELETE(camera_intrinsics, CameraIntrinsics);
}
}
void libmv_cameraIntrinsicsInvert(
const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
double x,
double y,
double* x1,
double* y1) {
/* Do a lens un-distortion if focal length is non-zero only/ */
if (libmv_camera_intrinsics_options->focal_length) {
CameraIntrinsics *camera_intrinsics =
libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options);
camera_intrinsics->InvertIntrinsics(x, y, x1, y1);
LIBMV_OBJECT_DELETE(camera_intrinsics, CameraIntrinsics);
}
}
static void libmv_cameraIntrinsicsFillFromOptions(
const libmv_CameraIntrinsicsOptions* camera_intrinsics_options,
CameraIntrinsics* camera_intrinsics) {
camera_intrinsics->SetFocalLength(camera_intrinsics_options->focal_length,
camera_intrinsics_options->focal_length);
camera_intrinsics->SetPrincipalPoint(
camera_intrinsics_options->principal_point_x,
camera_intrinsics_options->principal_point_y);
camera_intrinsics->SetImageSize(camera_intrinsics_options->image_width,
camera_intrinsics_options->image_height);
switch (camera_intrinsics_options->distortion_model) {
case LIBMV_DISTORTION_MODEL_POLYNOMIAL:
{
PolynomialCameraIntrinsics *polynomial_intrinsics =
static_cast<PolynomialCameraIntrinsics*>(camera_intrinsics);
polynomial_intrinsics->SetRadialDistortion(
camera_intrinsics_options->polynomial_k1,
camera_intrinsics_options->polynomial_k2,
camera_intrinsics_options->polynomial_k3);
break;
}
case LIBMV_DISTORTION_MODEL_DIVISION:
{
DivisionCameraIntrinsics *division_intrinsics =
static_cast<DivisionCameraIntrinsics*>(camera_intrinsics);
division_intrinsics->SetDistortion(
camera_intrinsics_options->division_k1,
camera_intrinsics_options->division_k2);
break;
}
default:
assert(!"Unknown distortion model");
}
}
CameraIntrinsics* libmv_cameraIntrinsicsCreateFromOptions(
const libmv_CameraIntrinsicsOptions* camera_intrinsics_options) {
CameraIntrinsics *camera_intrinsics = NULL;
switch (camera_intrinsics_options->distortion_model) {
case LIBMV_DISTORTION_MODEL_POLYNOMIAL:
camera_intrinsics = LIBMV_OBJECT_NEW(PolynomialCameraIntrinsics);
break;
case LIBMV_DISTORTION_MODEL_DIVISION:
camera_intrinsics = LIBMV_OBJECT_NEW(DivisionCameraIntrinsics);
break;
default:
assert(!"Unknown distortion model");
}
libmv_cameraIntrinsicsFillFromOptions(camera_intrinsics_options, camera_intrinsics);
return camera_intrinsics;
}

138
extern/libmv/intern/camera_intrinsics.h vendored Normal file
View File

@ -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_

148
extern/libmv/intern/detector.cc vendored Normal file
View File

@ -0,0 +1,148 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2011 Blender Foundation.
* All rights reserved.
*
* Contributor(s): Blender Foundation,
* Sergey Sharybin
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "intern/detector.h"
#include "intern/image.h"
#include "intern/utildefines.h"
#include "libmv/simple_pipeline/detect.h"
using libmv::Detect;
using libmv::DetectOptions;
using libmv::Feature;
using libmv::FloatImage;
struct libmv_Features {
int count;
Feature* features;
};
namespace {
libmv_Features *libmv_featuresFromVector(
const libmv::vector<Feature>& features) {
libmv_Features* libmv_features = LIBMV_STRUCT_NEW(libmv_Features, 1);
int count = features.size();
if (count) {
libmv_features->features = LIBMV_STRUCT_NEW(Feature, count);
for (int i = 0; i < count; i++) {
libmv_features->features[i] = features.at(i);
}
} else {
libmv_features->features = NULL;
}
libmv_features->count = count;
return libmv_features;
}
void libmv_convertDetectorOptions(libmv_DetectOptions *options,
DetectOptions *detector_options) {
switch (options->detector) {
#define LIBMV_CONVERT(the_detector) \
case LIBMV_DETECTOR_ ## the_detector: \
detector_options->type = DetectOptions::the_detector; \
break;
LIBMV_CONVERT(FAST)
LIBMV_CONVERT(MORAVEC)
LIBMV_CONVERT(HARRIS)
#undef LIBMV_CONVERT
}
detector_options->margin = options->margin;
detector_options->min_distance = options->min_distance;
detector_options->fast_min_trackness = options->fast_min_trackness;
detector_options->moravec_max_count = options->moravec_max_count;
detector_options->moravec_pattern = options->moravec_pattern;
detector_options->harris_threshold = options->harris_threshold;
}
} // namespace
libmv_Features *libmv_detectFeaturesByte(const unsigned char* image_buffer,
int width,
int height,
int channels,
libmv_DetectOptions* options) {
// Prepare the image.
FloatImage image;
libmv_byteBufferToFloatImage(image_buffer, width, height, channels, &image);
// Configure detector.
DetectOptions detector_options;
libmv_convertDetectorOptions(options, &detector_options);
// Run the detector.
libmv::vector<Feature> detected_features;
Detect(image, detector_options, &detected_features);
// Convert result to C-API.
libmv_Features* result = libmv_featuresFromVector(detected_features);
return result;
}
libmv_Features* libmv_detectFeaturesFloat(const float* image_buffer,
int width,
int height,
int channels,
libmv_DetectOptions* options) {
// Prepare the image.
FloatImage image;
libmv_floatBufferToFloatImage(image_buffer, width, height, channels, &image);
// Configure detector.
DetectOptions detector_options;
libmv_convertDetectorOptions(options, &detector_options);
// Run the detector.
libmv::vector<Feature> detected_features;
Detect(image, detector_options, &detected_features);
// Convert result to C-API.
libmv_Features* result = libmv_featuresFromVector(detected_features);
return result;
}
void libmv_featuresDestroy(libmv_Features* libmv_features) {
if (libmv_features->features) {
LIBMV_STRUCT_DELETE(libmv_features->features);
}
LIBMV_STRUCT_DELETE(libmv_features);
}
int libmv_countFeatures(const libmv_Features* libmv_features) {
return libmv_features->count;
}
void libmv_getFeature(const libmv_Features* libmv_features,
int number,
double* x,
double* y,
double* score,
double* size) {
Feature &feature = libmv_features->features[number];
*x = feature.x;
*y = feature.y;
*score = feature.score;
*size = feature.size;
}

77
extern/libmv/intern/detector.h vendored Normal file
View File

@ -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_

59
extern/libmv/intern/homography.cc vendored Normal file
View File

@ -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));
}

43
extern/libmv/intern/homography.h vendored Normal file
View File

@ -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_

272
extern/libmv/intern/image.cc vendored Normal file
View File

@ -0,0 +1,272 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2011 Blender Foundation.
* All rights reserved.
*
* Contributor(s): Blender Foundation,
* Sergey Sharybin
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "intern/image.h"
#include "intern/utildefines.h"
#include "libmv/tracking/track_region.h"
#include <cassert>
#include <png.h>
using libmv::FloatImage;
using libmv::SamplePlanarPatch;
void libmv_floatImaheDestroy(libmv_FloatImage *image) {
delete [] image->buffer;
}
/* Image <-> buffers conversion */
void libmv_byteBufferToFloatImage(const unsigned char* buffer,
int width,
int height,
int channels,
FloatImage* image) {
image->Resize(height, width, channels);
for (int y = 0, a = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
for (int k = 0; k < channels; k++) {
(*image)(y, x, k) = (float)buffer[a++] / 255.0f;
}
}
}
}
void libmv_floatBufferToFloatImage(const float* buffer,
int width,
int height,
int channels,
FloatImage* image) {
image->Resize(height, width, channels);
for (int y = 0, a = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
for (int k = 0; k < channels; k++) {
(*image)(y, x, k) = buffer[a++];
}
}
}
}
void libmv_floatImageToFloatBuffer(const FloatImage &image,
float* buffer) {
for (int y = 0, a = 0; y < image.Height(); y++) {
for (int x = 0; x < image.Width(); x++) {
for (int k = 0; k < image.Depth(); k++) {
buffer[a++] = image(y, x, k);
}
}
}
}
void libmv_floatImageToByteBuffer(const libmv::FloatImage &image,
unsigned char* buffer) {
for (int y = 0, a= 0; y < image.Height(); y++) {
for (int x = 0; x < image.Width(); x++) {
for (int k = 0; k < image.Depth(); k++) {
buffer[a++] = image(y, x, k) * 255.0f;
}
}
}
}
static bool savePNGImage(png_bytep* row_pointers,
int width,
int height,
int depth,
int color_type,
const char* file_name) {
png_infop info_ptr;
png_structp png_ptr;
FILE *fp = fopen(file_name, "wb");
if (fp == NULL) {
return false;
}
/* Initialize stuff */
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
info_ptr = png_create_info_struct(png_ptr);
if (setjmp(png_jmpbuf(png_ptr))) {
fclose(fp);
return false;
}
png_init_io(png_ptr, fp);
/* Write PNG header. */
if (setjmp(png_jmpbuf(png_ptr))) {
fclose(fp);
return false;
}
png_set_IHDR(png_ptr,
info_ptr,
width,
height,
depth,
color_type,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);
png_write_info(png_ptr, info_ptr);
/* Write bytes/ */
if (setjmp(png_jmpbuf(png_ptr))) {
fclose(fp);
return false;
}
png_write_image(png_ptr, row_pointers);
/* End write/ */
if (setjmp(png_jmpbuf(png_ptr))) {
fclose(fp);
return false;
}
png_write_end(png_ptr, NULL);
fclose(fp);
return true;
}
bool libmv_saveImage(const FloatImage& image,
const char* prefix,
int x0,
int y0) {
int x, y;
png_bytep *row_pointers;
assert(image.Depth() == 1);
row_pointers = new png_bytep[image.Height()];
for (y = 0; y < image.Height(); y++) {
row_pointers[y] = new png_byte[4 * image.Width()];
for (x = 0; x < image.Width(); x++) {
if (x0 == x && image.Height() - y0 - 1 == y) {
row_pointers[y][x * 4 + 0] = 255;
row_pointers[y][x * 4 + 1] = 0;
row_pointers[y][x * 4 + 2] = 0;
row_pointers[y][x * 4 + 3] = 255;
} else {
float pixel = image(image.Height() - y - 1, x, 0);
row_pointers[y][x * 4 + 0] = pixel * 255;
row_pointers[y][x * 4 + 1] = pixel * 255;
row_pointers[y][x * 4 + 2] = pixel * 255;
row_pointers[y][x * 4 + 3] = 255;
}
}
}
static int image_counter = 0;
char file_name[128];
snprintf(file_name, sizeof(file_name),
"%s_%02d.png",
prefix, ++image_counter);
bool result = savePNGImage(row_pointers,
image.Width(),
image.Height(),
8,
PNG_COLOR_TYPE_RGBA,
file_name);
for (y = 0; y < image.Height(); y++) {
delete [] row_pointers[y];
}
delete [] row_pointers;
return result;
}
void libmv_samplePlanarPatchFloat(const float* image,
int width,
int height,
int channels,
const double* xs,
const double* ys,
int num_samples_x,
int num_samples_y,
const float* mask,
float* patch,
double* warped_position_x,
double* warped_position_y) {
FloatImage libmv_image, libmv_patch, libmv_mask;
FloatImage *libmv_mask_for_sample = NULL;
libmv_floatBufferToFloatImage(image, width, height, channels, &libmv_image);
if (mask) {
libmv_floatBufferToFloatImage(mask, width, height, 1, &libmv_mask);
libmv_mask_for_sample = &libmv_mask;
}
SamplePlanarPatch(libmv_image,
xs, ys,
num_samples_x, num_samples_y,
libmv_mask_for_sample,
&libmv_patch,
warped_position_x,
warped_position_y);
libmv_floatImageToFloatBuffer(libmv_patch, patch);
}
void libmv_samplePlanarPatchByte(const unsigned char* image,
int width,
int height,
int channels,
const double* xs,
const double* ys,
int num_samples_x,
int num_samples_y,
const float* mask,
unsigned char* patch,
double* warped_position_x,
double* warped_position_y) {
libmv::FloatImage libmv_image, libmv_patch, libmv_mask;
libmv::FloatImage *libmv_mask_for_sample = NULL;
libmv_byteBufferToFloatImage(image, width, height, channels, &libmv_image);
if (mask) {
libmv_floatBufferToFloatImage(mask, width, height, 1, &libmv_mask);
libmv_mask_for_sample = &libmv_mask;
}
libmv::SamplePlanarPatch(libmv_image,
xs, ys,
num_samples_x, num_samples_y,
libmv_mask_for_sample,
&libmv_patch,
warped_position_x,
warped_position_y);
libmv_floatImageToByteBuffer(libmv_patch, patch);
}

99
extern/libmv/intern/image.h vendored Normal file
View File

@ -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_

55
extern/libmv/intern/logging.cc vendored Normal file
View File

@ -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);
}

47
extern/libmv/intern/logging.h vendored Normal file
View File

@ -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_

530
extern/libmv/intern/reconstruction.cc vendored Normal file
View File

@ -0,0 +1,530 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2011 Blender Foundation.
* All rights reserved.
*
* Contributor(s): Blender Foundation,
* Sergey Sharybin
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "intern/reconstruction.h"
#include "intern/camera_intrinsics.h"
#include "intern/tracks.h"
#include "intern/utildefines.h"
#include "libmv/logging/logging.h"
#include "libmv/simple_pipeline/bundle.h"
#include "libmv/simple_pipeline/keyframe_selection.h"
#include "libmv/simple_pipeline/initialize_reconstruction.h"
#include "libmv/simple_pipeline/modal_solver.h"
#include "libmv/simple_pipeline/pipeline.h"
#include "libmv/simple_pipeline/reconstruction_scale.h"
#include "libmv/simple_pipeline/tracks.h"
using libmv::CameraIntrinsics;
using libmv::EuclideanCamera;
using libmv::EuclideanPoint;
using libmv::EuclideanReconstruction;
using libmv::EuclideanScaleToUnity;
using libmv::Marker;
using libmv::ProgressUpdateCallback;
using libmv::PolynomialCameraIntrinsics;
using libmv::Tracks;
using libmv::EuclideanBundle;
using libmv::EuclideanCompleteReconstruction;
using libmv::EuclideanReconstructTwoFrames;
using libmv::EuclideanReprojectionError;
struct libmv_Reconstruction {
EuclideanReconstruction reconstruction;
/* Used for per-track average error calculation after reconstruction */
Tracks tracks;
CameraIntrinsics *intrinsics;
double error;
};
namespace {
class ReconstructUpdateCallback : public ProgressUpdateCallback {
public:
ReconstructUpdateCallback(
reconstruct_progress_update_cb progress_update_callback,
void *callback_customdata) {
progress_update_callback_ = progress_update_callback;
callback_customdata_ = callback_customdata;
}
void invoke(double progress, const char* message) {
if (progress_update_callback_) {
progress_update_callback_(callback_customdata_, progress, message);
}
}
protected:
reconstruct_progress_update_cb progress_update_callback_;
void* callback_customdata_;
};
void libmv_solveRefineIntrinsics(
const Tracks &tracks,
const int refine_intrinsics,
const int bundle_constraints,
reconstruct_progress_update_cb progress_update_callback,
void* callback_customdata,
EuclideanReconstruction* reconstruction,
CameraIntrinsics* intrinsics) {
/* only a few combinations are supported but trust the caller/ */
int bundle_intrinsics = 0;
if (refine_intrinsics & LIBMV_REFINE_FOCAL_LENGTH) {
bundle_intrinsics |= libmv::BUNDLE_FOCAL_LENGTH;
}
if (refine_intrinsics & LIBMV_REFINE_PRINCIPAL_POINT) {
bundle_intrinsics |= libmv::BUNDLE_PRINCIPAL_POINT;
}
if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K1) {
bundle_intrinsics |= libmv::BUNDLE_RADIAL_K1;
}
if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K2) {
bundle_intrinsics |= libmv::BUNDLE_RADIAL_K2;
}
progress_update_callback(callback_customdata, 1.0, "Refining solution");
EuclideanBundleCommonIntrinsics(tracks,
bundle_intrinsics,
bundle_constraints,
reconstruction,
intrinsics);
}
void finishReconstruction(
const Tracks &tracks,
const CameraIntrinsics &camera_intrinsics,
libmv_Reconstruction *libmv_reconstruction,
reconstruct_progress_update_cb progress_update_callback,
void *callback_customdata) {
EuclideanReconstruction &reconstruction =
libmv_reconstruction->reconstruction;
/* Reprojection error calculation. */
progress_update_callback(callback_customdata, 1.0, "Finishing solution");
libmv_reconstruction->tracks = tracks;
libmv_reconstruction->error = EuclideanReprojectionError(tracks,
reconstruction,
camera_intrinsics);
}
bool selectTwoKeyframesBasedOnGRICAndVariance(
Tracks& tracks,
Tracks& normalized_tracks,
CameraIntrinsics& camera_intrinsics,
int& keyframe1,
int& keyframe2) {
libmv::vector<int> keyframes;
/* Get list of all keyframe candidates first. */
SelectKeyframesBasedOnGRICAndVariance(normalized_tracks,
camera_intrinsics,
keyframes);
if (keyframes.size() < 2) {
LG << "Not enough keyframes detected by GRIC";
return false;
} else if (keyframes.size() == 2) {
keyframe1 = keyframes[0];
keyframe2 = keyframes[1];
return true;
}
/* Now choose two keyframes with minimal reprojection error after initial
* reconstruction choose keyframes with the least reprojection error after
* solving from two candidate keyframes.
*
* In fact, currently libmv returns single pair only, so this code will
* not actually run. But in the future this could change, so let's stay
* prepared.
*/
int previous_keyframe = keyframes[0];
double best_error = std::numeric_limits<double>::max();
for (int i = 1; i < keyframes.size(); i++) {
EuclideanReconstruction reconstruction;
int current_keyframe = keyframes[i];
libmv::vector<Marker> keyframe_markers =
normalized_tracks.MarkersForTracksInBothImages(previous_keyframe,
current_keyframe);
Tracks keyframe_tracks(keyframe_markers);
/* get a solution from two keyframes only */
EuclideanReconstructTwoFrames(keyframe_markers, &reconstruction);
EuclideanBundle(keyframe_tracks, &reconstruction);
EuclideanCompleteReconstruction(keyframe_tracks,
&reconstruction,
NULL);
double current_error = EuclideanReprojectionError(tracks,
reconstruction,
camera_intrinsics);
LG << "Error between " << previous_keyframe
<< " and " << current_keyframe
<< ": " << current_error;
if (current_error < best_error) {
best_error = current_error;
keyframe1 = previous_keyframe;
keyframe2 = current_keyframe;
}
previous_keyframe = current_keyframe;
}
return true;
}
Marker libmv_projectMarker(const EuclideanPoint& point,
const EuclideanCamera& camera,
const CameraIntrinsics& intrinsics) {
libmv::Vec3 projected = camera.R * point.X + camera.t;
projected /= projected(2);
libmv::Marker reprojected_marker;
intrinsics.ApplyIntrinsics(projected(0), projected(1),
&reprojected_marker.x,
&reprojected_marker.y);
reprojected_marker.image = camera.image;
reprojected_marker.track = point.track;
return reprojected_marker;
}
void libmv_getNormalizedTracks(const Tracks &tracks,
const CameraIntrinsics &camera_intrinsics,
Tracks *normalized_tracks)
{
libmv::vector<Marker> markers = tracks.AllMarkers();
for (int i = 0; i < markers.size(); ++i) {
Marker &marker = markers[i];
camera_intrinsics.InvertIntrinsics(marker.x, marker.y,
&marker.x, &marker.y);
normalized_tracks->Insert(marker.image,
marker.track,
marker.x, marker.y,
marker.weight);
}
}
} // namespace
libmv_Reconstruction *libmv_solveReconstruction(
const libmv_Tracks* libmv_tracks,
const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
libmv_ReconstructionOptions* libmv_reconstruction_options,
reconstruct_progress_update_cb progress_update_callback,
void* callback_customdata) {
libmv_Reconstruction *libmv_reconstruction =
LIBMV_OBJECT_NEW(libmv_Reconstruction);
Tracks &tracks = *((Tracks *) libmv_tracks);
EuclideanReconstruction &reconstruction =
libmv_reconstruction->reconstruction;
ReconstructUpdateCallback update_callback =
ReconstructUpdateCallback(progress_update_callback,
callback_customdata);
/* Retrieve reconstruction options from C-API to libmv API. */
CameraIntrinsics *camera_intrinsics;
camera_intrinsics = libmv_reconstruction->intrinsics =
libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options);
/* Invert the camera intrinsics/ */
Tracks normalized_tracks;
libmv_getNormalizedTracks(tracks, *camera_intrinsics, &normalized_tracks);
/* keyframe selection. */
int keyframe1 = libmv_reconstruction_options->keyframe1,
keyframe2 = libmv_reconstruction_options->keyframe2;
if (libmv_reconstruction_options->select_keyframes) {
LG << "Using automatic keyframe selection";
update_callback.invoke(0, "Selecting keyframes");
selectTwoKeyframesBasedOnGRICAndVariance(tracks,
normalized_tracks,
*camera_intrinsics,
keyframe1,
keyframe2);
/* so keyframes in the interface would be updated */
libmv_reconstruction_options->keyframe1 = keyframe1;
libmv_reconstruction_options->keyframe2 = keyframe2;
}
/* Actual reconstruction. */
LG << "frames to init from: " << keyframe1 << " " << keyframe2;
libmv::vector<Marker> keyframe_markers =
normalized_tracks.MarkersForTracksInBothImages(keyframe1, keyframe2);
LG << "number of markers for init: " << keyframe_markers.size();
update_callback.invoke(0, "Initial reconstruction");
EuclideanReconstructTwoFrames(keyframe_markers, &reconstruction);
EuclideanBundle(normalized_tracks, &reconstruction);
EuclideanCompleteReconstruction(normalized_tracks,
&reconstruction,
&update_callback);
/* Refinement/ */
if (libmv_reconstruction_options->refine_intrinsics) {
libmv_solveRefineIntrinsics(
tracks,
libmv_reconstruction_options->refine_intrinsics,
libmv::BUNDLE_NO_CONSTRAINTS,
progress_update_callback,
callback_customdata,
&reconstruction,
camera_intrinsics);
}
/* Set reconstruction scale to unity. */
EuclideanScaleToUnity(&reconstruction);
/* Finish reconstruction. */
finishReconstruction(tracks,
*camera_intrinsics,
libmv_reconstruction,
progress_update_callback,
callback_customdata);
return (libmv_Reconstruction *) libmv_reconstruction;
}
libmv_Reconstruction *libmv_solveModal(
const libmv_Tracks *libmv_tracks,
const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options,
const libmv_ReconstructionOptions *libmv_reconstruction_options,
reconstruct_progress_update_cb progress_update_callback,
void *callback_customdata) {
libmv_Reconstruction *libmv_reconstruction =
LIBMV_OBJECT_NEW(libmv_Reconstruction);
Tracks &tracks = *((Tracks *) libmv_tracks);
EuclideanReconstruction &reconstruction =
libmv_reconstruction->reconstruction;
ReconstructUpdateCallback update_callback =
ReconstructUpdateCallback(progress_update_callback,
callback_customdata);
/* Retrieve reconstruction options from C-API to libmv API. */
CameraIntrinsics *camera_intrinsics;
camera_intrinsics = libmv_reconstruction->intrinsics =
libmv_cameraIntrinsicsCreateFromOptions(
libmv_camera_intrinsics_options);
/* Invert the camera intrinsics. */
Tracks normalized_tracks;
libmv_getNormalizedTracks(tracks, *camera_intrinsics, &normalized_tracks);
/* Actual reconstruction. */
ModalSolver(normalized_tracks, &reconstruction, &update_callback);
PolynomialCameraIntrinsics empty_intrinsics;
EuclideanBundleCommonIntrinsics(normalized_tracks,
libmv::BUNDLE_NO_INTRINSICS,
libmv::BUNDLE_NO_TRANSLATION,
&reconstruction,
&empty_intrinsics);
/* Refinement. */
if (libmv_reconstruction_options->refine_intrinsics) {
libmv_solveRefineIntrinsics(
tracks,
libmv_reconstruction_options->refine_intrinsics,
libmv::BUNDLE_NO_TRANSLATION,
progress_update_callback, callback_customdata,
&reconstruction,
camera_intrinsics);
}
/* Finish reconstruction. */
finishReconstruction(tracks,
*camera_intrinsics,
libmv_reconstruction,
progress_update_callback,
callback_customdata);
return (libmv_Reconstruction *) libmv_reconstruction;
}
void libmv_reconstructionDestroy(libmv_Reconstruction *libmv_reconstruction) {
LIBMV_OBJECT_DELETE(libmv_reconstruction->intrinsics, CameraIntrinsics);
LIBMV_OBJECT_DELETE(libmv_reconstruction, libmv_Reconstruction);
}
int libmv_reprojectionPointForTrack(
const libmv_Reconstruction *libmv_reconstruction,
int track,
double pos[3]) {
const EuclideanReconstruction *reconstruction =
&libmv_reconstruction->reconstruction;
const EuclideanPoint *point =
reconstruction->PointForTrack(track);
if (point) {
pos[0] = point->X[0];
pos[1] = point->X[2];
pos[2] = point->X[1];
return 1;
}
return 0;
}
double libmv_reprojectionErrorForTrack(
const libmv_Reconstruction *libmv_reconstruction,
int track) {
const EuclideanReconstruction *reconstruction =
&libmv_reconstruction->reconstruction;
const CameraIntrinsics *intrinsics = libmv_reconstruction->intrinsics;
libmv::vector<Marker> markers =
libmv_reconstruction->tracks.MarkersForTrack(track);
int num_reprojected = 0;
double total_error = 0.0;
for (int i = 0; i < markers.size(); ++i) {
double weight = markers[i].weight;
const EuclideanCamera *camera =
reconstruction->CameraForImage(markers[i].image);
const EuclideanPoint *point =
reconstruction->PointForTrack(markers[i].track);
if (!camera || !point || weight == 0.0) {
continue;
}
num_reprojected++;
Marker reprojected_marker =
libmv_projectMarker(*point, *camera, *intrinsics);
double ex = (reprojected_marker.x - markers[i].x) * weight;
double ey = (reprojected_marker.y - markers[i].y) * weight;
total_error += sqrt(ex * ex + ey * ey);
}
return total_error / num_reprojected;
}
double libmv_reprojectionErrorForImage(
const libmv_Reconstruction *libmv_reconstruction,
int image) {
const EuclideanReconstruction *reconstruction =
&libmv_reconstruction->reconstruction;
const CameraIntrinsics *intrinsics = libmv_reconstruction->intrinsics;
libmv::vector<Marker> markers =
libmv_reconstruction->tracks.MarkersInImage(image);
const EuclideanCamera *camera = reconstruction->CameraForImage(image);
int num_reprojected = 0;
double total_error = 0.0;
if (!camera) {
return 0.0;
}
for (int i = 0; i < markers.size(); ++i) {
const EuclideanPoint *point =
reconstruction->PointForTrack(markers[i].track);
if (!point) {
continue;
}
num_reprojected++;
Marker reprojected_marker =
libmv_projectMarker(*point, *camera, *intrinsics);
double ex = (reprojected_marker.x - markers[i].x) * markers[i].weight;
double ey = (reprojected_marker.y - markers[i].y) * markers[i].weight;
total_error += sqrt(ex * ex + ey * ey);
}
return total_error / num_reprojected;
}
int libmv_reprojectionCameraForImage(
const libmv_Reconstruction *libmv_reconstruction,
int image,
double mat[4][4]) {
const EuclideanReconstruction *reconstruction =
&libmv_reconstruction->reconstruction;
const EuclideanCamera *camera =
reconstruction->CameraForImage(image);
if (camera) {
for (int j = 0; j < 3; ++j) {
for (int k = 0; k < 3; ++k) {
int l = k;
if (k == 1) {
l = 2;
} else if (k == 2) {
l = 1;
}
if (j == 2) {
mat[j][l] = -camera->R(j, k);
} else {
mat[j][l] = camera->R(j, k);
}
}
mat[j][3] = 0.0;
}
libmv::Vec3 optical_center = -camera->R.transpose() * camera->t;
mat[3][0] = optical_center(0);
mat[3][1] = optical_center(2);
mat[3][2] = optical_center(1);
mat[3][3] = 1.0;
return 1;
}
return 0;
}
double libmv_reprojectionError(
const libmv_Reconstruction *libmv_reconstruction) {
return libmv_reconstruction->error;
}
libmv_CameraIntrinsics *libmv_reconstructionExtractIntrinsics(
libmv_Reconstruction *libmv_reconstruction) {
return (libmv_CameraIntrinsics *) libmv_reconstruction->intrinsics;
}

99
extern/libmv/intern/reconstruction.h vendored Normal file
View File

@ -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_

43
extern/libmv/intern/region.h vendored Normal file
View File

@ -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_

330
extern/libmv/intern/stub.cc vendored Normal file
View File

@ -0,0 +1,330 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2013 Blender Foundation.
* All rights reserved.
*
* Contributor(s): Blender Foundation,
* Sergey Sharybin
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "libmv-capi.h"
#include <cstdlib>
#include <cstring>
/* ************ Logging ************ */
void libmv_initLogging(const char * /*argv0*/) {
}
void libmv_startDebugLogging(void) {
}
void libmv_setLoggingVerbosity(int /*verbosity*/) {
}
/* ************ Planar tracker ************ */
/* TrackRegion (new planar tracker) */
int libmv_trackRegion(const libmv_TrackRegionOptions * /*options*/,
const float * /*image1*/,
int /*image1_width*/,
int /*image1_height*/,
const float * /*image2*/,
int /*image2_width*/,
int /*image2_height*/,
const double *x1,
const double *y1,
libmv_TrackRegionResult *result,
double *x2,
double *y2) {
/* Convert to doubles for the libmv api. The four corners and the center. */
for (int i = 0; i < 5; ++i) {
x2[i] = x1[i];
y2[i] = y1[i];
}
result->termination = -1;
result->termination_reason = "Built without libmv support";
result->correlation = 0.0;
return false;
}
void libmv_samplePlanarPatchFloat(const float * /*image*/,
int /*width*/,
int /*height*/,
int /*channels*/,
const double * /*xs*/,
const double * /*ys*/,
int /*num_samples_x*/,
int /*num_samples_y*/,
const float * /*mask*/,
float * /*patch*/,
double * /*warped_position_x*/,
double * /*warped_position_y*/) {
/* TODO(sergey): implement */
}
void libmv_samplePlanarPatchByte(const unsigned char * /*image*/,
int /*width*/,
int /*height*/,
int /*channels*/,
const double * /*xs*/,
const double * /*ys*/,
int /*num_samples_x*/, int /*num_samples_y*/,
const float * /*mask*/,
unsigned char * /*patch*/,
double * /*warped_position_x*/,
double * /*warped_position_y*/) {
/* TODO(sergey): implement */
}
/* ************ Tracks ************ */
libmv_Tracks *libmv_tracksNew(void) {
return NULL;
}
void libmv_tracksInsert(libmv_Tracks * /*libmv_tracks*/,
int /*image*/,
int /*track*/,
double /*x*/,
double /*y*/,
double /*weight*/) {
}
void libmv_tracksDestroy(libmv_Tracks * /*libmv_tracks*/) {
}
/* ************ Reconstruction solver ************ */
libmv_Reconstruction *libmv_solveReconstruction(
const libmv_Tracks * /*libmv_tracks*/,
const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/,
libmv_ReconstructionOptions * /*libmv_reconstruction_options*/,
reconstruct_progress_update_cb /*progress_update_callback*/,
void * /*callback_customdata*/) {
return NULL;
}
libmv_Reconstruction *libmv_solveModal(
const libmv_Tracks * /*libmv_tracks*/,
const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/,
const libmv_ReconstructionOptions * /*libmv_reconstruction_options*/,
reconstruct_progress_update_cb /*progress_update_callback*/,
void * /*callback_customdata*/) {
return NULL;
}
int libmv_reprojectionPointForTrack(
const libmv_Reconstruction * /*libmv_reconstruction*/,
int /*track*/,
double /*pos*/[3]) {
return 0;
}
double libmv_reprojectionErrorForTrack(
const libmv_Reconstruction * /*libmv_reconstruction*/,
int /*track*/) {
return 0.0;
}
double libmv_reprojectionErrorForImage(
const libmv_Reconstruction * /*libmv_reconstruction*/,
int /*image*/) {
return 0.0;
}
int libmv_reprojectionCameraForImage(
const libmv_Reconstruction * /*libmv_reconstruction*/,
int /*image*/,
double /*mat*/[4][4]) {
return 0;
}
double libmv_reprojectionError(
const libmv_Reconstruction * /*libmv_reconstruction*/) {
return 0.0;
}
void libmv_reconstructionDestroy(
struct libmv_Reconstruction * /*libmv_reconstruction*/) {
}
/* ************ Feature detector ************ */
libmv_Features *libmv_detectFeaturesByte(const unsigned char */*image_buffer*/,
int /*width*/,
int /*height*/,
int /*channels*/,
libmv_DetectOptions */*options*/) {
return NULL;
}
struct libmv_Features *libmv_detectFeaturesFloat(
const float */*image_buffer*/,
int /*width*/,
int /*height*/,
int /*channels*/,
libmv_DetectOptions */*options*/) {
return NULL;
}
int libmv_countFeatures(const libmv_Features * /*libmv_features*/) {
return 0;
}
void libmv_getFeature(const libmv_Features * /*libmv_features*/,
int /*number*/,
double *x,
double *y,
double *score,
double *size) {
*x = 0.0;
*y = 0.0;
*score = 0.0;
*size = 0.0;
}
void libmv_featuresDestroy(struct libmv_Features * /*libmv_features*/) {
}
/* ************ Camera intrinsics ************ */
libmv_CameraIntrinsics *libmv_reconstructionExtractIntrinsics(
libmv_Reconstruction * /*libmv_reconstruction*/) {
return NULL;
}
libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew(
const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/) {
return NULL;
}
libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy(
const libmv_CameraIntrinsics * /*libmvIntrinsics*/) {
return NULL;
}
void libmv_cameraIntrinsicsDestroy(
libmv_CameraIntrinsics * /*libmvIntrinsics*/) {
}
void libmv_cameraIntrinsicsUpdate(
const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/,
libmv_CameraIntrinsics * /*libmv_intrinsics*/) {
}
void libmv_cameraIntrinsicsSetThreads(
libmv_CameraIntrinsics * /*libmv_intrinsics*/,
int /*threads*/) {
}
void libmv_cameraIntrinsicsExtractOptions(
const libmv_CameraIntrinsics */*libmv_intrinsics*/,
libmv_CameraIntrinsicsOptions *camera_intrinsics_options) {
memset(camera_intrinsics_options, 0, sizeof(libmv_CameraIntrinsicsOptions));
camera_intrinsics_options->focal_length = 1.0;
}
void libmv_cameraIntrinsicsUndistortByte(
const libmv_CameraIntrinsics * /*libmv_intrinsics*/,
const unsigned char *source_image,
int width, int height,
float overscan, int channels,
unsigned char *destination_image) {
memcpy(destination_image, source_image,
channels * width * height * sizeof(unsigned char));
}
void libmv_cameraIntrinsicsUndistortFloat(
const libmv_CameraIntrinsics* /*libmv_intrinsics*/,
const float* source_image,
int width,
int height,
float overscan,
int channels,
float* destination_image) {
memcpy(destination_image, source_image,
channels * width * height * sizeof(float));
}
void libmv_cameraIntrinsicsDistortByte(
const struct libmv_CameraIntrinsics* /*libmv_intrinsics*/,
const unsigned char *source_image,
int width,
int height,
float overscan,
int channels,
unsigned char *destination_image) {
memcpy(destination_image, source_image,
channels * width * height * sizeof(unsigned char));
}
void libmv_cameraIntrinsicsDistortFloat(
const libmv_CameraIntrinsics* /*libmv_intrinsics*/,
float* source_image,
int width,
int height,
float overscan,
int channels,
float* destination_image) {
memcpy(destination_image, source_image,
channels * width * height * sizeof(float));
}
/* ************ utils ************ */
void libmv_cameraIntrinsicsApply(
const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
double x,
double y,
double* x1,
double* y1) {
double focal_length = libmv_camera_intrinsics_options->focal_length;
double principal_x = libmv_camera_intrinsics_options->principal_point_x;
double principal_y = libmv_camera_intrinsics_options->principal_point_y;
*x1 = x * focal_length + principal_x;
*y1 = y * focal_length + principal_y;
}
void libmv_cameraIntrinsicsInvert(
const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
double x,
double y,
double* x1,
double* y1) {
double focal_length = libmv_camera_intrinsics_options->focal_length;
double principal_x = libmv_camera_intrinsics_options->principal_point_x;
double principal_y = libmv_camera_intrinsics_options->principal_point_y;
*x1 = (x - principal_x) / focal_length;
*y1 = (y - principal_y) / focal_length;
}
void libmv_homography2DFromCorrespondencesEuc(/* const */ double (*x1)[2],
/* const */ double (*x2)[2],
int num_points,
double H[3][3]) {
memset(H, 0, sizeof(double[3][3]));
H[0][0] = 1.0f;
H[1][1] = 1.0f;
H[2][2] = 1.0f;
}

177
extern/libmv/intern/track_region.cc vendored Normal file
View File

@ -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;
}

81
extern/libmv/intern/track_region.h vendored Normal file
View File

@ -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_

52
extern/libmv/intern/tracks.cc vendored Normal file
View File

@ -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);
}

51
extern/libmv/intern/tracks.h vendored Normal file
View File

@ -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_

View File

@ -23,8 +23,8 @@
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef LIBMV_C_API_INTERN_H
#define LIBMV_C_API_INTERN_H
#ifndef LIBMV_C_API_UTILDEFINES_H_
#define LIBMV_C_API_UTILDEFINES_H_
#if defined(_MSC_VER)
# define __func__ __FUNCTION__
@ -36,24 +36,27 @@
# 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_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)
new(malloc(sizeof(type))) type(args)
# else
# define LIBMV_OBJECT_NEW(type, ...) \
new(malloc(sizeof(type))) type(__VA_ARGS__)
new(malloc(sizeof(type))) type(__VA_ARGS__)
#endif
# define LIBMV_OBJECT_DELETE(what, type) \
{ if(what) { \
((type*)(what))->~type(); \
free(what); \
} } (void)0
{ \
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
#endif // LIBMV_C_API_UTILDEFINES_H_

File diff suppressed because it is too large Load Diff

View File

@ -27,180 +27,13 @@
#ifndef LIBMV_C_API_H
#define LIBMV_C_API_H
#ifdef __cplusplus
extern "C" {
#endif
#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"
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
#endif // LIBMV_C_API_H

View File

@ -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 <cstdlib>
#include <cstring>
/* ************ Logging ************ */
void libmv_initLogging(const char * /*argv0*/)
{
}
void libmv_startDebugLogging(void)
{
}
void libmv_setLoggingVerbosity(int /*verbosity*/)
{
}
/* ************ Planar tracker ************ */
/* TrackRegion (new planar tracker) */
int libmv_trackRegion(const libmv_TrackRegionOptions * /*options*/,
const float * /*image1*/, int /*image1_width*/, int /*image1_height*/,
const float * /*image2*/, int /*image2_width*/, int /*image2_height*/,
const double *x1, const double *y1,
libmv_TrackRegionResult *result,
double *x2, double *y2)
{
/* Convert to doubles for the libmv api. The four corners and the center. */
for (int i = 0; i < 5; ++i) {
x2[i] = x1[i];
y2[i] = y1[i];
}
result->termination = -1;
result->termination_reason = "Built without libmv support";
result->correlation = 0.0;
return false;
}
void libmv_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

View File

@ -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 <cassert>
#include <png.h>
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<PolynomialCameraIntrinsics*>(camera_intrinsics);
polynomial_intrinsics->SetRadialDistortion(
camera_intrinsics_options->polynomial_k1,
camera_intrinsics_options->polynomial_k2,
camera_intrinsics_options->polynomial_k3);
break;
}
case LIBMV_DISTORTION_MODEL_DIVISION:
{
DivisionCameraIntrinsics *division_intrinsics =
static_cast<DivisionCameraIntrinsics*>(camera_intrinsics);
division_intrinsics->SetDistortion(
camera_intrinsics_options->division_k1,
camera_intrinsics_options->division_k2);
break;
}
default:
assert(!"Unknown distortion model");
}
}
CameraIntrinsics *libmv_cameraIntrinsicsCreateFromOptions(
const libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
{
CameraIntrinsics *camera_intrinsics = NULL;
switch (camera_intrinsics_options->distortion_model) {
case LIBMV_DISTORTION_MODEL_POLYNOMIAL:
camera_intrinsics = LIBMV_OBJECT_NEW(PolynomialCameraIntrinsics);
break;
case LIBMV_DISTORTION_MODEL_DIVISION:
camera_intrinsics = LIBMV_OBJECT_NEW(DivisionCameraIntrinsics);
break;
default:
assert(!"Unknown distortion model");
}
libmv_cameraIntrinsicsFillFromOptions(camera_intrinsics_options, camera_intrinsics);
return camera_intrinsics;
}
/* Reconstruction utilities */
void libmv_getNormalizedTracks(const Tracks &tracks,
const CameraIntrinsics &camera_intrinsics,
Tracks *normalized_tracks)
{
libmv::vector<Marker> markers = tracks.AllMarkers();
for (int i = 0; i < markers.size(); ++i) {
Marker &marker = markers[i];
camera_intrinsics.InvertIntrinsics(marker.x, marker.y,
&marker.x, &marker.y);
normalized_tracks->Insert(marker.image, marker.track,
marker.x, marker.y,
marker.weight);
}
}
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;
}

View File

@ -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

View File

@ -1789,13 +1789,19 @@ ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking *
if (ibuf->rect_float) {
if (undistort) {
libmv_cameraIntrinsicsUndistortFloat(distortion->intrinsics,
ibuf->rect_float, resibuf->rect_float,
ibuf->x, ibuf->y, overscan, ibuf->channels);
ibuf->rect_float,
ibuf->x, ibuf->y,
overscan,
ibuf->channels,
resibuf->rect_float);
}
else {
libmv_cameraIntrinsicsDistortFloat(distortion->intrinsics,
ibuf->rect_float, resibuf->rect_float,
ibuf->x, ibuf->y, overscan, ibuf->channels);
ibuf->rect_float,
ibuf->x, ibuf->y,
overscan,
ibuf->channels,
resibuf->rect_float);
}
if (ibuf->rect)
@ -1804,13 +1810,19 @@ ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking *
else {
if (undistort) {
libmv_cameraIntrinsicsUndistortByte(distortion->intrinsics,
(unsigned char *)ibuf->rect, (unsigned char *)resibuf->rect,
ibuf->x, ibuf->y, overscan, ibuf->channels);
(unsigned char *)ibuf->rect,
ibuf->x, ibuf->y,
overscan,
ibuf->channels,
(unsigned char *)resibuf->rect);
}
else {
libmv_cameraIntrinsicsDistortByte(distortion->intrinsics,
(unsigned char *)ibuf->rect, (unsigned char *)resibuf->rect,
ibuf->x, ibuf->y, overscan, ibuf->channels);
(unsigned char *)ibuf->rect,
ibuf->x, ibuf->y,
overscan,
ibuf->channels,
(unsigned char *)resibuf->rect);
}
}
@ -2017,14 +2029,14 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *sea
}
if (search_ibuf->rect_float) {
libmv_samplePlanarPatch(search_ibuf->rect_float,
search_ibuf->x, search_ibuf->y, 4,
src_pixel_x, src_pixel_y,
num_samples_x, num_samples_y,
mask,
pattern_ibuf->rect_float,
&warped_position_x,
&warped_position_y);
libmv_samplePlanarPatchFloat(search_ibuf->rect_float,
search_ibuf->x, search_ibuf->y, 4,
src_pixel_x, src_pixel_y,
num_samples_x, num_samples_y,
mask,
pattern_ibuf->rect_float,
&warped_position_x,
&warped_position_y);
}
else {
libmv_samplePlanarPatchByte((unsigned char *) search_ibuf->rect,