Camera tracking: progress report clean-up

Send object which implements ProgressUpdateCallback to complete reconstruction
function rather than sending C-like procedure variable and context.
This commit is contained in:
Sergey Sharybin 2011-11-27 10:35:00 +00:00
parent f5f4348e10
commit 196d06a0bf
9 changed files with 114 additions and 43 deletions

@ -39,6 +39,7 @@ set(SRC
libmv-capi.cpp libmv-capi.cpp
libmv/numeric/numeric.cc libmv/numeric/numeric.cc
libmv/numeric/poly.cc libmv/numeric/poly.cc
libmv/simple_pipeline/callbacks.cc
libmv/simple_pipeline/reconstruction.cc libmv/simple_pipeline/reconstruction.cc
libmv/simple_pipeline/resect.cc libmv/simple_pipeline/resect.cc
libmv/simple_pipeline/intersect.cc libmv/simple_pipeline/intersect.cc
@ -83,6 +84,7 @@ set(SRC
libmv/numeric/poly.h libmv/numeric/poly.h
libmv/numeric/function_derivative.h libmv/numeric/function_derivative.h
libmv/numeric/numeric.h libmv/numeric/numeric.h
libmv/simple_pipeline/callbacks.h
libmv/simple_pipeline/resect.h libmv/simple_pipeline/resect.h
libmv/simple_pipeline/reconstruction.h libmv/simple_pipeline/reconstruction.h
libmv/simple_pipeline/camera_intrinsics.h libmv/simple_pipeline/camera_intrinsics.h

@ -43,6 +43,7 @@
#include "libmv/tracking/sad.h" #include "libmv/tracking/sad.h"
#include "libmv/simple_pipeline/callbacks.h"
#include "libmv/simple_pipeline/tracks.h" #include "libmv/simple_pipeline/tracks.h"
#include "libmv/simple_pipeline/initialize_reconstruction.h" #include "libmv/simple_pipeline/initialize_reconstruction.h"
#include "libmv/simple_pipeline/bundle.h" #include "libmv/simple_pipeline/bundle.h"
@ -341,6 +342,26 @@ void libmv_tracksDestroy(libmv_Tracks *libmv_tracks)
/* ************ Reconstruction solver ************ */ /* ************ 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) { int libmv_refineParametersAreValid(int parameters) {
return (parameters == (LIBMV_REFINE_FOCAL_LENGTH)) || return (parameters == (LIBMV_REFINE_FOCAL_LENGTH)) ||
(parameters == (LIBMV_REFINE_FOCAL_LENGTH | (parameters == (LIBMV_REFINE_FOCAL_LENGTH |
@ -367,6 +388,9 @@ libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyfra
libmv::EuclideanReconstruction *reconstruction = &libmv_reconstruction->reconstruction; libmv::EuclideanReconstruction *reconstruction = &libmv_reconstruction->reconstruction;
libmv::CameraIntrinsics *intrinsics = &libmv_reconstruction->intrinsics; libmv::CameraIntrinsics *intrinsics = &libmv_reconstruction->intrinsics;
ReconstructUpdateCallback update_callback =
ReconstructUpdateCallback(progress_update_callback, callback_customdata);
intrinsics->SetFocalLength(focal_length, focal_length); intrinsics->SetFocalLength(focal_length, focal_length);
intrinsics->SetPrincipalPoint(principal_x, principal_y); intrinsics->SetPrincipalPoint(principal_x, principal_y);
intrinsics->SetRadialDistortion(k1, k2, k3); intrinsics->SetRadialDistortion(k1, k2, k3);
@ -385,13 +409,11 @@ libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyfra
normalized_tracks.MarkersForTracksInBothImages(keyframe1, keyframe2); normalized_tracks.MarkersForTracksInBothImages(keyframe1, keyframe2);
LG << "number of markers for init: " << keyframe_markers.size(); LG << "number of markers for init: " << keyframe_markers.size();
if(progress_update_callback) update_callback.invoke(0, "Initial reconstruction");
progress_update_callback(callback_customdata, 0, "Initial reconstruction");
libmv::EuclideanReconstructTwoFrames(keyframe_markers, reconstruction); libmv::EuclideanReconstructTwoFrames(keyframe_markers, reconstruction);
libmv::EuclideanBundle(normalized_tracks, reconstruction); libmv::EuclideanBundle(normalized_tracks, reconstruction);
libmv::EuclideanCompleteReconstruction(normalized_tracks, reconstruction, &update_callback);
libmv::EuclideanCompleteReconstruction(normalized_tracks, reconstruction, progress_update_callback, callback_customdata);
if (refine_intrinsics) { if (refine_intrinsics) {
/* only a few combinations are supported but trust the caller */ /* only a few combinations are supported but trust the caller */
@ -410,7 +432,8 @@ libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyfra
} }
progress_update_callback(callback_customdata, 1.0, "Refining solution"); progress_update_callback(callback_customdata, 1.0, "Refining solution");
libmv::EuclideanBundleCommonIntrinsics(*(libmv::Tracks *)tracks, libmv_refine_flags, reconstruction, intrinsics); libmv::EuclideanBundleCommonIntrinsics(*(libmv::Tracks *)tracks, libmv_refine_flags,
reconstruction, intrinsics);
} }
progress_update_callback(callback_customdata, 1.0, "Finishing solution"); progress_update_callback(callback_customdata, 1.0, "Finishing solution");

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

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

