From 5483663864f04c829af41e29d9af37180f96c82b Mon Sep 17 00:00:00 2001 From: Sebastian Hahta <joseha@utu.fi> Date: Fri, 30 Aug 2019 11:14:39 +0300 Subject: [PATCH] Support both Mat and GpuMat with automatic uploads/downloads --- .../rgbd-sources/include/ftl/rgbd/frame.hpp | 65 +++++++++++++++---- components/rgbd-sources/src/stereovideo.cpp | 15 +++-- 2 files changed, 63 insertions(+), 17 deletions(-) diff --git a/components/rgbd-sources/include/ftl/rgbd/frame.hpp b/components/rgbd-sources/include/ftl/rgbd/frame.hpp index 5b004a3ad..15428e665 100644 --- a/components/rgbd-sources/include/ftl/rgbd/frame.hpp +++ b/components/rgbd-sources/include/ftl/rgbd/frame.hpp @@ -11,13 +11,13 @@ class Frame { public: /* @todo REMOVE HARDCODED CHANNEL COUNT! */ - Frame() : channels_(11), available_(11, false) {} + Frame() : channels_host_(11), channels_gpu_(11), available_(11, 0) {} /* @brief Reset all channels without releasing memory */ void reset() { - std::fill(available_.begin(), available_.end(), false); + std::fill(available_.begin(), available_.end(), 0); } /* @brief Is there valid data in channel. Must be checked if user @@ -29,15 +29,52 @@ public: return available_[_channelIdx(channel)]; } - /* @brief Get reference to the channel GpuMat and marks it valid. - * If hasChannel() was false, user of this method must set - * valid data to the returned reference. + /* @brief Get reference to the channel. + * @param Channel type + * @param Output parameter + * @param User of the method sets data. NOTE: Only works on unused + * channels or if reset() was called previously (TODO). + * @returns True, if output parameter contains valid data */ - cv::cuda::GpuMat& getChannel(const ftl::rgbd::channel_t& channel) + + bool getChannel(const ftl::rgbd::channel_t& channel, cv::Mat& out, bool set=false) + { + auto idx = _channelIdx(channel); + bool retval = available_[idx] & mask_host; + if (!retval) + { + if (available_[idx] & mask_gpu) + { + channels_gpu_[idx].download(channels_host_[idx]); + retval = true; + set = true; + } + } + + if (set) { available_[idx] |= mask_host; } + + out = channels_host_[idx]; + return retval; + } + + bool getChannel(const ftl::rgbd::channel_t& channel, cv::cuda::GpuMat& out, bool set=false) { auto idx = _channelIdx(channel); - available_[idx] = true; - return channels_[idx]; + bool retval = available_[idx] & mask_gpu; + if (!retval) + { + if (available_[idx] & mask_host) + { + channels_gpu_[idx].upload(channels_host_[idx]); + retval = true; + set = true; + } + } + + if (set) { available_[idx] |= mask_host; } + + out = channels_gpu_[idx]; + return retval; } private: @@ -56,12 +93,18 @@ private: case kChanConfidence: return 7; case kChanFlow: return 8; case kChanEnergy: return 9; - default: return 0; // should not happen + default: return 0; // should not happen (error) } } - std::vector<cv::cuda::GpuMat> channels_; - std::vector<bool> available_; + std::vector<cv::Mat> channels_host_; + std::vector<cv::cuda::GpuMat> channels_gpu_; + + // bitmasks for each channel stored in available_ + static const uint mask_host = 1; + static const uint mask_gpu = 2; + + std::vector<uint> available_; }; } diff --git a/components/rgbd-sources/src/stereovideo.cpp b/components/rgbd-sources/src/stereovideo.cpp index 58a513a08..a4c19767c 100644 --- a/components/rgbd-sources/src/stereovideo.cpp +++ b/components/rgbd-sources/src/stereovideo.cpp @@ -173,8 +173,9 @@ bool StereoVideoSource::capture(int64_t ts) { bool StereoVideoSource::retrieve() { auto &frame = frames_[0]; frame.reset(); - cv::cuda::GpuMat& left = frame.getChannel(ftl::rgbd::kChanLeft); - cv::cuda::GpuMat& right = frame.getChannel(ftl::rgbd::kChanRight); + cv::cuda::GpuMat left, right; + frame.getChannel(ftl::rgbd::kChanLeft, left, true); + frame.getChannel(ftl::rgbd::kChanRight, right, true); lsrc_->get(left, right, calib_, stream2_); #ifdef HAVE_OPTFLOW @@ -208,10 +209,9 @@ void StereoVideoSource::swap() { bool StereoVideoSource::compute(int n, int b) { auto &frame = frames_[1]; - cv::cuda::GpuMat& left = frame.getChannel(ftl::rgbd::kChanLeft); - cv::cuda::GpuMat& right = frame.getChannel(ftl::rgbd::kChanRight); - cv::cuda::GpuMat& depth = frame.getChannel(ftl::rgbd::kChanDepth); - cv::cuda::GpuMat& disp = frame.getChannel(ftl::rgbd::kChanDisparity); + cv::cuda::GpuMat left, right, disp, depth; + frame.getChannel(ftl::rgbd::kChanLeft, left); + frame.getChannel(ftl::rgbd::kChanRight, right); const ftl::rgbd::channel_t chan = host_->getChannel(); if (left.empty() || right.empty()) return false; @@ -219,6 +219,9 @@ bool StereoVideoSource::compute(int n, int b) { if (chan == ftl::rgbd::kChanDepth) { + frame.getChannel(ftl::rgbd::kChanDepth, depth, true); + frame.getChannel(ftl::rgbd::kChanDisparity, disp, true); + 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_); -- GitLab