64 ReconstructUpdateCallback(
66 void* callback_customdata) {
67 progress_update_callback_ = progress_update_callback;
68 callback_customdata_ = callback_customdata;
71 void invoke(
double progress,
const char* message) {
72 if (progress_update_callback_) {
73 progress_update_callback_(callback_customdata_, progress, message);
79 void* callback_customdata_;
82 void libmv_solveRefineIntrinsics(
84 const int refine_intrinsics,
85 const int bundle_constraints,
87 void* callback_customdata,
91 int bundle_intrinsics = 0;
100 #define SET_DISTORTION_FLAG_CHECKED(type, coefficient) \
102 if (refine_intrinsics & LIBMV_REFINE_##type##_DISTORTION_##coefficient) { \
103 bundle_intrinsics |= libmv::BUNDLE_##type##_##coefficient; \
115 #undef SET_DISTORTION_FLAG_CHECKED
117 progress_update_callback(callback_customdata, 1.0,
"Refining solution");
126 void finishReconstruction(
131 void* callback_customdata) {
136 progress_update_callback(callback_customdata, 1.0,
"Finishing solution");
138 libmv_reconstruction->
error =
142 bool selectTwoKeyframesBasedOnGRICAndVariance(
144 Tracks& normalized_tracks,
152 normalized_tracks, camera_intrinsics, keyframes);
154 if (keyframes.size() < 2) {
155 LG <<
"Not enough keyframes detected by GRIC";
157 }
else if (keyframes.size() == 2) {
158 keyframe1 = keyframes[0];
159 keyframe2 = keyframes[1];
171 int previous_keyframe = keyframes[0];
173 for (
int i = 1; i < keyframes.size(); i++) {
175 int current_keyframe = keyframes[i];
180 Tracks keyframe_tracks(keyframe_markers);
187 double current_error =
190 LG <<
"Error between " << previous_keyframe <<
" and " << current_keyframe
191 <<
": " << current_error;
193 if (current_error < best_error) {
194 best_error = current_error;
195 keyframe1 = previous_keyframe;
196 keyframe2 = current_keyframe;
199 previous_keyframe = current_keyframe;
209 projected /= projected(2);
213 projected(0), projected(1), &reprojected_marker.
x, &reprojected_marker.
y);
217 return reprojected_marker;
222 Tracks* normalized_tracks) {
224 for (
int i = 0; i <
markers.size(); ++i) {
227 marker.
x, marker.
y, &marker.
x, &marker.
y);
228 normalized_tracks->
Insert(
240 void* callback_customdata) {
248 ReconstructUpdateCallback update_callback =
249 ReconstructUpdateCallback(progress_update_callback, callback_customdata);
253 camera_intrinsics = libmv_reconstruction->
intrinsics =
258 libmv_getNormalizedTracks(
tracks, *camera_intrinsics, &normalized_tracks);
261 int keyframe1 = libmv_reconstruction_options->
keyframe1,
262 keyframe2 = libmv_reconstruction_options->
keyframe2;
265 LG <<
"Using automatic keyframe selection";
267 update_callback.invoke(0,
"Selecting keyframes");
269 if (selectTwoKeyframesBasedOnGRICAndVariance(
tracks,
275 libmv_reconstruction_options->
keyframe1 = keyframe1;
276 libmv_reconstruction_options->
keyframe2 = keyframe2;
281 LG <<
"frames to init from: " << keyframe1 <<
" " << keyframe2;
286 LG <<
"number of markers for init: " << keyframe_markers.size();
288 if (keyframe_markers.size() < 16) {
289 LG <<
"No enough markers to initialize from";
290 libmv_reconstruction->
is_valid =
false;
291 return libmv_reconstruction;
294 update_callback.invoke(0,
"Initial reconstruction");
297 LG <<
"Failed to initialize reconstruction";
298 libmv_reconstruction->
is_valid =
false;
299 return libmv_reconstruction;
308 libmv_solveRefineIntrinsics(
tracks,
311 progress_update_callback,
321 finishReconstruction(
tracks,
323 libmv_reconstruction,
324 progress_update_callback,
325 callback_customdata);
327 libmv_reconstruction->
is_valid =
true;
336 void* callback_customdata) {
344 ReconstructUpdateCallback update_callback =
345 ReconstructUpdateCallback(progress_update_callback, callback_customdata);
349 camera_intrinsics = libmv_reconstruction->
intrinsics =
354 libmv_getNormalizedTracks(
tracks, *camera_intrinsics, &normalized_tracks);
368 libmv_solveRefineIntrinsics(
tracks,
371 progress_update_callback,
378 finishReconstruction(
tracks,
380 libmv_reconstruction,
381 progress_update_callback,
382 callback_customdata);
384 libmv_reconstruction->
is_valid =
true;
389 return libmv_reconstruction->
is_valid;
405 pos[0] = point->
X[0];
406 pos[1] = point->
X[2];
407 pos[2] = point->
X[1];
421 int num_reprojected = 0;
422 double total_error = 0.0;
424 for (
int i = 0; i <
markers.size(); ++i) {
425 double weight =
markers[i].weight;
431 if (!camera || !point || weight == 0.0) {
437 Marker reprojected_marker =
438 libmv_projectMarker(*point, *camera, *intrinsics);
439 double ex = (reprojected_marker.
x -
markers[i].x) * weight;
440 double ey = (reprojected_marker.
y -
markers[i].y) * weight;
442 total_error +=
sqrt(ex * ex + ey * ey);
445 return total_error / num_reprojected;
456 int num_reprojected = 0;
457 double total_error = 0.0;
463 for (
int i = 0; i <
markers.size(); ++i) {
473 Marker reprojected_marker =
474 libmv_projectMarker(*point, *camera, *intrinsics);
478 total_error +=
sqrt(ex * ex + ey * ey);
481 return total_error / num_reprojected;
493 for (
int j = 0; j < 3; ++j) {
494 for (
int k = 0; k < 3; ++k) {
504 mat[j][
l] = -camera->
R(j, k);
506 mat[j][
l] = camera->
R(j, k);
512 libmv::Vec3 optical_center = -camera->
R.transpose() * camera->
t;
514 mat[3][0] = optical_center(0);
515 mat[3][1] = optical_center(2);
516 mat[3][2] = optical_center(1);
528 return libmv_reconstruction->
error;
ATTR_WARN_UNUSED_RESULT const BMLoop * l
virtual void ApplyIntrinsics(double normalized_x, double normalized_y, double *image_x, double *image_y) const =0
virtual void InvertIntrinsics(double image_x, double image_y, double *normalized_x, double *normalized_y) const =0
virtual void invoke(double progress, const char *message)=0
vector< Marker > MarkersInImage(int image) const
Returns all the markers visible in image.
vector< Marker > MarkersForTracksInBothImages(int image1, int image2) const
void Insert(int image, int track, double x, double y, double weight=1.0)
vector< Marker > MarkersForTrack(int track) const
Returns all the markers belonging to a track.
const vector< Marker > & markers
CameraIntrinsics * libmv_cameraIntrinsicsCreateFromOptions(const libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
struct libmv_CameraIntrinsics libmv_CameraIntrinsics
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)
double libmv_reprojectionErrorForImage(const libmv_Reconstruction *libmv_reconstruction, int image)
libmv_CameraIntrinsics * libmv_reconstructionExtractIntrinsics(libmv_Reconstruction *libmv_reconstruction)
double libmv_reprojectionError(const libmv_Reconstruction *libmv_reconstruction)
void libmv_reconstructionDestroy(libmv_Reconstruction *libmv_reconstruction)
int libmv_reconstructionIsValid(libmv_Reconstruction *libmv_reconstruction)
int libmv_reprojectionCameraForImage(const libmv_Reconstruction *libmv_reconstruction, int image, double mat[4][4])
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)
int libmv_reprojectionPointForTrack(const libmv_Reconstruction *libmv_reconstruction, int track, double pos[3])
#define SET_DISTORTION_FLAG_CHECKED(type, coefficient)
double libmv_reprojectionErrorForTrack(const libmv_Reconstruction *libmv_reconstruction, int track)
void(* reconstruct_progress_update_cb)(void *customdata, double progress, const char *message)
@ LIBMV_REFINE_FOCAL_LENGTH
@ LIBMV_REFINE_PRINCIPAL_POINT
struct libmv_Tracks libmv_Tracks
const ProjectiveReconstruction & reconstruction
std::vector< ElementType, Eigen::aligned_allocator< ElementType > > vector
void ModalSolver(const Tracks &tracks, EuclideanReconstruction *reconstruction, ProgressUpdateCallback *update_callback)
void SelectKeyframesBasedOnGRICAndVariance(const Tracks &_tracks, const CameraIntrinsics &intrinsics, vector< int > &keyframes)
bool EuclideanReconstructTwoFrames(const vector< Marker > &markers, EuclideanReconstruction *reconstruction)
void EuclideanScaleToUnity(EuclideanReconstruction *reconstruction)
void EuclideanBundle(const Tracks &tracks, EuclideanReconstruction *reconstruction)
void EuclideanCompleteReconstruction(const Tracks &tracks, EuclideanReconstruction *reconstruction, ProgressUpdateCallback *update_callback)
void EuclideanBundleCommonIntrinsics(const Tracks &tracks, const int bundle_intrinsics, const int bundle_constraints, EuclideanReconstruction *reconstruction, CameraIntrinsics *intrinsics, BundleEvaluation *evaluation)
double EuclideanReprojectionError(const Tracks &image_tracks, const EuclideanReconstruction &reconstruction, const CameraIntrinsics &intrinsics)
CameraIntrinsics * intrinsics
EuclideanReconstruction reconstruction
#define LIBMV_OBJECT_NEW(type,...)
#define LIBMV_OBJECT_DELETE(what, type)