@ -118,18 +118,19 @@ struct ProjectivePipelineRoutines {
} // namespace } // namespace
static void CompleteReconstructionLogProress(progress_update_callback update_callback, static void CompleteReconstructionLogProress(ProgressUpdateCallback *update_callback,
void *update_customdata,
double progress, double progress,
const char *step) const char *step = NULL)
{ {
if(update_callback) { if(update_callback) {
char message[256]; char message[256];
if(step) if(step)
snprintf(message, sizeof(message), "Completing solution %d%% | %s", (int)(progress*100), step); snprintf(message, sizeof(message), "Completing solution %d%% | %s", (int)(progress*100), step);
else else
snprintf(message, sizeof(message), "Completing solution %d%%", (int)(progress*100)); snprintf(message, sizeof(message), "Completing solution %d%%", (int)(progress*100));
update_callback(update_customdata, progress, message);
update_callback->invoke(progress, message);
} }
} }
@ -137,8 +138,7 @@ template<typename PipelineRoutines>
void InternalCompleteReconstruction( void InternalCompleteReconstruction(
const Tracks &tracks, const Tracks &tracks,
typename PipelineRoutines::Reconstruction *reconstruction, typename PipelineRoutines::Reconstruction *reconstruction,
progress_update_callback update_callback, ProgressUpdateCallback *update_callback = NULL) {
void *update_customdata) {
int max_track = tracks.MaxTrack(); int max_track = tracks.MaxTrack();
int max_image = tracks.MaxImage(); int max_image = tracks.MaxImage();
int num_resects = -1; int num_resects = -1;
@ -167,16 +167,15 @@ void InternalCompleteReconstruction(
LG << "Got " << reconstructed_markers.size() LG << "Got " << reconstructed_markers.size()
<< " reconstructed markers for track " << track; << " reconstructed markers for track " << track;
if (reconstructed_markers.size() >= 2) { if (reconstructed_markers.size() >= 2) {
CompleteReconstructionLogProress(update_callback, update_customdata, CompleteReconstructionLogProress(update_callback,
(double)tot_resects/(max_image), (double)tot_resects/(max_image));
NULL);
PipelineRoutines::Intersect(reconstructed_markers, reconstruction); PipelineRoutines::Intersect(reconstructed_markers, reconstruction);
num_intersects++; num_intersects++;
LG << "Ran Intersect() for track " << track; LG << "Ran Intersect() for track " << track;
} }
} }
if (num_intersects) { if (num_intersects) {
CompleteReconstructionLogProress(update_callback, update_customdata, CompleteReconstructionLogProress(update_callback,
(double)tot_resects/(max_image), (double)tot_resects/(max_image),
"Bundling..."); "Bundling...");
PipelineRoutines::Bundle(tracks, reconstruction); PipelineRoutines::Bundle(tracks, reconstruction);
@ -203,9 +202,8 @@ void InternalCompleteReconstruction(
LG << "Got " << reconstructed_markers.size() LG << "Got " << reconstructed_markers.size()
<< " reconstructed markers for image " << image; << " reconstructed markers for image " << image;
if (reconstructed_markers.size() >= 5) { if (reconstructed_markers.size() >= 5) {
CompleteReconstructionLogProress(update_callback, update_customdata, CompleteReconstructionLogProress(update_callback,
(double)tot_resects/(max_image), (double)tot_resects/(max_image));
NULL);
if (PipelineRoutines::Resect(reconstructed_markers, reconstruction, false)) { if (PipelineRoutines::Resect(reconstructed_markers, reconstruction, false)) {
num_resects++; num_resects++;
tot_resects++; tot_resects++;
@ -216,7 +214,7 @@ void InternalCompleteReconstruction(
} }
} }
if (num_resects) { if (num_resects) {
CompleteReconstructionLogProress(update_callback, update_customdata, CompleteReconstructionLogProress(update_callback,
(double)tot_resects/(max_image), (double)tot_resects/(max_image),
"Bundling..."); "Bundling...");
PipelineRoutines::Bundle(tracks, reconstruction); PipelineRoutines::Bundle(tracks, reconstruction);
@ -240,9 +238,8 @@ void InternalCompleteReconstruction(
} }
} }
if (reconstructed_markers.size() >= 5) { if (reconstructed_markers.size() >= 5) {
CompleteReconstructionLogProress(update_callback, update_customdata, CompleteReconstructionLogProress(update_callback,
(double)tot_resects/(max_image), (double)tot_resects/(max_image));
NULL);
if (PipelineRoutines::Resect(reconstructed_markers, reconstruction, true)) { if (PipelineRoutines::Resect(reconstructed_markers, reconstruction, true)) {
num_resects++; num_resects++;
LG << "Ran Resect() for image " << image; LG << "Ran Resect() for image " << image;
@ -252,7 +249,7 @@ void InternalCompleteReconstruction(
} }
} }
if (num_resects) { if (num_resects) {
CompleteReconstructionLogProress(update_callback, update_customdata, CompleteReconstructionLogProress(update_callback,
(double)tot_resects/(max_image), (double)tot_resects/(max_image),
"Bundling..."); "Bundling...");
PipelineRoutines::Bundle(tracks, reconstruction); PipelineRoutines::Bundle(tracks, reconstruction);
@ -329,19 +326,16 @@ double ProjectiveReprojectionError(
void EuclideanCompleteReconstruction(const Tracks &tracks, void EuclideanCompleteReconstruction(const Tracks &tracks,
EuclideanReconstruction *reconstruction, EuclideanReconstruction *reconstruction,
progress_update_callback update_callback, ProgressUpdateCallback *update_callback) {
void *update_customdata) {
InternalCompleteReconstruction<EuclideanPipelineRoutines>(tracks, InternalCompleteReconstruction<EuclideanPipelineRoutines>(tracks,
reconstruction, reconstruction,
update_callback, update_callback);
update_customdata);
} }
void ProjectiveCompleteReconstruction(const Tracks &tracks, void ProjectiveCompleteReconstruction(const Tracks &tracks,
ProjectiveReconstruction *reconstruction) { ProjectiveReconstruction *reconstruction) {
InternalCompleteReconstruction<ProjectivePipelineRoutines>(tracks, InternalCompleteReconstruction<ProjectivePipelineRoutines>(tracks,
reconstruction, reconstruction);
NULL, NULL);
} }
void InvertIntrinsicsForTracks(const Tracks &raw_tracks, void InvertIntrinsicsForTracks(const Tracks &raw_tracks,

@ -21,13 +21,12 @@
#ifndef LIBMV_SIMPLE_PIPELINE_PIPELINE_H_ #ifndef LIBMV_SIMPLE_PIPELINE_PIPELINE_H_
#define 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/tracks.h"
#include "libmv/simple_pipeline/reconstruction.h" #include "libmv/simple_pipeline/reconstruction.h"
namespace libmv { namespace libmv {
typedef void (*progress_update_callback) (void *customdata, double progress, const char *message);
/*! /*!
Estimate camera poses and scene 3D coordinates for all frames and tracks. Estimate camera poses and scene 3D coordinates for all frames and tracks.
@ -49,8 +48,7 @@ typedef void (*progress_update_callback) (void *customdata, double progress, con
*/ */
void EuclideanCompleteReconstruction(const Tracks &tracks, void EuclideanCompleteReconstruction(const Tracks &tracks,
EuclideanReconstruction *reconstruction, EuclideanReconstruction *reconstruction,
progress_update_callback update_callback, ProgressUpdateCallback *update_callback = NULL);
void *update_customdata);
/*! /*!
Estimate camera matrices and homogeneous 3D coordinates for all frames and Estimate camera matrices and homogeneous 3D coordinates for all frames and

@ -1356,7 +1356,6 @@ typedef struct ReconstructProgressData {
short *stop; short *stop;
short *do_update; short *do_update;
float *progress; float *progress;
float stats_progress;
char *stats_message; char *stats_message;
int message_size; int message_size;
} ReconstructProgressData; } ReconstructProgressData;
@ -1656,8 +1655,8 @@ static void solve_reconstruction_update_cb(void *customdata, double progress, co
*progressdata->do_update= 1; *progressdata->do_update= 1;
} }
BLI_snprintf(progressdata->stats_message, progressdata->message_size, "Solving camera | %s", message); BLI_snprintf(progressdata->stats_message, progressdata->message_size,
progressdata->stats_progress= progress; "Solving camera | %s", message);
} }
#if 0 #if 0

@ -1518,7 +1518,6 @@ typedef struct {
ReportList *reports; ReportList *reports;
char stats_message[256]; char stats_message[256];
float *stats_progress;
struct MovieReconstructContext *context; struct MovieReconstructContext *context;
} SolveCameraJob; } SolveCameraJob;
@ -1557,17 +1556,12 @@ static void solve_camera_updatejob(void *scv)
MovieTracking *tracking= &scj->clip->tracking; MovieTracking *tracking= &scj->clip->tracking;
BLI_strncpy(tracking->stats->message, scj->stats_message, sizeof(tracking->stats->message)); BLI_strncpy(tracking->stats->message, scj->stats_message, sizeof(tracking->stats->message));
if(scj->stats_progress)
tracking->stats->progress= *scj->stats_progress;
} }
static void solve_camera_startjob(void *scv, short *stop, short *do_update, float *progress) static void solve_camera_startjob(void *scv, short *stop, short *do_update, float *progress)
{ {
SolveCameraJob *scj= (SolveCameraJob *)scv; SolveCameraJob *scj= (SolveCameraJob *)scv;
scj->stats_progress= progress;
BKE_tracking_solve_reconstruction(scj->context, stop, do_update, progress, BKE_tracking_solve_reconstruction(scj->context, stop, do_update, progress,
scj->stats_message, sizeof(scj->stats_message)); scj->stats_message, sizeof(scj->stats_message));
} }

@ -174,7 +174,6 @@ typedef struct MovieTrackingReconstruction {
} MovieTrackingReconstruction; } MovieTrackingReconstruction;
typedef struct MovieTrackingStats { typedef struct MovieTrackingStats {
float progress;
char message[256]; char message[256];
} MovieTrackingStats; } MovieTrackingStats;