diff --git a/applications/reconstruct/src/ilw/ilw.cu b/applications/reconstruct/src/ilw/ilw.cu index c1222ca7956ad5f1fa1f80fa06a114ba16cb3281..48462f300981ad29c11c5047c0ef6f6a37a33c82 100644 --- a/applications/reconstruct/src/ilw/ilw.cu +++ b/applications/reconstruct/src/ilw/ilw.cu @@ -8,10 +8,10 @@ using ftl::rgbd::Camera; #define T_PER_BLOCK 8 #define FULL_MASK 0xffffffff -__device__ inline float warpMax(float e) { +__device__ inline float warpMin(float e) { for (int i = WARP_SIZE/2; i > 0; i /= 2) { const float other = __shfl_xor_sync(FULL_MASK, e, i, WARP_SIZE); - e = max(e, other); + e = min(e, other); } return e; } @@ -39,8 +39,8 @@ __global__ void correspondence_energy_vector_kernel( const float3 camPos2 = pose2 * world1; const uint2 screen2 = cam2.camToScreen<uint2>(camPos2); - float bestconf = 0.0f; - float nextbest = 0.0f; + float bestcost = 1.1f; + float nextbest = 1.0f; float3 bestpoint; // Project to p2 using cam2 @@ -54,29 +54,28 @@ __global__ void correspondence_energy_vector_kernel( if (world2.x == MINF) continue; // Determine degree of correspondence - const float l = length(world1 - world2); - const float confidence = ftl::cuda::spatialWeighting(l, 0.04f); + const float cost = 1.0f - ftl::cuda::spatialWeighting(world1, world2, 0.04f); - if (confidence > bestconf) { + if (cost < bestcost) { bestpoint = world2; - nextbest = bestconf; - bestconf = confidence; + nextbest = bestcost; + bestcost = cost; } } - const float maxconf = warpMax(bestconf); - bool best = maxconf == bestconf; - bestconf = (best) ? 0.0f : bestconf; - const float conf = maxconf - warpMax(bestconf); + const float mincost = warpMin(bestcost); + bool best = mincost == bestcost; + bestcost = (best) ? nextbest : bestcost; + const float confidence = mincost / warpMin(bestcost); - if (best && maxconf > 0.0f) { + if (best && mincost < 1.0f) { vout(x,y) = vout.tex2D(x, y) + make_float4( (bestpoint.x - world1.x), (bestpoint.y - world1.y), (bestpoint.z - world1.z), - maxconf); - eout(x,y) = conf * 5.0f; //maxconf * 5.0f; //(maxconf - warpMax(nextbest)); - } else if (maxconf == 0.0f && lane == 0) { + mincost); + eout(x,y) = mincost * 5.0f; //confidence * 5.0f; + } else if (mincost >= 1.0f && lane == 0) { vout(x,y) = make_float4(0.0f); eout(x,y) = 0.0f; } diff --git a/components/renderers/cpp/include/ftl/cuda/weighting.hpp b/components/renderers/cpp/include/ftl/cuda/weighting.hpp index 9498d0508605087306db2658b2a1ae1943cde536..15d3dbcec387f97d8ffe60690bdb5c1fda2c098c 100644 --- a/components/renderers/cpp/include/ftl/cuda/weighting.hpp +++ b/components/renderers/cpp/include/ftl/cuda/weighting.hpp @@ -4,19 +4,41 @@ namespace ftl { namespace cuda { +__device__ inline float weighting(float r, float h) { + if (r >= h) return 0.0f; + float rh = r / h; + rh = 1.0f - rh*rh; + return rh*rh*rh*rh; +} + /* * Guennebaud, G.; Gross, M. Algebraic point set surfaces. ACMTransactions on Graphics Vol. 26, No. 3, Article No. 23, 2007. * Used in: FusionMLS: Highly dynamic 3D reconstruction with consumer-grade RGB-D cameras * r = distance between points * h = smoothing parameter in meters (default 4cm) */ -__device__ inline float spatialWeighting(float r, float h) { +__device__ inline float spatialWeighting(const float3 &a, const float3 &b, float h) { + const float r = length(a-b); if (r >= h) return 0.0f; float rh = r / h; rh = 1.0f - rh*rh; return rh*rh*rh*rh; } +/* + * Colour weighting as suggested in: + * C. Kuster et al. Spatio-Temporal Geometry Fusion for Multiple Hybrid Cameras using Moving Least Squares Surfaces. 2014. + * c = colour distance + */ + __device__ inline float colourWeighting(uchar4 a, uchar4 b, float h) { + const float3 delta = make_float3((float)a.x - (float)b.x, (float)a.y - (float)b.y, (float)a.z - (float)b.z); + const float c = length(delta); + if (c >= h) return 0.0f; + float ch = c / h; + ch = 1.0f - ch*ch; + return ch*ch*ch*ch; +} + } } diff --git a/components/renderers/cpp/src/splatter.cu b/components/renderers/cpp/src/splatter.cu index 3b1ae4b47ef0fe6b29b15d1fa20fdc9a0fd0b9bb..6b615fa6b9c092cc9bc7856b8e8d36ceb1ddec0d 100644 --- a/components/renderers/cpp/src/splatter.cu +++ b/components/renderers/cpp/src/splatter.cu @@ -116,7 +116,7 @@ __global__ void dibr_attribute_contrib_kernel( const float3 nearest = params.camera.screenToCam((int)(screenPos.x+u),(int)(screenPos.y+v),d); // What is contribution of our current point at this pixel? - const float weight = ftl::cuda::spatialWeighting(length(nearest - camPos), SMOOTHING_MULTIPLIER_C*(nearest.z/params.camera.fx)); + const float weight = ftl::cuda::spatialWeighting(nearest, camPos, SMOOTHING_MULTIPLIER_C*(nearest.z/params.camera.fx)); if (screenPos.x+u < colour_out.width() && screenPos.y+v < colour_out.height() && weight > 0.0f) { // TODO: Use confidence threshold here const float4 wcolour = colour * weight; //const float4 wnormal = normal * weight; @@ -187,7 +187,7 @@ __global__ void dibr_attribute_contrib_kernel( const float3 nearest = params.camera.screenToCam((int)(screenPos.x+u),(int)(screenPos.y+v),d); // What is contribution of our current point at this pixel? - const float weight = ftl::cuda::spatialWeighting(length(nearest - camPos), SMOOTHING_MULTIPLIER_C*(nearest.z/params.camera.fx)); + const float weight = ftl::cuda::spatialWeighting(nearest, camPos, SMOOTHING_MULTIPLIER_C*(nearest.z/params.camera.fx)); if (screenPos.x+u < colour_out.width() && screenPos.y+v < colour_out.height() && weight > 0.0f) { // TODO: Use confidence threshold here const float wcolour = colour * weight; //const float4 wnormal = normal * weight;