diff --git a/applications/reconstruct/src/main.cpp b/applications/reconstruct/src/main.cpp index 8202aff31a10a164edb330173634016e296ed508..4ca06248a336a51bf6ca2aacc25aced4ec970e34 100644 --- a/applications/reconstruct/src/main.cpp +++ b/applications/reconstruct/src/main.cpp @@ -246,11 +246,14 @@ static void run(ftl::Configurable *root) { bool busy = false; - auto *smooth = ftl::config::create<ftl::filters::MLSSmoother>(root, "filters"); + // Create the source depth map filters + auto *filters = ftl::config::create<ftl::Filters>(root, "filters"); + filters->create<ftl::filters::DepthSmoother>("hfnoise"); + filters->create<ftl::filters::MLSSmoother>("mls"); group->setLatency(4); group->setName("ReconGroup"); - group->sync([splat,virt,&busy,&slave,&scene_A,&scene_B,&align,controls,smooth](ftl::rgbd::FrameSet &fs) -> bool { + group->sync([splat,virt,&busy,&slave,&scene_A,&scene_B,&align,controls,filters](ftl::rgbd::FrameSet &fs) -> bool { //cudaSetDevice(scene->getCUDADevice()); //if (slave.isPaused()) return true; @@ -265,7 +268,7 @@ static void run(ftl::Configurable *root) { // Swap the entire frameset to allow rapid return fs.swapTo(scene_A); - ftl::pool.push([&scene_B,&scene_A,&busy,&slave,&align, smooth](int id) { + ftl::pool.push([&scene_B,&scene_A,&busy,&slave,&align, filters](int id) { //cudaSetDevice(scene->getCUDADevice()); // TODO: Release frameset here... //cudaSafeCall(cudaStreamSynchronize(scene->getIntegrationStream())); @@ -296,7 +299,7 @@ static void run(ftl::Configurable *root) { cv::cuda::cvtColor(tmp,col, cv::COLOR_BGR2BGRA, 0); } - smooth->smooth(f, s); + filters->filter(f, s, 0); /*ftl::cuda::smoothing_factor( f.createTexture<float>(Channel::Depth), diff --git a/components/codecs/src/nvpipe_encoder.cpp b/components/codecs/src/nvpipe_encoder.cpp index 10901ef56993f25960cadd0e6f17778093f256a7..132a3209ad0849dd76f1a5f7438eba8f5655b854 100644 --- a/components/codecs/src/nvpipe_encoder.cpp +++ b/components/codecs/src/nvpipe_encoder.cpp @@ -59,6 +59,11 @@ bool NvPipeEncoder::encode(const cv::cuda::GpuMat &in, definition_t odefinition, auto width = ftl::codecs::getWidth(definition); auto height = ftl::codecs::getHeight(definition); + if (in.empty()) { + LOG(WARNING) << "No data"; + return false; + } + cv::cuda::GpuMat tmp; if (width != in.cols || height != in.rows) { LOG(WARNING) << "Mismatch resolution with encoding resolution"; diff --git a/components/filters/CMakeLists.txt b/components/filters/CMakeLists.txt index 92601b3714ac5e166d4e4f8eecf22c8f04edc58f..31fc04413f12bcfb4a0194b05516ccd63adb5cf9 100644 --- a/components/filters/CMakeLists.txt +++ b/components/filters/CMakeLists.txt @@ -1,6 +1,7 @@ add_library(ftlfilter src/smoothing.cpp - src/smoothing.cu + src/smoothing.cu + src/filter.cpp ) # These cause errors in CI build and are being removed from PCL in newer versions diff --git a/components/filters/include/ftl/filters/filter.hpp b/components/filters/include/ftl/filters/filter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d11ba08e48dae5a6b15af34a4ebd6535fc4201ab --- /dev/null +++ b/components/filters/include/ftl/filters/filter.hpp @@ -0,0 +1,65 @@ +#ifndef _FTL_FILTERS_FILTER_HPP_ + +#include <list> +#include <ftl/configurable.hpp> +#include <ftl/configuration.hpp> +#include <ftl/rgbd/frame.hpp> +#include <ftl/rgbd/source.hpp> +#include <ftl/cuda_common.hpp> + +namespace ftl { +//namespace filters { + +/** + * An abstract frame filter interface. Any kind of filter that operates on a + * single frame should use this as a base class. An example of a filter would + * be MLS smoothing, or optical flow temporal smoothing. Some 'filters' might + * simply generate additional channels, such as a 'Normals' filter that + * generates a normals channel. Filters may also have internal data buffers, + * these may also persist between frames in some cases. + */ +class Filter : public ftl::Configurable { + public: + explicit Filter(nlohmann::json &config); + virtual ~Filter(); + + virtual void filter(ftl::rgbd::Frame &f, ftl::rgbd::Source *s, cudaStream_t stream)=0; + + inline void enable() { enabled_ = true; } + inline void disable() { enabled_ = false; } + inline bool enabled() const { return enabled_; } + inline void enabled(bool e) { enabled_ = e; } + + protected: + bool enabled_; +}; + +/** + * Represent a sequential collection of filters. Each filter created is + * added to an internal list and then applied to a frame in the order they were + * created. + */ +class Filters : public ftl::Configurable { + public: + explicit Filters(nlohmann::json &config); + ~Filters(); + + template <typename T> + Filter *create(const std::string &name); + + void filter(ftl::rgbd::Frame &f, ftl::rgbd::Source *s, cudaStream_t stream=0); + + private: + std::list<ftl::Filter*> filters_; + Filter *_create(Filter *f); +}; + +//} +} + +template <typename T> +ftl::Filter *ftl::Filters::create(const std::string &name) { + return _create(dynamic_cast<ftl::Filter*>(ftl::create<T>(this, name))); +} + +#endif // _FTL_FILTERS_FILTER_HPP_ diff --git a/components/filters/include/ftl/filters/smoothing.hpp b/components/filters/include/ftl/filters/smoothing.hpp index 06f8a594155c95b7d5f1f2ab40f30086c4aa8f25..f6722e9b38b8a9fa862ae28934b508f78f86e0b5 100644 --- a/components/filters/include/ftl/filters/smoothing.hpp +++ b/components/filters/include/ftl/filters/smoothing.hpp @@ -1,32 +1,29 @@ #ifndef _FTL_SMOOTHING_HPP_ #define _FTL_SMOOTHING_HPP_ -#include <ftl/configurable.hpp> -#include <ftl/cuda_common.hpp> -#include <ftl/rgbd/source.hpp> -#include <ftl/rgbd/frame.hpp> +#include <ftl/filters/filter.hpp> namespace ftl { namespace filters { -class DepthSmoother : public ftl::Configurable { +class DepthSmoother : public ftl::Filter { public: explicit DepthSmoother(nlohmann::json &config); ~DepthSmoother(); - void smooth(ftl::rgbd::Frame &frame, ftl::rgbd::Source *src); + void filter(ftl::rgbd::Frame &frame, ftl::rgbd::Source *src, cudaStream_t stream) override; private: cv::cuda::GpuMat temp_; ftl::rgbd::Frame frames_[4]; }; -class MLSSmoother : public ftl::Configurable { +class MLSSmoother : public ftl::Filter { public: explicit MLSSmoother(nlohmann::json &config); ~MLSSmoother(); - void smooth(ftl::rgbd::Frame &frame, ftl::rgbd::Source *src); + void filter(ftl::rgbd::Frame &frame, ftl::rgbd::Source *src, cudaStream_t stream) override; private: }; diff --git a/components/filters/src/filter.cpp b/components/filters/src/filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4712ea7e7dcff9fc1e779ccba5493c1c00fd3d0a --- /dev/null +++ b/components/filters/src/filter.cpp @@ -0,0 +1,35 @@ +#include <ftl/filters/filter.hpp> + +using ftl::Filter; +using ftl::Filters; + +Filter::Filter(nlohmann::json &config) : ftl::Configurable(config) { + enabled_ = value("enabled", true); + + on("enabled", [this](const ftl::config::Event &e) { + enabled_ = value("enabled", true); + }); +} + +Filter::~Filter() {} + +Filters::Filters(nlohmann::json &config) : ftl::Configurable(config) { + +} + +Filters::~Filters() { + +} + +void Filters::filter(ftl::rgbd::Frame &f, ftl::rgbd::Source *s, cudaStream_t stream) { + for (auto i : filters_) { + if (i->enabled()) { + i->filter(f, s, stream); + } + } +} + +Filter *Filters::_create(Filter *f) { + filters_.push_back(f); + return f; +} diff --git a/components/filters/src/smoothing.cpp b/components/filters/src/smoothing.cpp index e2805174544875aaec56cc8c092a31e5173dfaa3..f473018e69a9a7636fb9b94453b12dee1af713af 100644 --- a/components/filters/src/smoothing.cpp +++ b/components/filters/src/smoothing.cpp @@ -8,7 +8,7 @@ using ftl::filters::MLSSmoother; using ftl::codecs::Channel; using cv::cuda::GpuMat; -DepthSmoother::DepthSmoother(nlohmann::json &config) : ftl::Configurable(config) { +DepthSmoother::DepthSmoother(nlohmann::json &config) : ftl::Filter(config) { } @@ -16,13 +16,13 @@ DepthSmoother::~DepthSmoother() { } -void DepthSmoother::smooth(ftl::rgbd::Frame &f, ftl::rgbd::Source *s) { +void DepthSmoother::filter(ftl::rgbd::Frame &f, ftl::rgbd::Source *s, cudaStream_t stream) { float var_thresh = value("variance_threshold", 0.0002f); - bool do_smooth = value("pre_smooth", false); + //bool do_smooth = value("pre_smooth", false); int levels = max(0, min(value("levels",0), 4)); int iters = value("iterations",5); - if (!do_smooth) return; + //if (!do_smooth) return; for (int i=0; i<iters; ++i) { ftl::cuda::smoothing_factor( @@ -59,7 +59,7 @@ void DepthSmoother::smooth(ftl::rgbd::Frame &f, ftl::rgbd::Source *s) { // ===== MLS =================================================================== -MLSSmoother::MLSSmoother(nlohmann::json &config) : ftl::Configurable(config) { +MLSSmoother::MLSSmoother(nlohmann::json &config) : ftl::Filter(config) { } @@ -67,13 +67,13 @@ MLSSmoother::~MLSSmoother() { } -void MLSSmoother::smooth(ftl::rgbd::Frame &f, ftl::rgbd::Source *s) { - bool do_smooth = value("mls_smooth", false); - if (!do_smooth) return; - +void MLSSmoother::filter(ftl::rgbd::Frame &f, ftl::rgbd::Source *s, cudaStream_t stream) { + //bool do_smooth = value("mls_smooth", false); float thresh = value("mls_threshold", 0.04f); int iters = value("mls_iterations", 1); + //if (!do_smooth) return; + for (int i=0; i<iters; ++i) { if (i > 0 || !f.hasChannel(Channel::Normals)) { ftl::cuda::normals(