Libmv: Support disabled color channels in trackign settings
authorSergey Sharybin <sergey.vfx@gmail.com>
Thu, 30 Oct 2014 17:03:19 +0000 (22:03 +0500)
committerSergey Sharybin <sergey.vfx@gmail.com>
Thu, 30 Oct 2014 17:03:19 +0000 (22:03 +0500)
This was never ported to a new trackign 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/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 9d68bce2869d0121839049828bd9a33b035992f5..a573478cbc5640ed232f7fec90d24b67dda178d2 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->visible_channels = libmv_marker.visible_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->visible_channels = marker.visible_channels;
 }
 
 libmv_TracksN* libmv_tracksNewN(void) {
index ea8b3e8a4f889dbd008c1d2ccdd06ea5dd6b9aa1..12549bd76e76bef4c11d6e3fbfa0043d3d727cfb 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 visible_channels;
 } libmv_Marker;
 
 #ifdef __cplusplus
index ea5e2f7a8db1bc6387e4bb1251acc24a09ffe642..4a02031bfe6f8b6e660cbf9cfefad943a193dc09 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,48 @@ namespace mv {
 
 namespace {
 
+class DisableChannelsTransform : public FrameAccessor::Transform {
+ public:
+  DisableChannelsTransform(int visible_channels)
+      : visible_channels_(visible_channels) {  }
+
+  int64_t key() const {
+    // We invert bits here so key is never null.
+    return !visible_channels_;
+  }
+
+  void run(const FloatImage& input, FloatImage* output) const {
+    bool disable_red   = (visible_channels_ & Marker::CHANNEL_R) == 0,
+         disable_green = (visible_channels_ & Marker::CHANNEL_G) == 0,
+         disable_blue  = (visible_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.Width(), input.Height(), 1);
+    for (int y = 0; y < input.Height(); y++) {
+      for (int x = 0; x < input.Width(); x++) {
+        float r = disable_red   ? 0.0f : input(x, y, 0);
+        float g = disable_green ? 0.0f : input(x, y, 1);
+        float b = disable_blue  ? 0.0f : input(x, y, 2);
+        (*output)(x, y, 0) = (0.2126f * r + 0.7152f * g + 0.0722f * b) / scale;
+      }
+    }
+  }
+
+ private:
+  // Bitfield representing visible channels, bits are from Marker::Channel.
+  int visible_channels_;
+};
+
 template<typename QuadT, typename ArrayT>
 void QuadToArrays(const QuadT& quad, ArrayT* x, ArrayT* y) {
   for (int i = 0; i < 4; ++i) {
@@ -56,12 +99,18 @@ 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.visible_channels != (Marker::CHANNEL_R |
+                                  Marker::CHANNEL_G |
+                                  Marker::CHANNEL_B)) {
+    transform.reset(new DisableChannelsTransform(marker.visible_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..394ec97f81542dc206d2dc1abd386611f203870e 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.
 
+  // Channels from the original frame which this marker is able to see.
+  enum Channel {
+    CHANNEL_R = (1 << 0),
+    CHANNEL_G = (1 << 1),
+    CHANNEL_B = (1 << 2),
+  };
+
+  int visible_channels;
+
   // Offset everything (center, patch, search) by the given delta.
   template<typename T>
   void Offset(const T& offset) {
index 2cd13a90048a3aab6dcace0cd36914dee52b4a04..f344e60a7a5d5813c6aa0ea3b1c3b1b56523eaf6 100644 (file)
@@ -183,6 +183,11 @@ static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track,
                                                marker->framenr - 1 :
                                                marker->framenr;
        }
+
+       libmv_marker->visible_channels =
+               ((track->flag & TRACK_DISABLE_RED)   ? 0 : LIBMV_MARKER_CHANNEL_R) |
+               ((track->flag & TRACK_DISABLE_GREEN) ? 0 : LIBMV_MARKER_CHANNEL_G) |
+               ((track->flag & TRACK_DISABLE_BLUE)  ? 0 : LIBMV_MARKER_CHANNEL_B);
 }
 
 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.