diff --git a/doc/changes/auxiliary/mr.825.md b/doc/changes/auxiliary/mr.825.md new file mode 100644 index 000000000..f6e4f62a5 --- /dev/null +++ b/doc/changes/auxiliary/mr.825.md @@ -0,0 +1,2 @@ +t/fm: Add simple FrameMat that wraps a cv::Mat, this allows us to easily pass +cv::Mat's around without the C code needing to know about OpenCV. diff --git a/src/xrt/auxiliary/CMakeLists.txt b/src/xrt/auxiliary/CMakeLists.txt index 44eff39c8..c95886637 100644 --- a/src/xrt/auxiliary/CMakeLists.txt +++ b/src/xrt/auxiliary/CMakeLists.txt @@ -97,6 +97,8 @@ if(XRT_HAVE_OPENCV) tracking/t_debug_hsv_picker.cpp tracking/t_debug_hsv_viewer.cpp tracking/t_file.cpp + tracking/t_frame_cv_mat_wrapper.cpp + tracking/t_frame_cv_mat_wrapper.hpp tracking/t_fusion.hpp tracking/t_helper_debug_sink.hpp tracking/t_hsv_filter.c diff --git a/src/xrt/auxiliary/meson.build b/src/xrt/auxiliary/meson.build index 2d2e2bc0f..3e41cbd55 100644 --- a/src/xrt/auxiliary/meson.build +++ b/src/xrt/auxiliary/meson.build @@ -205,6 +205,8 @@ if build_tracking 'tracking/t_debug_hsv_picker.cpp', 'tracking/t_debug_hsv_viewer.cpp', 'tracking/t_file.cpp', + 'tracking/t_frame_cv_mat_wrapper.cpp', + 'tracking/t_frame_cv_mat_wrapper.hpp', 'tracking/t_fusion.hpp', 'tracking/t_helper_debug_sink.hpp', 'tracking/t_hsv_filter.c', diff --git a/src/xrt/auxiliary/tracking/t_frame_cv_mat_wrapper.cpp b/src/xrt/auxiliary/tracking/t_frame_cv_mat_wrapper.cpp new file mode 100644 index 000000000..122ca51be --- /dev/null +++ b/src/xrt/auxiliary/tracking/t_frame_cv_mat_wrapper.cpp @@ -0,0 +1,116 @@ +// Copyright 2021, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Simple @ref xrt_frame wrapper around a @ref cv::Mat. + * @author Jakob Bornecrantz + * @ingroup aux_tracking + */ + +#include "util/u_format.h" + +#include "tracking/t_frame_cv_mat_wrapper.hpp" + + +namespace xrt::auxiliary::tracking { + + +/* + * + * C functions. + * + */ + +extern "C" void +frame_mat_destroy(struct xrt_frame *xf) +{ + FrameMat *fm = (FrameMat *)xf; + delete fm; +} + + +/* + * + * Member functions + * + */ + +void +FrameMat::fillInFields(cv::Mat mat, xrt_format format, const Params ¶ms) +{ + uint32_t width = (uint32_t)mat.cols; + uint32_t height = (uint32_t)mat.rows; + size_t stride = mat.step[0]; + size_t size = stride * height; + + this->matrix = mat; + + // Main wrapping of cv::Mat by frame. + xrt_frame &frame = this->frame; + frame.reference.count = 1; + frame.destroy = frame_mat_destroy; + frame.data = mat.ptr(); + frame.format = format; + frame.width = width; + frame.height = height; + frame.stride = stride; + frame.size = size; + + // Params + frame.timestamp = params.timestamp_ns; + frame.stereo_format = params.stereo_format; +} + +FrameMat::~FrameMat() +{ + // Noop +} + +FrameMat::FrameMat() +{ + // Noop +} + + +/* + * + * Static functions. + * + */ + +void +FrameMat::wrapR8G8B8(cv::Mat mat, xrt_frame **fm_out, const Params /*&&?*/ params) +{ + assert(mat.channels() == 3); + assert(mat.type() == CV_8UC3); + + + FrameMat *fm = new FrameMat(); + fm->fillInFields(mat, XRT_FORMAT_R8G8B8, params); + + // Unreference any old frames. + xrt_frame_reference(fm_out, NULL); + + // Already has a ref count of one. + *fm_out = &fm->frame; +} + +void +FrameMat::wrapL8(cv::Mat mat, xrt_frame **fm_out, const Params /*&&?*/ params) +{ + assert(mat.channels() == 1); + assert(mat.type() == CV_8UC1); + + + FrameMat *fm = new FrameMat(); + fm->fillInFields(mat, XRT_FORMAT_L8, params); + + // Unreference any old frames. + xrt_frame_reference(fm_out, NULL); + + // Already has a ref count of one. + *fm_out = &fm->frame; +} + + +} // namespace xrt::auxiliary::tracking diff --git a/src/xrt/auxiliary/tracking/t_frame_cv_mat_wrapper.hpp b/src/xrt/auxiliary/tracking/t_frame_cv_mat_wrapper.hpp new file mode 100644 index 000000000..bac6b1f7e --- /dev/null +++ b/src/xrt/auxiliary/tracking/t_frame_cv_mat_wrapper.hpp @@ -0,0 +1,70 @@ +// Copyright 2021, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Simple @ref xrt_frame wrapper around a @ref cv::Mat. + * @author Jakob Bornecrantz + * @ingroup aux_tracking + */ + +#include "xrt/xrt_frame.h" + +#include + + +namespace xrt::auxiliary::tracking { + + +class FrameMat +{ +public: + /*! + * Additional optional parameters for frame creation. + */ + class Params + { + public: + enum xrt_stereo_format stereo_format; + uint64_t timestamp_ns; + }; + + +public: + // Exposed to the C api. + struct xrt_frame frame = {}; + + // The @ref cv::Mat that holds the data. + cv::Mat matrix = cv::Mat(); + + +public: + /*! + * Only public due to C needed to destroy it. + */ + ~FrameMat(); + + /*! + * Wraps the given @ref cv::Mat assuming it's a 24bit RGB format matrix, the pointer pointed to by @ref xf_ptr + * will have it's reference updated. + */ + static void + wrapR8G8B8(cv::Mat mat, xrt_frame **xf_ptr, const Params /*&&?*/ params = {}); + + /*! + * Wraps the given @ref cv::Mat assuming it's a 8bit format matrix, the pointer pointed to by @ref xf_ptr will + * have it's reference updated. + */ + static void + wrapL8(cv::Mat mat, xrt_frame **xf_ptr, const Params /*&&?*/ params = {}); + + +private: + FrameMat(); + + void + fillInFields(cv::Mat mat, xrt_format format, const Params ¶ms); +}; + + + +} // namespace xrt::auxiliary::tracking