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:
parent
34abb614f1
commit
058e3f087e
|
@ -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()
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
|
@ -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));
|
||||
}
|
|
@ -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_
|
|
@ -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);
|
||||
}
|
|
@ -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_
|
|
@ -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);
|
||||
}
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
|
@ -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_
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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_
|
|
@ -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);
|
||||
}
|
|
@ -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_
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue