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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/libmv/libmv-capi.cc')
-rw-r--r--extern/libmv/libmv-capi.cc1185
1 files changed, 0 insertions, 1185 deletions
diff --git a/extern/libmv/libmv-capi.cc b/extern/libmv/libmv-capi.cc
deleted file mode 100644
index 82143d50fbf..00000000000
--- a/extern/libmv/libmv-capi.cc
+++ /dev/null
@@ -1,1185 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2011 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): Blender Foundation,
- * Sergey Sharybin
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifdef WITH_LIBMV
-
-/* define this to generate PNG images with content of search areas
- tracking between which failed */
-#undef DUMP_FAILURE
-
-/* define this to generate PNG images with content of search areas
- on every itteration of tracking */
-#undef DUMP_ALWAYS
-
-#include "libmv-capi.h"
-#include "libmv-util.h"
-
-#include <cassert>
-
-#include "libmv-capi_intern.h"
-#include "libmv/logging/logging.h"
-#include "libmv/multiview/homography.h"
-#include "libmv/tracking/track_region.h"
-#include "libmv/simple_pipeline/callbacks.h"
-#include "libmv/simple_pipeline/tracks.h"
-#include "libmv/simple_pipeline/initialize_reconstruction.h"
-#include "libmv/simple_pipeline/bundle.h"
-#include "libmv/simple_pipeline/detect.h"
-#include "libmv/simple_pipeline/pipeline.h"
-#include "libmv/simple_pipeline/camera_intrinsics.h"
-#include "libmv/simple_pipeline/modal_solver.h"
-#include "libmv/simple_pipeline/reconstruction_scale.h"
-#include "libmv/simple_pipeline/keyframe_selection.h"
-
-#ifdef _MSC_VER
-# define snprintf _snprintf
-#endif
-
-using libmv::CameraIntrinsics;
-using libmv::DetectOptions;
-using libmv::DivisionCameraIntrinsics;
-using libmv::EuclideanCamera;
-using libmv::EuclideanPoint;
-using libmv::EuclideanReconstruction;
-using libmv::EuclideanScaleToUnity;
-using libmv::Feature;
-using libmv::FloatImage;
-using libmv::Marker;
-using libmv::PolynomialCameraIntrinsics;
-using libmv::ProgressUpdateCallback;
-using libmv::Tracks;
-using libmv::TrackRegionOptions;
-using libmv::TrackRegionResult;
-
-using libmv::Detect;
-using libmv::EuclideanBundle;
-using libmv::EuclideanCompleteReconstruction;
-using libmv::EuclideanReconstructTwoFrames;
-using libmv::EuclideanReprojectionError;
-using libmv::TrackRegion;
-using libmv::SamplePlanarPatch;
-
-typedef struct libmv_Tracks libmv_Tracks;
-typedef struct libmv_Reconstruction libmv_Reconstruction;
-typedef struct libmv_Features libmv_Features;
-typedef struct libmv_CameraIntrinsics libmv_CameraIntrinsics;
-
-struct libmv_Reconstruction {
- EuclideanReconstruction reconstruction;
-
- /* used for per-track average error calculation after reconstruction */
- Tracks tracks;
- CameraIntrinsics *intrinsics;
-
- double error;
-};
-
-struct libmv_Features {
- int count;
- Feature *features;
-};
-
-/* ************ Logging ************ */
-
-void libmv_initLogging(const char *argv0)
-{
- /* Make it so FATAL messages are always print into console */
- char severity_fatal[32];
- snprintf(severity_fatal, sizeof(severity_fatal), "%d",
- google::GLOG_FATAL);
-
- google::InitGoogleLogging(argv0);
- google::SetCommandLineOption("logtostderr", "1");
- google::SetCommandLineOption("v", "0");
- google::SetCommandLineOption("stderrthreshold", severity_fatal);
- google::SetCommandLineOption("minloglevel", severity_fatal);
-}
-
-void libmv_startDebugLogging(void)
-{
- google::SetCommandLineOption("logtostderr", "1");
- google::SetCommandLineOption("v", "2");
- google::SetCommandLineOption("stderrthreshold", "1");
- google::SetCommandLineOption("minloglevel", "0");
-}
-
-void libmv_setLoggingVerbosity(int verbosity)
-{
- char val[10];
- snprintf(val, sizeof(val), "%d", verbosity);
-
- google::SetCommandLineOption("v", val);
-}
-
-/* ************ Planar tracker ************ */
-
-/* TrackRegion */
-int libmv_trackRegion(const libmv_TrackRegionOptions *options,
- const float *image1, int image1_width, int image1_height,
- const float *image2, int image2_width, int image2_height,
- const double *x1, const double *y1,
- libmv_TrackRegionResult *result,
- double *x2, double *y2)
-{
- double xx1[5], yy1[5];
- double xx2[5], yy2[5];
- bool tracking_result = false;
-
- /* Convert to doubles for the libmv api. The four corners and the center. */
- for (int i = 0; i < 5; ++i) {
- xx1[i] = x1[i];
- yy1[i] = y1[i];
- xx2[i] = x2[i];
- yy2[i] = y2[i];
- }
-
- TrackRegionOptions track_region_options;
- FloatImage image1_mask;
-
- switch (options->motion_model) {
-#define LIBMV_CONVERT(the_model) \
- case TrackRegionOptions::the_model: \
- track_region_options.mode = TrackRegionOptions::the_model; \
- break;
- LIBMV_CONVERT(TRANSLATION)
- LIBMV_CONVERT(TRANSLATION_ROTATION)
- LIBMV_CONVERT(TRANSLATION_SCALE)
- LIBMV_CONVERT(TRANSLATION_ROTATION_SCALE)
- LIBMV_CONVERT(AFFINE)
- LIBMV_CONVERT(HOMOGRAPHY)
-#undef LIBMV_CONVERT
- }
-
- track_region_options.minimum_correlation = options->minimum_correlation;
- track_region_options.max_iterations = options->num_iterations;
- track_region_options.sigma = options->sigma;
- track_region_options.num_extra_points = 1;
- track_region_options.image1_mask = NULL;
- track_region_options.use_brute_initialization = options->use_brute;
- /* TODO(keir): This will make some cases better, but may be a regression until
- * the motion model is in. Since this is on trunk, enable it for now.
- *
- * TODO(sergey): This gives much worse results on mango footage (see 04_2e)
- * so disabling for now for until proper prediction model is landed.
- *
- * The thing is, currently blender sends input coordinates as the guess to
- * region tracker and in case of fast motion such an early out ruins the track.
- */
- track_region_options.attempt_refine_before_brute = false;
- track_region_options.use_normalized_intensities = options->use_normalization;
-
- if (options->image1_mask) {
- libmv_floatBufferToImage(options->image1_mask,
- image1_width, image1_height, 1,
- &image1_mask);
-
- track_region_options.image1_mask = &image1_mask;
- }
-
- /* Convert from raw float buffers to libmv's FloatImage. */
- FloatImage old_patch, new_patch;
- libmv_floatBufferToImage(image1,
- image1_width, image1_height, 1,
- &old_patch);
- libmv_floatBufferToImage(image2,
- image2_width, image2_height, 1,
- &new_patch);
-
- TrackRegionResult track_region_result;
- TrackRegion(old_patch, new_patch,
- xx1, yy1,
- track_region_options,
- xx2, yy2,
- &track_region_result);
-
- /* Convert to floats for the blender api. */
- for (int i = 0; i < 5; ++i) {
- x2[i] = xx2[i];
- y2[i] = yy2[i];
- }
-
- /* TODO(keir): Update the termination string with failure details. */
- if (track_region_result.termination == TrackRegionResult::CONVERGENCE ||
- track_region_result.termination == TrackRegionResult::NO_CONVERGENCE)
- {
- tracking_result = true;
- }
-
- /* Debug dump of patches. */
-#if defined(DUMP_FAILURE) || defined(DUMP_ALWAYS)
- {
- bool need_dump = !tracking_result;
-
-# ifdef DUMP_ALWAYS
- need_dump = true;
-# endif
-
- if (need_dump) {
- libmv_saveImage(old_patch, "old_patch", x1[4], y1[4]);
- libmv_saveImage(new_patch, "new_patch", x2[4], y2[4]);
-
- if (options->image1_mask) {
- libmv_saveImage(image1_mask, "mask", x2[4], y2[4]);
- }
- }
- }
-#endif
-
- return tracking_result;
-}
-
-void libmv_samplePlanarPatch(const float *image,
- int width, int height, int channels,
- const double *xs, const double *ys,
- int num_samples_x, int num_samples_y,
- const float *mask,
- float *patch,
- double *warped_position_x,
- double *warped_position_y)
-{
- FloatImage libmv_image, libmv_patch, libmv_mask;
- FloatImage *libmv_mask_for_sample = NULL;
-
- libmv_floatBufferToImage(image, width, height, channels, &libmv_image);
-
- if (mask) {
- libmv_floatBufferToImage(mask, width, height, 1, &libmv_mask);
-
- libmv_mask_for_sample = &libmv_mask;
- }
-
- SamplePlanarPatch(libmv_image,
- xs, ys,
- num_samples_x, num_samples_y,
- libmv_mask_for_sample,
- &libmv_patch,
- warped_position_x,
- warped_position_y);
-
- libmv_imageToFloatBuffer(libmv_patch, patch);
-}
-
- void libmv_samplePlanarPatchByte(const unsigned char *image,
- int width, int height, int channels,
- const double *xs, const double *ys,
- int num_samples_x, int num_samples_y,
- const float *mask,
- unsigned char *patch,
- double *warped_position_x, double *warped_position_y)
-{
- libmv::FloatImage libmv_image, libmv_patch, libmv_mask;
- libmv::FloatImage *libmv_mask_for_sample = NULL;
-
- libmv_byteBufferToImage(image, width, height, channels, &libmv_image);
-
- if (mask) {
- libmv_floatBufferToImage(mask, width, height, 1, &libmv_mask);
-
- libmv_mask_for_sample = &libmv_mask;
- }
-
- libmv::SamplePlanarPatch(libmv_image, xs, ys,
- num_samples_x, num_samples_y,
- libmv_mask_for_sample,
- &libmv_patch,
- warped_position_x,
- warped_position_y);
-
- libmv_imageToByteBuffer(libmv_patch, patch);
-}
-
-/* ************ Tracks ************ */
-
-libmv_Tracks *libmv_tracksNew(void)
-{
- Tracks *libmv_tracks = LIBMV_OBJECT_NEW(Tracks);
-
- return (libmv_Tracks *) libmv_tracks;
-}
-
-void libmv_tracksDestroy(libmv_Tracks *libmv_tracks)
-{
- LIBMV_OBJECT_DELETE(libmv_tracks, Tracks);
-}
-
-void libmv_tracksInsert(libmv_Tracks *libmv_tracks,
- int image, int track,
- double x, double y,
- double weight)
-{
- ((Tracks *) libmv_tracks)->Insert(image, track, x, y, weight);
-}
-
-/* ************ Reconstruction ************ */
-
-namespace {
-
-class ReconstructUpdateCallback : public ProgressUpdateCallback {
-public:
- ReconstructUpdateCallback(
- reconstruct_progress_update_cb progress_update_callback,
- void *callback_customdata)
- {
- progress_update_callback_ = progress_update_callback;
- callback_customdata_ = callback_customdata;
- }
-
- void invoke(double progress, const char *message)
- {
- if (progress_update_callback_) {
- progress_update_callback_(callback_customdata_, progress, message);
- }
- }
-protected:
- reconstruct_progress_update_cb progress_update_callback_;
- void *callback_customdata_;
-};
-
-void libmv_solveRefineIntrinsics(
- const Tracks &tracks,
- const int refine_intrinsics,
- const int bundle_constraints,
- reconstruct_progress_update_cb progress_update_callback,
- void *callback_customdata,
- EuclideanReconstruction *reconstruction,
- CameraIntrinsics *intrinsics)
-{
- /* only a few combinations are supported but trust the caller */
- int bundle_intrinsics = 0;
-
- if (refine_intrinsics & LIBMV_REFINE_FOCAL_LENGTH) {
- bundle_intrinsics |= libmv::BUNDLE_FOCAL_LENGTH;
- }
- if (refine_intrinsics & LIBMV_REFINE_PRINCIPAL_POINT) {
- bundle_intrinsics |= libmv::BUNDLE_PRINCIPAL_POINT;
- }
- if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K1) {
- bundle_intrinsics |= libmv::BUNDLE_RADIAL_K1;
- }
- if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K2) {
- bundle_intrinsics |= libmv::BUNDLE_RADIAL_K2;
- }
-
- progress_update_callback(callback_customdata, 1.0, "Refining solution");
-
- EuclideanBundleCommonIntrinsics(tracks,
- bundle_intrinsics,
- bundle_constraints,
- reconstruction,
- intrinsics);
-}
-
-void finishReconstruction(
- const Tracks &tracks,
- const CameraIntrinsics &camera_intrinsics,
- libmv_Reconstruction *libmv_reconstruction,
- reconstruct_progress_update_cb progress_update_callback,
- void *callback_customdata)
-{
- EuclideanReconstruction &reconstruction =
- libmv_reconstruction->reconstruction;
-
- /* reprojection error calculation */
- progress_update_callback(callback_customdata, 1.0, "Finishing solution");
- libmv_reconstruction->tracks = tracks;
- libmv_reconstruction->error = EuclideanReprojectionError(tracks,
- reconstruction,
- camera_intrinsics);
-}
-
-bool selectTwoKeyframesBasedOnGRICAndVariance(
- Tracks &tracks,
- Tracks &normalized_tracks,
- CameraIntrinsics &camera_intrinsics,
- int &keyframe1,
- int &keyframe2)
-{
- libmv::vector<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;
-}
-
-} // 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;
-}
-
-/* ************ Feature detector ************ */
-
-static 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;
-}
-
-static void libmv_convertDetectorOptions(libmv_DetectOptions *options,
- DetectOptions *detector_options)
-{
- switch (options->detector) {
-#define LIBMV_CONVERT(the_detector) \
- case LIBMV_DETECTOR_ ## the_detector: \
- detector_options->type = DetectOptions::the_detector; \
- break;
- LIBMV_CONVERT(FAST)
- LIBMV_CONVERT(MORAVEC)
- LIBMV_CONVERT(HARRIS)
-#undef LIBMV_CONVERT
- }
- detector_options->margin = options->margin;
- detector_options->min_distance = options->min_distance;
- detector_options->fast_min_trackness = options->fast_min_trackness;
- detector_options->moravec_max_count = options->moravec_max_count;
- detector_options->moravec_pattern = options->moravec_pattern;
- detector_options->harris_threshold = options->harris_threshold;
-}
-
-libmv_Features *libmv_detectFeaturesByte(
- const unsigned char *image_buffer,
- int width, int height,
- int channels,
- libmv_DetectOptions *options)
-{
- // Prepare the image.
- FloatImage image;
- libmv_byteBufferToImage(image_buffer, width, height, channels, &image);
-
- // Configure detector.
- DetectOptions detector_options;
- libmv_convertDetectorOptions(options, &detector_options);
-
- // Run the detector.
- libmv::vector<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_floatBufferToImage(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;
-}
-
-/* ************ Camera intrinsics ************ */
-
-libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew(
- const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options)
-{
- CameraIntrinsics *camera_intrinsics =
- libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options);
-
- return (libmv_CameraIntrinsics *) camera_intrinsics;
-}
-
-libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy(
- const libmv_CameraIntrinsics *libmvIntrinsics)
-{
- const CameraIntrinsics *orig_intrinsics =
- (const CameraIntrinsics *) libmvIntrinsics;
-
- CameraIntrinsics *new_intrinsics = NULL;
-
- switch (orig_intrinsics->GetDistortionModelType()) {
- case libmv::DISTORTION_MODEL_POLYNOMIAL:
- {
- const PolynomialCameraIntrinsics *polynomial_intrinsics =
- static_cast<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 *libmvIntrinsics)
-{
- LIBMV_OBJECT_DELETE(libmvIntrinsics, CameraIntrinsics);
-}
-
-void libmv_cameraIntrinsicsUpdate(
- const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options,
- libmv_CameraIntrinsics *libmv_intrinsics)
-{
- CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics;
-
- double focal_length = libmv_camera_intrinsics_options->focal_length;
- double principal_x = libmv_camera_intrinsics_options->principal_point_x;
- double principal_y = libmv_camera_intrinsics_options->principal_point_y;
- int image_width = libmv_camera_intrinsics_options->image_width;
- int image_height = libmv_camera_intrinsics_options->image_height;
-
- /* Try avoid unnecessary updates,
- * so pre-computed distortion grids are not freed.
- */
-
- if (camera_intrinsics->focal_length() != focal_length)
- camera_intrinsics->SetFocalLength(focal_length, focal_length);
-
- if (camera_intrinsics->principal_point_x() != principal_x ||
- camera_intrinsics->principal_point_y() != principal_y)
- {
- camera_intrinsics->SetPrincipalPoint(principal_x, principal_y);
- }
-
- if (camera_intrinsics->image_width() != image_width ||
- camera_intrinsics->image_height() != image_height)
- {
- camera_intrinsics->SetImageSize(image_width, image_height);
- }
-
- switch (libmv_camera_intrinsics_options->distortion_model) {
- case LIBMV_DISTORTION_MODEL_POLYNOMIAL:
- {
- assert(camera_intrinsics->GetDistortionModelType() ==
- libmv::DISTORTION_MODEL_POLYNOMIAL);
-
- PolynomialCameraIntrinsics *polynomial_intrinsics =
- (PolynomialCameraIntrinsics *) camera_intrinsics;
-
- double k1 = libmv_camera_intrinsics_options->polynomial_k1;
- double k2 = libmv_camera_intrinsics_options->polynomial_k2;
- double k3 = libmv_camera_intrinsics_options->polynomial_k3;
-
- if (polynomial_intrinsics->k1() != k1 ||
- polynomial_intrinsics->k2() != k2 ||
- polynomial_intrinsics->k3() != k3)
- {
- polynomial_intrinsics->SetRadialDistortion(k1, k2, k3);
- }
-
- break;
- }
-
- case LIBMV_DISTORTION_MODEL_DIVISION:
- {
- assert(camera_intrinsics->GetDistortionModelType() ==
- libmv::DISTORTION_MODEL_DIVISION);
-
- DivisionCameraIntrinsics *division_intrinsics =
- (DivisionCameraIntrinsics *) camera_intrinsics;
-
- double k1 = libmv_camera_intrinsics_options->division_k1;
- double k2 = libmv_camera_intrinsics_options->division_k2;
-
- if (division_intrinsics->k1() != k1 ||
- division_intrinsics->k2() != k2)
- {
- division_intrinsics->SetDistortion(k1, k2);
- }
-
- break;
- }
-
- default:
- assert(!"Unknown distortion model");
- }
-}
-
-void libmv_cameraIntrinsicsSetThreads(
- libmv_CameraIntrinsics *libmv_intrinsics, int threads)
-{
- CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics;
-
- camera_intrinsics->SetThreads(threads);
-}
-
-void libmv_cameraIntrinsicsExtractOptions(
- const libmv_CameraIntrinsics *libmv_intrinsics,
- libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
-{
- const CameraIntrinsics *camera_intrinsics =
- (const CameraIntrinsics *) libmv_intrinsics;
-
- // Fill in options which are common for all distortion models.
- camera_intrinsics_options->focal_length = camera_intrinsics->focal_length();
- camera_intrinsics_options->principal_point_x =
- camera_intrinsics->principal_point_x();
- camera_intrinsics_options->principal_point_y =
- camera_intrinsics->principal_point_y();
-
- camera_intrinsics_options->image_width = camera_intrinsics->image_width();
- camera_intrinsics_options->image_height = camera_intrinsics->image_height();
-
- switch (camera_intrinsics->GetDistortionModelType()) {
- case libmv::DISTORTION_MODEL_POLYNOMIAL:
- {
- const PolynomialCameraIntrinsics *polynomial_intrinsics =
- static_cast<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,
- unsigned char *src, unsigned char *dst, int width, int height,
- float overscan, int channels)
-{
- CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics;
- camera_intrinsics->UndistortBuffer(src,
- width, height, overscan, channels,
- dst);
-}
-
-void libmv_cameraIntrinsicsUndistortFloat(
- const libmv_CameraIntrinsics *libmvIntrinsics,
- float *src, float *dst, int width, int height,
- float overscan, int channels)
-{
- CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmvIntrinsics;
- intrinsics->UndistortBuffer(src,
- width, height, overscan, channels,
- dst);
-}
-
-void libmv_cameraIntrinsicsDistortByte(
- const libmv_CameraIntrinsics *libmvIntrinsics,
- unsigned char *src, unsigned char *dst, int width, int height,
- float overscan, int channels)
-{
- CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmvIntrinsics;
- intrinsics->DistortBuffer(src,
- width, height, overscan, channels,
- dst);
-}
-
-void libmv_cameraIntrinsicsDistortFloat(
- const libmv_CameraIntrinsics *libmvIntrinsics,
- float *src, float *dst, int width, int height,
- float overscan, int channels)
-{
- CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmvIntrinsics;
- intrinsics->DistortBuffer(src,
- width, height, overscan, channels,
- dst);
-}
-
-void libmv_cameraIntrinsicsApply(
- const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options,
- double x, double y, double *x1, double *y1)
-{
- /* do a lens undistortion if focal length is non-zero only */
- if (libmv_camera_intrinsics_options->focal_length) {
- CameraIntrinsics *camera_intrinsics =
- libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options);
-
- camera_intrinsics->ApplyIntrinsics(x, y, x1, y1);
-
- LIBMV_OBJECT_DELETE(camera_intrinsics, CameraIntrinsics);
- }
-}
-
-void libmv_cameraIntrinsicsInvert(
- const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options,
- double x, double y, double *x1, double *y1)
-{
- /* do a lens distortion if focal length is non-zero only */
- if (libmv_camera_intrinsics_options->focal_length) {
- CameraIntrinsics *camera_intrinsics =
- libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options);
-
- camera_intrinsics->InvertIntrinsics(x, y, x1, y1);
-
- LIBMV_OBJECT_DELETE(camera_intrinsics, CameraIntrinsics);
- }
-}
-
-void libmv_homography2DFromCorrespondencesEuc(double (*x1)[2],
- double (*x2)[2],
- int num_points,
- double H[3][3])
-{
- libmv::Mat x1_mat, x2_mat;
- libmv::Mat3 H_mat;
-
- x1_mat.resize(2, num_points);
- x2_mat.resize(2, num_points);
-
- for (int i = 0; i < num_points; i++) {
- x1_mat.col(i) = libmv::Vec2(x1[i][0], x1[i][1]);
- x2_mat.col(i) = libmv::Vec2(x2[i][0], x2[i][1]);
- }
-
- LG << "x1: " << x1_mat;
- LG << "x2: " << x2_mat;
-
- libmv::EstimateHomographyOptions options;
- libmv::EstimateHomography2DFromCorrespondences(x1_mat,
- x2_mat,
- options,
- &H_mat);
-
- LG << "H: " << H_mat;
-
- memcpy(H, H_mat.data(), 9 * sizeof(double));
-}
-
-#endif