From 197595125f11e7037f06a75cbabc38a4c728d044 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 30 Jul 2011 17:14:07 +0000 Subject: [PATCH] Camera tracking integration =========================== - Fixed occasional crash caused by conflicting access to non-threadsafe moviecache. Added lock on movie clip ibuf acquire level. - A bit nicer feedback from libmv when doing reconstruction. Now if all tracks and frames were reconstructed average error would be reported in "notification area". If there's something failed to be reconstructed warning message would appear and failed items would be printed to the console. --- extern/libmv/libmv-capi.cpp | 33 +++++++++++++------ extern/libmv/libmv-capi.h | 7 ++-- source/blender/blenkernel/BKE_tracking.h | 2 +- source/blender/blenkernel/intern/moviecache.c | 3 +- source/blender/blenkernel/intern/movieclip.c | 11 ++++--- source/blender/blenkernel/intern/tracking.c | 22 +++++++++---- .../blender/editors/space_clip/tracking_ops.c | 8 ++++- 7 files changed, 58 insertions(+), 28 deletions(-) diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index 5d37c43f095..6b6ecf15908 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -65,6 +65,11 @@ typedef struct libmv_RegionTracker { libmv::RegionTracker *region_tracker; } libmv_RegionTracker; +typedef struct libmv_Reconstruction { + libmv::Reconstruction reconstruction; + double error; +} libmv_Reconstruction; + /* ************ Logging ************ */ void libmv_initLogging(const char *argv0) @@ -316,13 +321,14 @@ void libmv_tracksDestroy(libmv_Tracks *tracks) /* ************ Reconstruction solver ************ */ -struct libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyframe1, int keyframe2, +libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyframe1, int keyframe2, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3) { /* Invert the camera intrinsics. */ libmv::vector markers = ((libmv::Tracks*)tracks)->AllMarkers(); libmv::CameraIntrinsics intrinsics; - libmv::Reconstruction *reconstruction = new libmv::Reconstruction(); + libmv_Reconstruction *libmv_reconstruction = new libmv_Reconstruction(); + libmv::Reconstruction *reconstruction = &libmv_reconstruction->reconstruction; intrinsics.SetFocalLength(focal_length, focal_length); intrinsics.SetPrincipalPoint(principal_x, principal_y); @@ -346,14 +352,15 @@ struct libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int libmv::ReconstructTwoFrames(keyframe_markers, reconstruction); libmv::Bundle(normalized_tracks, reconstruction); libmv::CompleteReconstruction(normalized_tracks, reconstruction); - libmv::ReprojectionError(*(libmv::Tracks *)tracks, *reconstruction, intrinsics); + libmv_reconstruction->error = libmv::ReprojectionError(*(libmv::Tracks *)tracks, *reconstruction, intrinsics); - return (libmv_Reconstruction *)reconstruction; + return (libmv_Reconstruction *)libmv_reconstruction; } -int libmv_reporojectionPointForTrack(libmv_Reconstruction *reconstruction, int track, double pos[3]) +int libmv_reporojectionPointForTrack(libmv_Reconstruction *libmv_reconstruction, int track, double pos[3]) { - libmv::Point *point = ((libmv::Reconstruction *)reconstruction)->PointForTrack(track); + libmv::Reconstruction *reconstruction = &libmv_reconstruction->reconstruction; + libmv::Point *point = reconstruction->PointForTrack(track); if(point) { pos[0] = point->X[0]; @@ -366,9 +373,10 @@ int libmv_reporojectionPointForTrack(libmv_Reconstruction *reconstruction, int t return 0; } -int libmv_reporojectionCameraForImage(libmv_Reconstruction *reconstruction, int image, double mat[4][4]) +int libmv_reporojectionCameraForImage(libmv_Reconstruction *libmv_reconstruction, int image, double mat[4][4]) { - libmv::Camera *camera = ((libmv::Reconstruction *)reconstruction)->CameraForImage(image); + libmv::Reconstruction *reconstruction = &libmv_reconstruction->reconstruction; + libmv::Camera *camera = reconstruction->CameraForImage(image); if(camera) { for (int j = 0; j < 3; ++j) { @@ -398,9 +406,14 @@ int libmv_reporojectionCameraForImage(libmv_Reconstruction *reconstruction, int return 0; } -void libmv_destroyReconstruction(libmv_Reconstruction *reconstruction) +float libmv_reprojectionError(libmv_Reconstruction *libmv_reconstruction) +{ + return libmv_reconstruction->error; +} + +void libmv_destroyReconstruction(libmv_Reconstruction *libmv_reconstruction) { - delete (libmv::Reconstruction *)reconstruction; + delete libmv_reconstruction; } /* ************ feature detector ************ */ diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h index cad93b3c538..12881f9cb3e 100644 --- a/extern/libmv/libmv-capi.h +++ b/extern/libmv/libmv-capi.h @@ -58,9 +58,10 @@ void libmv_tracksDestroy(struct libmv_Tracks *tracks); /* Reconstruction solver */ struct libmv_Reconstruction *libmv_solveReconstruction(struct libmv_Tracks *tracks, int keyframe1, int keyframe2, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3); -int libmv_reporojectionPointForTrack(struct libmv_Reconstruction *reconstruction, int track, double pos[3]); -int libmv_reporojectionCameraForImage(struct libmv_Reconstruction *reconstruction, int image, double mat[4][4]); -void libmv_destroyReconstruction(struct libmv_Reconstruction *reconstruction); +int libmv_reporojectionPointForTrack(struct libmv_Reconstruction *libmv_reconstruction, int track, double pos[3]); +int libmv_reporojectionCameraForImage(struct libmv_Reconstruction *libmv_reconstruction, int image, double mat[4][4]); +float libmv_reprojectionError(struct libmv_Reconstruction *libmv_reconstruction); +void libmv_destroyReconstruction(struct libmv_Reconstruction *libmv_reconstruction); /* feature detector */ diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 7b37702ecfc..85af75d2656 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -71,7 +71,7 @@ void BKE_tracking_sync(struct MovieTrackingContext *context); void BKE_tracking_sync_user(struct MovieClipUser *user, struct MovieTrackingContext *context); int BKE_tracking_next(struct MovieTrackingContext *context); -void BKE_tracking_solve_reconstruction(struct MovieClip *clip); +float BKE_tracking_solve_reconstruction(struct MovieClip *clip); void BKE_track_unique_name(struct MovieTracking *tracking, struct MovieTrackingTrack *track); struct MovieTrackingTrack *BKE_find_track_by_name(struct MovieTracking *tracking, const char *name); diff --git a/source/blender/blenkernel/intern/moviecache.c b/source/blender/blenkernel/intern/moviecache.c index aa02fd7d711..6aacf5052e9 100644 --- a/source/blender/blenkernel/intern/moviecache.c +++ b/source/blender/blenkernel/intern/moviecache.c @@ -269,6 +269,7 @@ ImBuf* BKE_moviecache_get(MovieCache *cache, void *userkey) if(item->ibuf) { MEM_CacheLimiter_touch(item->c_handle); IMB_refImBuf(item->ibuf); + return item->ibuf; } } @@ -365,4 +366,4 @@ void BKE_moviecache_get_cache_segments(MovieCache *cache, int *totseg_r, int **p cache->points= points; } } -} \ No newline at end of file +} diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 544902ae7ad..7eddde31800 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -292,6 +292,10 @@ ImBuf *BKE_movieclip_acquire_ibuf(MovieClip *clip, MovieClipUser *user) ImBuf *ibuf= NULL; int framenr= user?user->framenr:clip->lastframe; + /* cache isn't threadsafe itself and also loading of movies + can't happen from concurent threads that's why we use lock here */ + BLI_lock_thread(LOCK_MOVIECLIP); + /* cache is supposed to be threadsafe */ ibuf= get_imbuf_cache(clip, user); @@ -299,12 +303,7 @@ ImBuf *BKE_movieclip_acquire_ibuf(MovieClip *clip, MovieClipUser *user) if(clip->source==MCLIP_SRC_SEQUENCE) ibuf= movieclip_load_sequence_file(clip, framenr); else { - /* loading of movies can't happen from concurent threads */ - BLI_lock_thread(LOCK_MOVIECLIP); - ibuf= movieclip_load_movie_file(clip, framenr); - - BLI_unlock_thread(LOCK_MOVIECLIP); } if(ibuf) @@ -318,6 +317,8 @@ ImBuf *BKE_movieclip_acquire_ibuf(MovieClip *clip, MovieClipUser *user) clip->lastsize[1]= ibuf->y; } + BLI_unlock_thread(LOCK_MOVIECLIP); + return ibuf; } diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 53ab52b0313..bbb03252b09 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -902,7 +902,7 @@ static struct libmv_Tracks *create_libmv_tracks(MovieClip *clip) return tracks; } -static void retrive_libmv_reconstruct(MovieClip *clip, struct libmv_Reconstruction *reconstruction) +static int retrive_libmv_reconstruct(MovieClip *clip, struct libmv_Reconstruction *reconstruction) { int tracknr= 0; int sfra= INT_MAX, efra= INT_MIN, a, origin_set= 0; @@ -911,6 +911,7 @@ static void retrive_libmv_reconstruct(MovieClip *clip, struct libmv_Reconstructi MovieTrackingCamera *camera; MovieReconstructedCamera *reconstructed; float origin[3]= {0.0f, 0.f, 0.0f}; + int ok= 1; track= tracking->tracks.first; while(track) { @@ -924,9 +925,9 @@ static void retrive_libmv_reconstruct(MovieClip *clip, struct libmv_Reconstructi track->flag|= TRACK_HAS_BUNDLE; } else { track->flag&= ~TRACK_HAS_BUNDLE; + ok= 0; - if (G.f & G_DEBUG) - printf("No bundle for track #%d '%s'\n", tracknr, track->name); + printf("No bundle for track #%d '%s'\n", tracknr, track->name); } if(track->markersnr) { @@ -969,8 +970,9 @@ static void retrive_libmv_reconstruct(MovieClip *clip, struct libmv_Reconstructi copy_m4_m4(reconstructed[camera->reconnr].mat, mat); reconstructed[camera->reconnr].framenr= a; camera->reconnr++; - } else if (G.f & G_DEBUG) { - printf("No camera for image %d\n", a); + } else { + ok= 0; + printf("No camera for frame %d\n", a); } } @@ -990,11 +992,13 @@ static void retrive_libmv_reconstruct(MovieClip *clip, struct libmv_Reconstructi } MEM_freeN(reconstructed); + + return ok; } #endif -void BKE_tracking_solve_reconstruction(MovieClip *clip) +float BKE_tracking_solve_reconstruction(MovieClip *clip) { #if WITH_LIBMV { @@ -1005,11 +1009,15 @@ void BKE_tracking_solve_reconstruction(MovieClip *clip) tracking->settings.keyframe1, tracking->settings.keyframe2, camera->focal, camera->principal[0], camera->principal[1], camera->k1, camera->k2, camera->k3); + float error= libmv_reprojectionError(reconstruction); - retrive_libmv_reconstruct(clip, reconstruction); + if(!retrive_libmv_reconstruct(clip, reconstruction)) + error= -1.f; libmv_destroyReconstruction(reconstruction); libmv_tracksDestroy(tracks); + + return error; } #endif } diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 53a4441a5ee..e8fd58e80ce 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1486,13 +1486,19 @@ static int solve_camera_exec(bContext *C, wmOperator *op) SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); Scene *scene= CTX_data_scene(C); + float error; if(!check_solve_tarck_count(&clip->tracking)) { BKE_report(op->reports, RPT_ERROR, "At least 10 tracks on both of keyframes are needed for reconstruction"); return OPERATOR_CANCELLED; } - BKE_tracking_solve_reconstruction(clip); + error = BKE_tracking_solve_reconstruction(clip); + + if(error<0) + BKE_report(op->reports, RPT_WARNING, "Some data failed to reconstruct, see console for details"); + else + BKE_reportf(op->reports, RPT_INFO, "Average reprojection error %.3f", error); scene->clip= clip; -- 2.28.0