diff --git a/components/rgbd-sources/include/ftl/rgbd/detail/source.hpp b/components/rgbd-sources/include/ftl/rgbd/detail/source.hpp index a75fb1879f5e919cc306ca9b96a3f9562051f549..29edf722fe4a3eaac36c76f7c861797f8ff71a49 100644 --- a/components/rgbd-sources/include/ftl/rgbd/detail/source.hpp +++ b/components/rgbd-sources/include/ftl/rgbd/detail/source.hpp @@ -4,36 +4,13 @@ #include <Eigen/Eigen> #include <opencv2/opencv.hpp> #include <ftl/rgbd/camera.hpp> +#include <ftl/rgbd/frame.hpp> namespace ftl{ namespace rgbd { class Source; -// TODO: frame.hpp has to know the exact amount of channels -// (remove hardcoded value by providing exact value elsewhere). -// Possibly move channels to frame.hpp? - -typedef unsigned int channel_t; - -static const channel_t kChanNone = 0; -static const channel_t kChanLeft = 0x0001; -static const channel_t kChanDepth = 0x0002; -static const channel_t kChanRight = 0x0004; -static const channel_t kChanDisparity = 0x0008; -static const channel_t kChanDeviation = 0x0010; -static const channel_t kChanNormals = 0x0020; -static const channel_t kChanConfidence = 0x0040; -static const channel_t kChanFlow = 0x0080; -static const channel_t kChanEnergy = 0x0100; - -static const channel_t kChanOverlay1 = 0x1000; - -inline bool isFloatChannel(ftl::rgbd::channel_t chan) { - return (chan == ftl::rgbd::kChanDepth || chan == ftl::rgbd::kChanEnergy); -} - - typedef unsigned int capability_t; static const capability_t kCapMovable = 0x0001; // A movable virtual cam diff --git a/components/rgbd-sources/include/ftl/rgbd/frame.hpp b/components/rgbd-sources/include/ftl/rgbd/frame.hpp index ddc624d9b2dc05ee3745400d366c3017735579fc..993b49aa57b0eb76d4ef99a42c71869c6ac2d645 100644 --- a/components/rgbd-sources/include/ftl/rgbd/frame.hpp +++ b/components/rgbd-sources/include/ftl/rgbd/frame.hpp @@ -1,17 +1,44 @@ #pragma once +#ifndef _FTL_RGBD_FRAME_HPP_ +#define _FTL_RGBD_FRAME_HPP_ -#include <ftl/rgbd/detail/source.hpp> #include <ftl/configuration.hpp> #include <opencv2/core.hpp> +#include <opencv2/core/cuda.hpp> namespace ftl { namespace rgbd { +typedef unsigned int channel_t; + +static const channel_t kChanNone = 0; +static const channel_t kChanLeft = 0x0001; +static const channel_t kChanDepth = 0x0002; +static const channel_t kChanRight = 0x0004; +static const channel_t kChanDisparity = 0x0008; +static const channel_t kChanDeviation = 0x0010; +static const channel_t kChanNormals = 0x0020; +static const channel_t kChanConfidence = 0x0040; +static const channel_t kChanFlow = 0x0080; +static const channel_t kChanEnergy = 0x0100; + +static const channel_t kChanOverlay1 = 0x1000; + +// maximum number of available channels +static const unsigned int n_channels = 11; + +inline bool isFloatChannel(ftl::rgbd::channel_t chan) { + return (chan == ftl::rgbd::kChanDepth || chan == ftl::rgbd::kChanEnergy); +} + +class Frame; + class Frame { public: - /* @todo TODO: REMOVE HARDCODED CHANNEL COUNT! - */ - Frame() : channels_host_(11), channels_gpu_(11), available_(11, 0) {} + Frame() : channels_host_(n_channels), + channels_gpu_(n_channels), + available_(n_channels, 0) + {} /* @brief Reset all channels without releasing memory. */ @@ -27,16 +54,27 @@ public: return available_[_channelIdx(channel)]; } - /* @brief get reference to the channel contents - * @param channel type - * @returns const reference to channel data + /* @brief Method to get reference to the channel content + * @param Channel type + * @returns Const reference to channel data * - * Methods automatically copy between host/gpu if the data is only available - * in the other. Results are cached. Result is valid only if hasChannel() is - * true. + * Result is valid only if hasChannel() is true. Host/Gpu transfer is + * performed, if necessary, but only once unless channel contents is + * changed by calling setChannel(). Return value valid only if + * hasChannel(channel) is true. */ template <typename T> const T& getChannel(const ftl::rgbd::channel_t& channel); + + + /* @brief Method to set/modify channel content + * @param Channel type + * @returns Reference to channel data + * + * Returns non-const reference to channel data. Invalidates other copies of + * the data (host/gpu) for the specified channel, next time getChannel() is + * called a memory transfer may occur. + */ template <typename T> T& setChannel(const ftl::rgbd::channel_t& channel); private: @@ -70,5 +108,12 @@ private: std::vector<uint> available_; }; +template<> const cv::Mat& Frame::getChannel(const ftl::rgbd::channel_t& channel); +template<> cv::Mat& Frame::setChannel(const ftl::rgbd::channel_t& channel); +template<> const cv::cuda::GpuMat& Frame::getChannel(const ftl::rgbd::channel_t& channel); +template<> cv::cuda::GpuMat& Frame::setChannel(const ftl::rgbd::channel_t& channel); + } } + +#endif // _FTL_RGBD_FRAME_HPP_ \ No newline at end of file diff --git a/components/rgbd-sources/src/algorithms/fixstars_sgm.cpp b/components/rgbd-sources/src/algorithms/fixstars_sgm.cpp index 71f714c3afd06c7c0b362d7b0f635efcf4dd808b..b37c7b0780c785cec7b94dc2b5afe3fafabdeb93 100644 --- a/components/rgbd-sources/src/algorithms/fixstars_sgm.cpp +++ b/components/rgbd-sources/src/algorithms/fixstars_sgm.cpp @@ -64,9 +64,17 @@ void FixstarsSGM::init(const cv::Size size) { ); } -void FixstarsSGM::compute(const cv::cuda::GpuMat &l, const cv::cuda::GpuMat &r, - cv::cuda::GpuMat &disp, cv::cuda::Stream &stream) +void FixstarsSGM::compute(ftl::rgbd::Frame &frame, cv::cuda::Stream &stream) { + const auto &l = frame.getChannel<GpuMat>(ftl::rgbd::kChanLeft); + const auto &r = frame.getChannel<GpuMat>(ftl::rgbd::kChanRight); + auto &disp = frame.setChannel<GpuMat>(ftl::rgbd::kChanDisparity); + + if (disp.size() != l.size()) + { + disp = GpuMat(l.size(), CV_32FC1); + } + if (l.size() != size_) { // re-use same buffer for l/r cv::cuda::resize(r, l_downscaled_, size_, 0.0, 0.0, cv::INTER_CUBIC, stream); diff --git a/components/rgbd-sources/src/algorithms/fixstars_sgm.hpp b/components/rgbd-sources/src/algorithms/fixstars_sgm.hpp index d773446d784761af8fe75fd7c98db75f3d4fd10f..14f80bf89408bec04a4556c0d2592fe0b09a3681 100644 --- a/components/rgbd-sources/src/algorithms/fixstars_sgm.hpp +++ b/components/rgbd-sources/src/algorithms/fixstars_sgm.hpp @@ -30,7 +30,7 @@ namespace ftl { public: explicit FixstarsSGM(nlohmann::json &config); - void compute(const cv::cuda::GpuMat &l, const cv::cuda::GpuMat &r, cv::cuda::GpuMat &disp, cv::cuda::Stream &stream) override; + void compute(ftl::rgbd::Frame &frame, cv::cuda::Stream &stream) override; void setMask(cv::Mat &mask) override; /* Factory creator */ diff --git a/components/rgbd-sources/src/disparity.hpp b/components/rgbd-sources/src/disparity.hpp index e7e78b277544afd87870e62ca5b833b15d9cfd6d..a5e7efea79e9572f095f01346a9574257da332fd 100644 --- a/components/rgbd-sources/src/disparity.hpp +++ b/components/rgbd-sources/src/disparity.hpp @@ -8,6 +8,7 @@ #include <opencv2/opencv.hpp> #include <nlohmann/json.hpp> #include <ftl/configurable.hpp> +#include <ftl/rgbd/frame.hpp> namespace ftl { namespace rgbd { @@ -32,7 +33,15 @@ class Disparity : public ftl::Configurable { * Pure virtual function representing the actual computation of * disparity from left and right images to be implemented. */ - virtual void compute(const cv::cuda::GpuMat &l, const cv::cuda::GpuMat &r, cv::cuda::GpuMat &disp, cv::cuda::Stream &stream)=0; + virtual void compute(Frame &frame, cv::cuda::Stream &stream)=0; + virtual void compute(cv::cuda::GpuMat &l, cv::cuda::GpuMat &r, cv::cuda::GpuMat &disp, cv::cuda::Stream &stream) + { + ftl::rgbd::Frame frame; + frame.setChannel<cv::cuda::GpuMat>(kChanLeft) = l; + frame.setChannel<cv::cuda::GpuMat>(kChanRight) = r; + frame.setChannel<cv::cuda::GpuMat>(kChanDisparity) = disp; + } + /** * Factory registration class. diff --git a/components/rgbd-sources/src/frame.cpp b/components/rgbd-sources/src/frame.cpp index 62b3795ff79c4f728cc637b5e03dd646642a1abe..ea6a94f4f98763dccf57299f606b9b9b53c8f17f 100644 --- a/components/rgbd-sources/src/frame.cpp +++ b/components/rgbd-sources/src/frame.cpp @@ -6,7 +6,7 @@ namespace rgbd { template<> const cv::Mat& Frame::getChannel(const ftl::rgbd::channel_t& channel) { - auto idx = _channelIdx(channel); + size_t idx = _channelIdx(channel); if (!(available_[idx] & mask_host)) { if (available_[idx] & mask_gpu) @@ -21,14 +21,14 @@ template<> const cv::Mat& Frame::getChannel(const ftl::rgbd::channel_t& channel) template<> cv::Mat& Frame::setChannel(const ftl::rgbd::channel_t& channel) { - auto idx = _channelIdx(channel); + size_t idx = _channelIdx(channel); available_[idx] = mask_host; return channels_host_[idx]; } template<> const cv::cuda::GpuMat& Frame::getChannel(const ftl::rgbd::channel_t& channel) { - auto idx = _channelIdx(channel); + size_t idx = _channelIdx(channel); if (!(available_[idx] & mask_gpu)) { if (available_[idx] & mask_host) @@ -43,7 +43,7 @@ template<> const cv::cuda::GpuMat& Frame::getChannel(const ftl::rgbd::channel_t& template<> cv::cuda::GpuMat& Frame::setChannel(const ftl::rgbd::channel_t& channel) { - auto idx = _channelIdx(channel); + size_t idx = _channelIdx(channel); available_[idx] = mask_gpu; return channels_gpu_[idx]; } diff --git a/components/rgbd-sources/src/stereovideo.cpp b/components/rgbd-sources/src/stereovideo.cpp index 9e2de4615691d2bf583231a1f94f5020afc21eff..5a1ecfdb6a0319dc535e9e50e8ce8f6a102d1876 100644 --- a/components/rgbd-sources/src/stereovideo.cpp +++ b/components/rgbd-sources/src/stereovideo.cpp @@ -217,16 +217,16 @@ bool StereoVideoSource::compute(int n, int b) { if (left.empty() || right.empty()) return false; if (chan == ftl::rgbd::kChanDepth) { + disp_->compute(frame, stream_); + + auto &disp = frame.getChannel<cv::cuda::GpuMat>(ftl::rgbd::kChanDisparity); auto &depth = frame.setChannel<cv::cuda::GpuMat>(ftl::rgbd::kChanDepth); - auto &disp = frame.setChannel<cv::cuda::GpuMat>(ftl::rgbd::kChanDisparity); - if (depth.empty()) depth = cv::cuda::GpuMat(left.size(), CV_32FC1); - if (disp.empty()) disp = cv::cuda::GpuMat(left.size(), CV_32FC1); - disp_->compute(left, right, disp, stream_); + ftl::cuda::disparity_to_depth(disp, depth, params_, stream_); + left.download(rgb_, stream_); depth.download(depth_, stream_); - stream_.waitForCompletion(); // TODO:(Nick) Move to getFrames } else if (chan == ftl::rgbd::kChanRight) { left.download(rgb_, stream_);