From f312f890f1bf035db52f3518ca9583a62999cf02 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 30 Oct 2014 23:13:53 +0500 Subject: Libmv: Support disabled color channels in tracking settings 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 | 2 +- extern/libmv/intern/frame_accessor.cc | 2 +- extern/libmv/intern/tracksN.cc | 2 + extern/libmv/intern/tracksN.h | 7 ++++ extern/libmv/libmv/autotrack/autotrack.cc | 48 +++++++++++++++++++++++- extern/libmv/libmv/autotrack/frame_accessor.h | 1 + extern/libmv/libmv/autotrack/marker.h | 9 +++++ source/blender/blenkernel/intern/tracking_auto.c | 5 +++ source/blender/blenkernel/intern/tracking_util.c | 28 +++++++------- 9 files changed, 88 insertions(+), 16 deletions(-) diff --git a/extern/libmv/bundle.sh b/extern/libmv/bundle.sh index 668c11bf94b..1ac377e17fe 100755 --- a/extern/libmv/bundle.sh +++ b/extern/libmv/bundle.sh @@ -213,7 +213,7 @@ ${tests} endif() else() list(APPEND SRC - intern/stub.cc + libmv-capi_stub.cc ) endif() diff --git a/extern/libmv/intern/frame_accessor.cc b/extern/libmv/intern/frame_accessor.cc index a7d969af05b..8bf2cab914b 100644 --- a/extern/libmv/intern/frame_accessor.cc +++ b/extern/libmv/intern/frame_accessor.cc @@ -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; diff --git a/extern/libmv/intern/tracksN.cc b/extern/libmv/intern/tracksN.cc index 9d68bce2869..9e1da88ef10 100644 --- a/extern/libmv/intern/tracksN.cc +++ b/extern/libmv/intern/tracksN.cc @@ -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) { diff --git a/extern/libmv/intern/tracksN.h b/extern/libmv/intern/tracksN.h index ea8b3e8a4f8..1366ea2f613 100644 --- a/extern/libmv/intern/tracksN.h +++ b/extern/libmv/intern/tracksN.h @@ -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 diff --git a/extern/libmv/libmv/autotrack/autotrack.cc b/extern/libmv/libmv/autotrack/autotrack.cc index ea5e2f7a8db..96a0ef64a50 100644 --- a/extern/libmv/libmv/autotrack/autotrack.cc +++ b/extern/libmv/libmv/autotrack/autotrack.cc @@ -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 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 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. ®ion, - NULL, + transform.get(), image); } diff --git a/extern/libmv/libmv/autotrack/frame_accessor.h b/extern/libmv/libmv/autotrack/frame_accessor.h index e788bb8ab97..8de5d865cd7 100644 --- a/extern/libmv/libmv/autotrack/frame_accessor.h +++ b/extern/libmv/libmv/autotrack/frame_accessor.h @@ -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; diff --git a/extern/libmv/libmv/autotrack/marker.h b/extern/libmv/libmv/autotrack/marker.h index dc73de84ee2..bb803313af8 100644 --- a/extern/libmv/libmv/autotrack/marker.h +++ b/extern/libmv/libmv/autotrack/marker.h @@ -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 void Offset(const T& offset) { diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c index 2cd13a90048..11753d7d14c 100644 --- a/source/blender/blenkernel/intern/tracking_auto.c +++ b/source/blender/blenkernel/intern/tracking_auto.c @@ -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, diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c index 250b575aa14..505f705857b 100644 --- a/source/blender/blenkernel/intern/tracking_util.c +++ b/source/blender/blenkernel/intern/tracking_util.c @@ -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. -- cgit v1.2.3