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
path: root/extern
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2011-11-28 17:49:42 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2011-11-28 17:49:42 +0400
commit9f3c921957124d65aa0d2cbc4ad2aacb56411670 (patch)
tree1aa3e3eb139ce638afba27cc129dbfd167446728 /extern
parent24cc4a6c2188f8143282851b19c11f0b61d41475 (diff)
Camera tracking: moved camera solver into it's own job
In some cases solving can take a while (especially when refining is used) and keeping interface locked is a bit annoying. Now camera solver is moved to job system and interface isn't locking. Reporting progress isn't really accurate, but trying to make it more linear can lead to spending more effort on it than having benefit. Also, changing status in the information line helps to understand that blender isn't hang up and solving is till working nicely. Main changes in code: - libmv_solveReconstruction now accepts additional parameters: * progress_update_callback - a function which is getting called from solver algorithm to report progress back to Blender. * callback_customdata - a user-defined context which is passing to progress_update_callback so progress can be updated in needed blender-side data structures. This parameters are optional. - Added structure MovieTrackingStats which is placed in MovieTracking structure. It's supposed to be used for displaying information about different operations (currently it's only camera solver, but can be easily used for something else in the future) in clip editor. This statistics structure is getting allocated for time operator is working and not saving into .blend file. - Clip Editor now displays statistics stored in MovieTrackingStats structure like it's done for rendering.
Diffstat (limited to 'extern')
-rw-r--r--extern/libmv/CMakeLists.txt2
-rw-r--r--extern/libmv/libmv-capi.cpp44
-rw-r--r--extern/libmv/libmv-capi.h6
-rw-r--r--extern/libmv/libmv/simple_pipeline/callbacks.cc29
-rw-r--r--extern/libmv/libmv/simple_pipeline/callbacks.h33
-rw-r--r--extern/libmv/libmv/simple_pipeline/pipeline.cc46
-rw-r--r--extern/libmv/libmv/simple_pipeline/pipeline.h4
7 files changed, 152 insertions, 12 deletions
diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt
index cd1f572197c..6f0d5f3d126 100644
--- a/extern/libmv/CMakeLists.txt
+++ b/extern/libmv/CMakeLists.txt
@@ -39,6 +39,7 @@ set(SRC
libmv-capi.cpp
libmv/numeric/numeric.cc
libmv/numeric/poly.cc
+ libmv/simple_pipeline/callbacks.cc
libmv/simple_pipeline/reconstruction.cc
libmv/simple_pipeline/resect.cc
libmv/simple_pipeline/intersect.cc
@@ -83,6 +84,7 @@ set(SRC
libmv/numeric/poly.h
libmv/numeric/function_derivative.h
libmv/numeric/numeric.h
+ libmv/simple_pipeline/callbacks.h
libmv/simple_pipeline/resect.h
libmv/simple_pipeline/reconstruction.h
libmv/simple_pipeline/camera_intrinsics.h
diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp
index 8c453944e9d..f08aea9fbd1 100644
--- a/extern/libmv/libmv-capi.cpp
+++ b/extern/libmv/libmv-capi.cpp
@@ -31,6 +31,8 @@
#include "libmv-capi.h"
#include "glog/logging.h"
+#include "libmv/logging/logging.h"
+
#include "Math/v3d_optimization.h"
#include "libmv/tracking/esm_region_tracker.h"
@@ -41,6 +43,7 @@
#include "libmv/tracking/sad.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"
@@ -339,6 +342,26 @@ void libmv_tracksDestroy(libmv_Tracks *libmv_tracks)
/* ************ Reconstruction solver ************ */
+class ReconstructUpdateCallback : public libmv::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_;
+};
+
int libmv_refineParametersAreValid(int parameters) {
return (parameters == (LIBMV_REFINE_FOCAL_LENGTH)) ||
(parameters == (LIBMV_REFINE_FOCAL_LENGTH |
@@ -356,7 +379,8 @@ int libmv_refineParametersAreValid(int parameters) {
libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyframe1, int keyframe2,
- int refine_intrinsics, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3)
+ int refine_intrinsics, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
+ reconstruct_progress_update_cb progress_update_callback, void *callback_customdata)
{
/* Invert the camera intrinsics. */
libmv::vector<libmv::Marker> markers = ((libmv::Tracks*)tracks)->AllMarkers();
@@ -364,6 +388,9 @@ libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyfra
libmv::EuclideanReconstruction *reconstruction = &libmv_reconstruction->reconstruction;
libmv::CameraIntrinsics *intrinsics = &libmv_reconstruction->intrinsics;
+ ReconstructUpdateCallback update_callback =
+ ReconstructUpdateCallback(progress_update_callback, callback_customdata);
+
intrinsics->SetFocalLength(focal_length, focal_length);
intrinsics->SetPrincipalPoint(principal_x, principal_y);
intrinsics->SetRadialDistortion(k1, k2, k3);
@@ -377,15 +404,16 @@ libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyfra
libmv::Tracks normalized_tracks(markers);
- // printf("frames to init from: %d, %d\n", keyframe1, keyframe2);
+ LG << "frames to init from: " << keyframe1 << " " << keyframe2;
libmv::vector<libmv::Marker> keyframe_markers =
normalized_tracks.MarkersForTracksInBothImages(keyframe1, keyframe2);
- // printf("number of markers for init: %d\n", keyframe_markers.size());
+ LG << "number of markers for init: " << keyframe_markers.size();
+
+ update_callback.invoke(0, "Initial reconstruction");
libmv::EuclideanReconstructTwoFrames(keyframe_markers, reconstruction);
libmv::EuclideanBundle(normalized_tracks, reconstruction);
-
- libmv::EuclideanCompleteReconstruction(normalized_tracks, reconstruction);
+ libmv::EuclideanCompleteReconstruction(normalized_tracks, reconstruction, &update_callback);
if (refine_intrinsics) {
/* only a few combinations are supported but trust the caller */
@@ -402,9 +430,13 @@ libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyfra
if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K2) {
libmv_refine_flags |= libmv::BUNDLE_RADIAL_K2;
}
- libmv::EuclideanBundleCommonIntrinsics(*(libmv::Tracks *)tracks, libmv_refine_flags, reconstruction, intrinsics);
+
+ progress_update_callback(callback_customdata, 1.0, "Refining solution");
+ libmv::EuclideanBundleCommonIntrinsics(*(libmv::Tracks *)tracks, libmv_refine_flags,
+ reconstruction, intrinsics);
}
+ progress_update_callback(callback_customdata, 1.0, "Finishing solution");
libmv_reconstruction->tracks = *(libmv::Tracks *)tracks;
libmv_reconstruction->error = libmv::EuclideanReprojectionError(*(libmv::Tracks *)tracks, *reconstruction, *intrinsics);
diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h
index 8252a11739b..536f8a5f14c 100644
--- a/extern/libmv/libmv-capi.h
+++ b/extern/libmv/libmv-capi.h
@@ -64,10 +64,14 @@ void libmv_tracksDestroy(struct libmv_Tracks *libmv_tracks);
#define LIBMV_REFINE_PRINCIPAL_POINT (1<<1)
#define LIBMV_REFINE_RADIAL_DISTORTION_K1 (1<<2)
#define LIBMV_REFINE_RADIAL_DISTORTION_K2 (1<<4)
+
+typedef void (*reconstruct_progress_update_cb) (void *customdata, double progress, const char *message);
+
int libmv_refineParametersAreValid(int parameters);
struct libmv_Reconstruction *libmv_solveReconstruction(struct libmv_Tracks *tracks, int keyframe1, int keyframe2,
- int refine_intrinsics, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3);
+ int refine_intrinsics, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
+ reconstruct_progress_update_cb progress_update_callback, void *callback_customdata);
int libmv_reporojectionPointForTrack(struct libmv_Reconstruction *libmv_reconstruction, int track, double pos[3]);
double libmv_reporojectionErrorForTrack(struct libmv_Reconstruction *libmv_reconstruction, int track);
double libmv_reporojectionErrorForImage(struct libmv_Reconstruction *libmv_reconstruction, int image);
diff --git a/extern/libmv/libmv/simple_pipeline/callbacks.cc b/extern/libmv/libmv/simple_pipeline/callbacks.cc
new file mode 100644
index 00000000000..7e4bca6efc7
--- /dev/null
+++ b/extern/libmv/libmv/simple_pipeline/callbacks.cc
@@ -0,0 +1,29 @@
+// Copyright (c) 2011 libmv authors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+
+#include "libmv/simple_pipeline/callbacks.h"
+
+namespace libmv {
+
+void ProgressUpdateCallback::invoke(double progress, const char* message)
+{
+}
+
+} // namespace libmv
diff --git a/extern/libmv/libmv/simple_pipeline/callbacks.h b/extern/libmv/libmv/simple_pipeline/callbacks.h
new file mode 100644
index 00000000000..675f73c1cab
--- /dev/null
+++ b/extern/libmv/libmv/simple_pipeline/callbacks.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2011 libmv authors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+
+#ifndef LIBMV_SIMPLE_PIPELINE_CALLBACKS_H_
+#define LIBMV_SIMPLE_PIPELINE_CALLBACKS_H_
+
+namespace libmv {
+
+class ProgressUpdateCallback {
+ public:
+ virtual void invoke(double progress, const char *message);
+};
+
+} // namespace libmv
+
+#endif // LIBMV_SIMPLE_PIPELINE_MARKERS_H_
diff --git a/extern/libmv/libmv/simple_pipeline/pipeline.cc b/extern/libmv/libmv/simple_pipeline/pipeline.cc
index 9512a41c00f..382365e579f 100644
--- a/extern/libmv/libmv/simple_pipeline/pipeline.cc
+++ b/extern/libmv/libmv/simple_pipeline/pipeline.cc
@@ -21,6 +21,7 @@
#include <cstdio>
#include "libmv/logging/logging.h"
+#include "libmv/simple_pipeline/pipeline.h"
#include "libmv/simple_pipeline/bundle.h"
#include "libmv/simple_pipeline/intersect.h"
#include "libmv/simple_pipeline/resect.h"
@@ -117,14 +118,32 @@ struct ProjectivePipelineRoutines {
} // namespace
+static void CompleteReconstructionLogProress(ProgressUpdateCallback *update_callback,
+ double progress,
+ const char *step = NULL)
+{
+ if(update_callback) {
+ char message[256];
+
+ if(step)
+ snprintf(message, sizeof(message), "Completing solution %d%% | %s", (int)(progress*100), step);
+ else
+ snprintf(message, sizeof(message), "Completing solution %d%%", (int)(progress*100));
+
+ update_callback->invoke(progress, message);
+ }
+}
+
template<typename PipelineRoutines>
void InternalCompleteReconstruction(
const Tracks &tracks,
- typename PipelineRoutines::Reconstruction *reconstruction) {
+ typename PipelineRoutines::Reconstruction *reconstruction,
+ ProgressUpdateCallback *update_callback = NULL) {
int max_track = tracks.MaxTrack();
int max_image = tracks.MaxImage();
int num_resects = -1;
int num_intersects = -1;
+ int tot_resects = 0;
LG << "Max track: " << max_track;
LG << "Max image: " << max_image;
LG << "Number of markers: " << tracks.NumMarkers();
@@ -148,12 +167,17 @@ void InternalCompleteReconstruction(
LG << "Got " << reconstructed_markers.size()
<< " reconstructed markers for track " << track;
if (reconstructed_markers.size() >= 2) {
+ CompleteReconstructionLogProress(update_callback,
+ (double)tot_resects/(max_image));
PipelineRoutines::Intersect(reconstructed_markers, reconstruction);
num_intersects++;
LG << "Ran Intersect() for track " << track;
}
}
if (num_intersects) {
+ CompleteReconstructionLogProress(update_callback,
+ (double)tot_resects/(max_image),
+ "Bundling...");
PipelineRoutines::Bundle(tracks, reconstruction);
LG << "Ran Bundle() after intersections.";
}
@@ -178,8 +202,11 @@ void InternalCompleteReconstruction(
LG << "Got " << reconstructed_markers.size()
<< " reconstructed markers for image " << image;
if (reconstructed_markers.size() >= 5) {
+ CompleteReconstructionLogProress(update_callback,
+ (double)tot_resects/(max_image));
if (PipelineRoutines::Resect(reconstructed_markers, reconstruction, false)) {
num_resects++;
+ tot_resects++;
LG << "Ran Resect() for image " << image;
} else {
LG << "Failed Resect() for image " << image;
@@ -187,6 +214,9 @@ void InternalCompleteReconstruction(
}
}
if (num_resects) {
+ CompleteReconstructionLogProress(update_callback,
+ (double)tot_resects/(max_image),
+ "Bundling...");
PipelineRoutines::Bundle(tracks, reconstruction);
}
LG << "Did " << num_resects << " resects.";
@@ -208,6 +238,8 @@ void InternalCompleteReconstruction(
}
}
if (reconstructed_markers.size() >= 5) {
+ CompleteReconstructionLogProress(update_callback,
+ (double)tot_resects/(max_image));
if (PipelineRoutines::Resect(reconstructed_markers, reconstruction, true)) {
num_resects++;
LG << "Ran Resect() for image " << image;
@@ -217,6 +249,9 @@ void InternalCompleteReconstruction(
}
}
if (num_resects) {
+ CompleteReconstructionLogProress(update_callback,
+ (double)tot_resects/(max_image),
+ "Bundling...");
PipelineRoutines::Bundle(tracks, reconstruction);
}
}
@@ -244,7 +279,7 @@ double InternalReprojectionError(const Tracks &image_tracks,
PipelineRoutines::ProjectMarker(*point, *camera, intrinsics);
double ex = reprojected_marker.x - markers[i].x;
double ey = reprojected_marker.y - markers[i].y;
-
+#if 0
const int N = 100;
char line[N];
snprintf(line, N,
@@ -262,6 +297,7 @@ double InternalReprojectionError(const Tracks &image_tracks,
ex,
ey,
sqrt(ex*ex + ey*ey));
+#endif
total_error += sqrt(ex*ex + ey*ey);
}
LG << "Skipped " << num_skipped << " markers.";
@@ -289,9 +325,11 @@ double ProjectiveReprojectionError(
}
void EuclideanCompleteReconstruction(const Tracks &tracks,
- EuclideanReconstruction *reconstruction) {
+ EuclideanReconstruction *reconstruction,
+ ProgressUpdateCallback *update_callback) {
InternalCompleteReconstruction<EuclideanPipelineRoutines>(tracks,
- reconstruction);
+ reconstruction,
+ update_callback);
}
void ProjectiveCompleteReconstruction(const Tracks &tracks,
diff --git a/extern/libmv/libmv/simple_pipeline/pipeline.h b/extern/libmv/libmv/simple_pipeline/pipeline.h
index b7dfcb7993a..e940b57bc0d 100644
--- a/extern/libmv/libmv/simple_pipeline/pipeline.h
+++ b/extern/libmv/libmv/simple_pipeline/pipeline.h
@@ -21,6 +21,7 @@
#ifndef LIBMV_SIMPLE_PIPELINE_PIPELINE_H_
#define LIBMV_SIMPLE_PIPELINE_PIPELINE_H_
+#include "libmv/simple_pipeline/callbacks.h"
#include "libmv/simple_pipeline/tracks.h"
#include "libmv/simple_pipeline/reconstruction.h"
@@ -46,7 +47,8 @@ namespace libmv {
\sa EuclideanResect, EuclideanIntersect, EuclideanBundle
*/
void EuclideanCompleteReconstruction(const Tracks &tracks,
- EuclideanReconstruction *reconstruction);
+ EuclideanReconstruction *reconstruction,
+ ProgressUpdateCallback *update_callback = NULL);
/*!
Estimate camera matrices and homogeneous 3D coordinates for all frames and