Libmv: Support disabled color channels in tracking settings
authorSergey Sharybin <sergey.vfx@gmail.com>
Thu, 30 Oct 2014 18:13:53 +0000 (23:13 +0500)
committerSergey Sharybin <sergey.vfx@gmail.com>
Thu, 30 Oct 2014 18:29:53 +0000 (23:29 +0500)
This was never ported to a new tracking pipeline and now it's done using
FrameAccessor::Transform routines. Quite striaghtforward, but i've changed
order of grayscale conversion in blender side with call of transform callback.

This way it's much easier to perform rescaling in libmv side.

extern/libmv/bundle.sh
extern/libmv/intern/frame_accessor.cc
extern/libmv/intern/tracksN.cc
extern/libmv/intern/tracksN.h
extern/libmv/libmv/autotrack/autotrack.cc
extern/libmv/libmv/autotrack/frame_accessor.h
extern/libmv/libmv/autotrack/marker.h
source/blender/blenkernel/intern/tracking_auto.c
source/blender/blenkernel/intern/tracking_util.c

index 668c11bf94b93703fa7c2ec1aaeef84b0b652093..1ac377e17fe5a23e11665ab056dd4e0ef1054cb1 100755 (executable)
@@ -213,7 +213,7 @@ ${tests}
        endif()
 else()
        list(APPEND SRC
-               intern/stub.cc
+               libmv-capi_stub.cc
        )
 endif()
 
