diff --git a/applications/reconstruct/src/main.cpp b/applications/reconstruct/src/main.cpp index a3e5504a41b11ef0f2b020710b88dae050b0d9c1..55c6e6d1c92f60512817d4ac349b37cad9f6bd30 100644 --- a/applications/reconstruct/src/main.cpp +++ b/applications/reconstruct/src/main.cpp @@ -246,7 +246,7 @@ static void run(ftl::Configurable *root) { bool busy = false; - auto *smooth = ftl::config::create<ftl::DepthSmoother>(root, "filters"); + auto *smooth = ftl::config::create<ftl::filters::DepthSmoother>(root, "filters"); group->setLatency(4); group->setName("ReconGroup"); diff --git a/components/filters/include/ftl/filters/smoothing.hpp b/components/filters/include/ftl/filters/smoothing.hpp index 5e5035f58981107d94f20ad948afe80297254edb..06f8a594155c95b7d5f1f2ab40f30086c4aa8f25 100644 --- a/components/filters/include/ftl/filters/smoothing.hpp +++ b/components/filters/include/ftl/filters/smoothing.hpp @@ -7,6 +7,7 @@ #include <ftl/rgbd/frame.hpp> namespace ftl { +namespace filters { class DepthSmoother : public ftl::Configurable { public: @@ -20,6 +21,17 @@ class DepthSmoother : public ftl::Configurable { ftl::rgbd::Frame frames_[4]; }; +class MLSSmoother : public ftl::Configurable { + public: + explicit MLSSmoother(nlohmann::json &config); + ~MLSSmoother(); + + void smooth(ftl::rgbd::Frame &frame, ftl::rgbd::Source *src); + + private: +}; + +} } #endif // _FTL_SMOOTHING_HPP_ diff --git a/components/filters/src/smoothing.cpp b/components/filters/src/smoothing.cpp index edd6a072fbb51cc498b243c8530f3abdb550e592..ce0e03db369e436b89d47f42c19a0c43fa1b0bb8 100644 --- a/components/filters/src/smoothing.cpp +++ b/components/filters/src/smoothing.cpp @@ -1,7 +1,8 @@ #include <ftl/filters/smoothing.hpp> #include "smoothing_cuda.hpp" -using ftl::DepthSmoother; +using ftl::filters::DepthSmoother; +using ftl::filters::MLSSmoother; using ftl::codecs::Channel; using cv::cuda::GpuMat; @@ -53,3 +54,33 @@ void DepthSmoother::smooth(ftl::rgbd::Frame &f, ftl::rgbd::Source *s) { //cv::cuda::subtract(f.get<GpuMat>(Channel::Depth), f.get<GpuMat>(Channel::Smoothing), f.get<GpuMat>(Channel::Depth)); } + +// ===== MLS =================================================================== + +MLSSmoother::MLSSmoother(nlohmann::json &config) : ftl::Configurable(config) { + +} + +MLSSmoother::~MLSSmoother() { + +} + +void MLSSmoother::smooth(ftl::rgbd::Frame &f, ftl::rgbd::Source *s) { + if (!f.hasChannel(Channel::Normals)) { + LOG(ERROR) << "Missing normals for MLS smooth"; + return; + } + + float thresh = value("mls_threshold", 0.04f); + ftl::cuda::mls_smooth( + f.createTexture<float4>(Channel::Normals), + f.createTexture<float>(Channel::Depth), + f.createTexture<float>(Channel::Depth2, ftl::rgbd::Format<float>(f.get<cv::cuda::GpuMat>(Channel::Depth).size())), + thresh, + s->parameters(), + 0 + ); + + +} + diff --git a/components/filters/src/smoothing.cu b/components/filters/src/smoothing.cu index 43cb1f6bd0a56760aa2c6d4d3fff4c664631c404..0ba749d25c57e23496df0a59b5428dea0a2c0d27 100644 --- a/components/filters/src/smoothing.cu +++ b/components/filters/src/smoothing.cu @@ -6,6 +6,90 @@ using ftl::cuda::TextureObject; #define T_PER_BLOCK 8 +// ===== MLS Smooth ============================================================ + +/* + * Smooth depth map using Moving Least Squares + */ + template <int SEARCH_RADIUS> + __global__ void mls_smooth_kernel( + TextureObject<float4> normals, + TextureObject<float> depth_in, // Virtual depth map + TextureObject<float> depth_out, // Accumulated output + float smoothing, + ftl::rgbd::Camera camera) { + + const int x = blockIdx.x*blockDim.x + threadIdx.x; + const int y = blockIdx.y*blockDim.y + threadIdx.y; + + if (x < 0 || y < 0 || x >= depth_in.width() || y >= depth_in.height()) return; + + float3 aX = make_float3(0.0f,0.0f,0.0f); + float3 nX = make_float3(0.0f,0.0f,0.0f); + float contrib = 0.0f; + + float d0 = depth_in.tex2D(x, y); + if (d0 < camera.minDepth || d0 > camera.maxDepth) return; + float3 X = camera.screenToCam((int)(x),(int)(y),d0); + + // Neighbourhood + for (int v=-SEARCH_RADIUS; v<=SEARCH_RADIUS; ++v) { + for (int u=-SEARCH_RADIUS; u<=SEARCH_RADIUS; ++u) { + const float d = depth_in.tex2D(x+u, y+v); + if (d < camera.minDepth || d > camera.maxDepth) continue; + + // Point and normal of neighbour + const float3 Xi = camera.screenToCam((int)(x)+u,(int)(y)+v,d); + const float3 Ni = make_float3(normals.tex2D((int)(x)+u, (int)(y)+v)); + + // Gauss approx weighting function using point distance + const float w = ftl::cuda::spatialWeighting(X,Xi,smoothing); + + aX += Xi*w; + nX += Ni*w; + contrib += w; + } + } + + nX /= contrib; // Weighted average normal + aX /= contrib; // Weighted average point (centroid) + + // Signed-Distance Field function + float fX = nX.x * (X.x - aX.x) + nX.y * (X.y - aX.y) + nX.z * (X.z - aX.z); + + // Calculate new point using SDF function to adjust depth (and position) + X = X - nX * fX; + + //uint2 screen = camera.camToScreen<uint2>(X); + + //if (screen.x < depth_out.width() && screen.y < depth_out.height()) { + // depth_out(screen.x,screen.y) = X.z; + //} + depth_out(x,y) = X.z; +} + +void ftl::cuda::mls_smooth( + ftl::cuda::TextureObject<float4> &normals, + ftl::cuda::TextureObject<float> &depth_in, + ftl::cuda::TextureObject<float> &depth_out, + float smoothing, + const ftl::rgbd::Camera &camera, + cudaStream_t stream) { + + const dim3 gridSize((depth_out.width() + T_PER_BLOCK - 1)/T_PER_BLOCK, (depth_out.height() + T_PER_BLOCK - 1)/T_PER_BLOCK); + const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK); + + mls_smooth_kernel<3><<<gridSize, blockSize, 0, stream>>>(normals, depth_in, depth_out, smoothing, camera); + cudaSafeCall( cudaGetLastError() ); + + + #ifdef _DEBUG + cudaSafeCall(cudaDeviceSynchronize()); + #endif +} + +// ===== Colour-based Smooth =================================================== + template <int RADIUS> __global__ void depth_smooth_kernel( ftl::cuda::TextureObject<float> depth_in, diff --git a/components/filters/src/smoothing_cuda.hpp b/components/filters/src/smoothing_cuda.hpp index da800f883f2e39a44253929fbc7675360e3a543d..ee28b4d489c717dfa60d43c942e264df9ed830d0 100644 --- a/components/filters/src/smoothing_cuda.hpp +++ b/components/filters/src/smoothing_cuda.hpp @@ -7,6 +7,14 @@ namespace ftl { namespace cuda { +void mls_smooth( + ftl::cuda::TextureObject<float4> &normals, + ftl::cuda::TextureObject<float> &depth_in, + ftl::cuda::TextureObject<float> &depth_out, + float smoothing, + const ftl::rgbd::Camera &camera, + cudaStream_t stream); + void depth_smooth( ftl::cuda::TextureObject<float> &depth_in, ftl::cuda::TextureObject<uchar4> &colour_in,