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.
This commit is contained in:
Sergey Sharybin 2014-10-30 23:13:53 +05:00
parent 606329d0f8
commit f312f890f1
9 changed files with 88 additions and 16 deletions

@ -213,7 +213,7 @@ ${tests}
endif() endif()
else() else()
list(APPEND SRC list(APPEND SRC
intern/stub.cc libmv-capi_stub.cc
) )
endif() endif()

@ -147,8 +147,8 @@ void libmv_frameAccessorgetTransformRun(const libmv_FrameTransform *transform,
const libmv_FloatImage *input_image, const libmv_FloatImage *input_image,
libmv_FloatImage *output_image) { libmv_FloatImage *output_image) {
const FloatImage input(input_image->buffer, const FloatImage input(input_image->buffer,
input_image->width,
input_image->height, input_image->height,
input_image->width,
input_image->channels); input_image->channels);
FloatImage output; FloatImage output;

@ -54,6 +54,7 @@ void libmv_apiMarkerToMarker(const libmv_Marker& libmv_marker,
marker->reference_frame = libmv_marker.reference_frame; marker->reference_frame = libmv_marker.reference_frame;
marker->model_type = (Marker::ModelType) libmv_marker.model_type; marker->model_type = (Marker::ModelType) libmv_marker.model_type;
marker->model_id = libmv_marker.model_id; marker->model_id = libmv_marker.model_id;
marker->disabled_channels = libmv_marker.disabled_channels;
} }
void libmv_markerToApiMarker(const Marker& marker, 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->reference_frame = marker.reference_frame;
libmv_marker->model_type = (libmv_MarkerModelType) marker.model_type; libmv_marker->model_type = (libmv_MarkerModelType) marker.model_type;
libmv_marker->model_id = marker.model_id; libmv_marker->model_id = marker.model_id;
libmv_marker->disabled_channels = marker.disabled_channels;
} }
libmv_TracksN* libmv_tracksNewN(void) { libmv_TracksN* libmv_tracksNewN(void) {

@ -60,6 +60,12 @@ typedef enum libmv_MarkerModelType {
LIBMV_MARKER_MODEL_TYPE_CUBE, LIBMV_MARKER_MODEL_TYPE_CUBE,
} libmv_MarkerModelType; } 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 { typedef struct libmv_Marker {
int clip; int clip;
int frame; int frame;
@ -75,6 +81,7 @@ typedef struct libmv_Marker {
int reference_frame; int reference_frame;
libmv_MarkerModelType model_type; libmv_MarkerModelType model_type;
int model_id; int model_id;
int disabled_channels;
} libmv_Marker; } libmv_Marker;
#ifdef __cplusplus #ifdef __cplusplus

@ -24,6 +24,7 @@
#include "libmv/autotrack/quad.h" #include "libmv/autotrack/quad.h"
#include "libmv/autotrack/frame_accessor.h" #include "libmv/autotrack/frame_accessor.h"
#include "libmv/autotrack/predict_tracks.h" #include "libmv/autotrack/predict_tracks.h"
#include "libmv/base/scoped_ptr.h"
#include "libmv/logging/logging.h" #include "libmv/logging/logging.h"
#include "libmv/numeric/numeric.h" #include "libmv/numeric/numeric.h"
@ -31,6 +32,47 @@ namespace mv {
namespace { 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> template<typename QuadT, typename ArrayT>
void QuadToArrays(const QuadT& quad, ArrayT* x, ArrayT* y) { void QuadToArrays(const QuadT& quad, ArrayT* x, ArrayT* y) {
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
@ -56,12 +98,16 @@ FrameAccessor::Key GetImageForMarker(const Marker& marker,
// do rounding here. // do rounding here.
// Ideally we would need to pass IntRegion to the frame accessor. // Ideally we would need to pass IntRegion to the frame accessor.
Region region = marker.search_region.Rounded(); 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, return frame_accessor->GetImage(marker.clip,
marker.frame, marker.frame,
FrameAccessor::MONO, FrameAccessor::MONO,
0, // No downscale for now. 0, // No downscale for now.
&region, &region,
NULL, transform.get(),
image); image);
} }

@ -41,6 +41,7 @@ using libmv::FloatImage;
// implementations to cache filtered image pieces). // implementations to cache filtered image pieces).
struct FrameAccessor { struct FrameAccessor {
struct Transform { struct Transform {
virtual ~Transform() { }
// The key should depend on the transform arguments. Must be non-zero. // The key should depend on the transform arguments. Must be non-zero.
virtual int64_t key() const = 0; virtual int64_t key() const = 0;

@ -104,6 +104,15 @@ struct Marker {
// TODO(keir): Add a "int model_argument" to capture that e.g. a marker is on // TODO(keir): Add a "int model_argument" to capture that e.g. a marker is on
// the 3rd face of a cube. // 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. // Offset everything (center, patch, search) by the given delta.
template<typename T> template<typename T>
void Offset(const T& offset) { void Offset(const T& offset) {

@ -183,6 +183,11 @@ static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track,
marker->framenr - 1 : marker->framenr - 1 :
marker->framenr; 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, static void libmv_marker_to_dna_marker(libmv_Marker *libmv_marker,

@ -754,19 +754,6 @@ static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor,
ibuf->y / (1 << downscale)); 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) { if (transform != NULL) {
libmv_FloatImage input_image, output_image; libmv_FloatImage input_image, output_image;
ibuf_to_float_image(final_ibuf, &input_image); ibuf_to_float_image(final_ibuf, &input_image);
@ -780,6 +767,21 @@ static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor,
libmv_floatImageDestroy(&output_image); 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, /* it's possible processing stil didn't happen at this point,
* but we really need a copy of the buffer to be transformed * but we really need a copy of the buffer to be transformed
* and to be put to the cache. * and to be put to the cache.