index a7d969af05b95be1e1c0ddb75db2d08fbf1454e2..8bf2cab914bf5a0caf5f48a946c653ea3f1ae77f 100644 (file)
@@ -147,8 +147,8 @@ void libmv_frameAccessorgetTransformRun(const libmv_FrameTransform *transform,
                                         const libmv_FloatImage *input_image,
                                         libmv_FloatImage *output_image) {
   const FloatImage input(input_image->buffer,
-                         input_image->width,
                          input_image->height,
+                         input_image->width,
                          input_image->channels);
 
   FloatImage output;
index 9d68bce2869d0121839049828bd9a33b035992f5..9e1da88ef10a29ffcf759c5408afb2cdd5fd594c 100644 (file)
@@ -54,6 +54,7 @@ void libmv_apiMarkerToMarker(const libmv_Marker& libmv_marker,
   marker->reference_frame = libmv_marker.reference_frame;
   marker->model_type = (Marker::ModelType) libmv_marker.model_type;
   marker->model_id = libmv_marker.model_id;
+  marker->disabled_channels = libmv_marker.disabled_channels;
 }
 
 void libmv_markerToApiMarker(const Marker& marker,
@@ -78,6 +79,7 @@ void libmv_markerToApiMarker(const Marker& marker,
   libmv_marker->reference_frame = marker.reference_frame;
   libmv_marker->model_type = (libmv_MarkerModelType) marker.model_type;
   libmv_marker->model_id = marker.model_id;
+  libmv_marker->disabled_channels = marker.disabled_channels;
 }
 
 libmv_TracksN* libmv_tracksNewN(void) {
index ea8b3e8a4f889dbd008c1d2ccdd06ea5dd6b9aa1..1366ea2f613522389be20cac482ee811a43a4fbb 100644 (file)
@@ -60,6 +60,12 @@ typedef enum libmv_MarkerModelType {
   LIBMV_MARKER_MODEL_TYPE_CUBE,
 } libmv_MarkerModelType;
 
+enum libmv_MarkerChannel {
+  LIBMV_MARKER_CHANNEL_R = (1 << 0),
+  LIBMV_MARKER_CHANNEL_G = (1 << 1),
+  LIBMV_MARKER_CHANNEL_B = (1 << 2),
+};
+
 typedef struct libmv_Marker {
   int clip;
   int frame;
@@ -75,6 +81,7 @@ typedef struct libmv_Marker {
   int reference_frame;
   libmv_MarkerModelType model_type;
   int model_id;
+  int disabled_channels;
 } libmv_Marker;
 
 #ifdef __cplusplus
index ea5e2f7a8db1bc6387e4bb1251acc24a09ffe642..96a0ef64a504a37cdfe14ab9a1b7ebd3d1c2f174 100644 (file)
@@ -24,6 +24,7 @@
 #include "libmv/autotrack/quad.h"
 #include "libmv/autotrack/frame_accessor.h"
 #include "libmv/autotrack/predict_tracks.h"
+#include "libmv/base/scoped_ptr.h"
 #include "libmv/logging/logging.h"
 #include "libmv/numeric/numeric.h"
 
@@ -31,6 +32,47 @@ namespace mv {
 
 namespace {
 
+class DisableChannelsTransform : public FrameAccessor::Transform {
+ public:
+  DisableChannelsTransform(int disabled_channels)
+      : disabled_channels_(disabled_channels) {  }
+
+  int64_t key() const {
+    return disabled_channels_;
+  }
+
+  void run(const FloatImage& input, FloatImage* output) const {
+    bool disable_red   = (disabled_channels_ & Marker::CHANNEL_R) != 0,
+         disable_green = (disabled_channels_ & Marker::CHANNEL_G) != 0,
+         disable_blue  = (disabled_channels_ & Marker::CHANNEL_B) != 0;
+
+    LG << "Disabling channels: "
+       << (disable_red   ? "R " : "")
+       << (disable_green ? "G " : "")
+       << (disable_blue  ? "B" : "");
+
+    // It's important to rescale the resultappropriately so that e.g. if only
+    // blue is selected, it's not zeroed out.
+    float scale = (disable_red   ? 0.0f : 0.2126f) +
+                  (disable_green ? 0.0f : 0.7152f) +
+                  (disable_blue  ? 0.0f : 0.0722f);
+
+    output->Resize(input.Height(), input.Width(), 1);
+    for (int y = 0; y < input.Height(); y++) {
+      for (int x = 0; x < input.Width(); x++) {
+        float r = disable_red   ? 0.0f : input(y, x, 0);
+        float g = disable_green ? 0.0f : input(y, x, 1);
+        float b = disable_blue  ? 0.0f : input(y, x, 2);
+        (*output)(y, x, 0) = (0.2126f * r + 0.7152f * g + 0.0722f * b) / scale;
+      }
+    }
+  }
+
+ private:
+  // Bitfield representing visible channels, bits are from Marker::Channel.
+  int disabled_channels_;
+};
+
 template<typename QuadT, typename ArrayT>
 void QuadToArrays(const QuadT& quad, ArrayT* x, ArrayT* y) {
   for (int i = 0; i < 4; ++i) {
@@ -56,12 +98,16 @@ FrameAccessor::Key GetImageForMarker(const Marker& marker,
   // do rounding here.
   // Ideally we would need to pass IntRegion to the frame accessor.
   Region region = marker.search_region.Rounded();
+  libmv::scoped_ptr<FrameAccessor::Transform> transform = NULL;
+  if (marker.disabled_channels != 0) {
+    transform.reset(new DisableChannelsTransform(marker.disabled_channels));
+  }
   return frame_accessor->GetImage(marker.clip,
                                   marker.frame,
                                   FrameAccessor::MONO,
                                   0,  // No downscale for now.
                                   &region,
-                                  NULL,
+                                  transform.get(),
                                   image);
 }
 
index e788bb8ab978440fbb297469a7f10d9d7f666837..8de5d865cd71873fe75988339c1ce3f94d4f3a8c 100644 (file)
@@ -41,6 +41,7 @@ using libmv::FloatImage;
 // implementations to cache filtered image pieces).
 struct FrameAccessor {
   struct Transform {
+    virtual ~Transform() {  }
     // The key should depend on the transform arguments. Must be non-zero.
     virtual int64_t key() const = 0;
 
index dc73de84ee231fa93fe7c7702c46ddb362d64135..bb803313af8756266a454658974425e4529a5ccd 100644 (file)
@@ -104,6 +104,15 @@ struct Marker {
   // TODO(keir): Add a "int model_argument" to capture that e.g. a marker is on
   // the 3rd face of a cube.
 
+  enum Channel {
+    CHANNEL_R = (1 << 0),
+    CHANNEL_G = (1 << 1),
+    CHANNEL_B = (1 << 2),
+  };
+
+  // Channels from the original frame which this marker is unable to see.
+  int disabled_channels;
+
   // Offset everything (center, patch, search) by the given delta.
   template<typename T>
   void Offset(const T& offset) {
index 2cd13a90048a3aab6dcace0cd36914dee52b4a04..11753d7d14cd1330c38f7d3fa07e90a3ec0f2f44 100644 (file)
@@ -183,6 +183,11 @@ static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track,
                                                marker->framenr - 1 :
                                                marker->framenr;
        }
+
+       libmv_marker->disabled_channels =
+               ((track->flag & TRACK_DISABLE_RED)   ? LIBMV_MARKER_CHANNEL_R : 0) |
+               ((track->flag & TRACK_DISABLE_GREEN) ? LIBMV_MARKER_CHANNEL_G : 0) |
+               ((track->flag & TRACK_DISABLE_BLUE)  ? LIBMV_MARKER_CHANNEL_B : 0);
 }
 
 static void libmv_marker_to_dna_marker(libmv_Marker *libmv_marker,
index 250b575aa14ae44c6948ea888c119881ec2ecc78..505f705857b281eb931662fa3046990234572c9a 100644 (file)
@@ -754,19 +754,6 @@ static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor,
                               ibuf->y / (1 << downscale));
        }
 
-       if (input_mode == LIBMV_IMAGE_MODE_RGBA) {
-               BLI_assert(ibuf->channels == 3 || ibuf->channels == 4);
-               /* pass */
-       }
-       else /* if (input_mode == LIBMV_IMAGE_MODE_MONO) */ {
-               ImBuf *grayscale_ibuf = make_grayscale_ibuf_copy(final_ibuf);
-               if (final_ibuf != orig_ibuf) {
-                       /* We dereference original frame later. */
-                       IMB_freeImBuf(final_ibuf);
-               }
-               final_ibuf = grayscale_ibuf;
-       }
-
        if (transform != NULL) {
                libmv_FloatImage input_image, output_image;
                ibuf_to_float_image(final_ibuf, &input_image);
@@ -780,6 +767,21 @@ static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor,
                libmv_floatImageDestroy(&output_image);
        }
 
+       if (input_mode == LIBMV_IMAGE_MODE_RGBA) {
+               BLI_assert(ibuf->channels == 3 || ibuf->channels == 4);
+               /* pass */
+       }
+       else /* if (input_mode == LIBMV_IMAGE_MODE_MONO) */ {
+               if (final_ibuf->channels != 1) {
+                       ImBuf *grayscale_ibuf = make_grayscale_ibuf_copy(final_ibuf);
+                       if (final_ibuf != orig_ibuf) {
+                               /* We dereference original frame later. */
+                               IMB_freeImBuf(final_ibuf);
+                       }
+                       final_ibuf = grayscale_ibuf;
+               }
+       }
+
        /* it's possible processing stil didn't happen at this point,
         * but we really need a copy of the buffer to be transformed
         * and to be put to the cache.