Camera tracking integration
authorSergey Sharybin <sergey.vfx@gmail.com>
Sat, 30 Jul 2011 17:14:07 +0000 (17:14 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Sat, 30 Jul 2011 17:14:07 +0000 (17:14 +0000)
===========================

- 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
extern/libmv/libmv-capi.h
source/blender/blenkernel/BKE_tracking.h
source/blender/blenkernel/intern/moviecache.c
source/blender/blenkernel/intern/movieclip.c
source/blender/blenkernel/intern/tracking.c
source/blender/editors/space_clip/tracking_ops.c

index 5d37c43f095f6f0d5a484eb4c6c3f798e6b1e2bf..6b6ecf15908d1818021d4df017c2b3806bd9cbbf 100644 (file)
@@ -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<libmv::Marker> 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 ************ */
index cad93b3c538662c6b38012797bdb682f307fa1de..12881f9cb3ee9c65adc5043f33e7f827a72ba846 100644 (file)
@@ -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 */
 
index 7b37702ecfcb6a3c01c67278df6a0edb0729ce4a..85af75d2656f0eb492203e785f8457ee2ad0ea28 100644 (file)
@@ -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);
index aa02fd7d71187f2df6246bdb949df43c3f8b9e1a..6aacf5052e9facfe9922d0d7be727db7f093deb6 100644 (file)
@@ -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
+}
index 544902ae7ad74a0c86c59d4e26163aa6ffabd836..7eddde31800ede42721956c217f737c536a08607 100644 (file)
@@ -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;
 }
 
index 53ab52b0313846313dbfa4fdfe0c0d6f4f7cf03c..bbb03252b0963d034780d68075efda6c300097c5 100644 (file)
@@ -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
 }
index 53a4441a5ee953d05f6daa84d50e8c4c97f4f946..e8fd58e80ce48352d37287356a00e2ee6afd5075 100644 (file)
@@ -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;