diff --git a/components/operators/src/fusion/smoothing/mls_multi_weighted.cu b/components/operators/src/fusion/smoothing/mls_multi_weighted.cu index 4d62d3bdaf2d8a07f6548aa74e194022e5e65561..a73edc0879df1c59e248c55131898ad7f8fe61ec 100644 --- a/components/operators/src/fusion/smoothing/mls_multi_weighted.cu +++ b/components/operators/src/fusion/smoothing/mls_multi_weighted.cu @@ -12,6 +12,17 @@ __device__ inline float featureWeight(int f1, int f2) { return w*w*w; } +__device__ inline float biasedLength(const float3 &Xi, const float3 &X) { + float l = 0.0f; + const float dx = Xi.x-X.x; + l += 2.0f*dx*dx; + const float dy = Xi.y-X.y; + l += 2.0f*dy*dy; + const float dz = Xi.z-X.z; + l += dz*dz; + return sqrt(l); +} + /* * Gather points for Moving Least Squares, from each source image */ @@ -55,11 +66,17 @@ __device__ inline float featureWeight(int f1, int f2) { const uchar2 feature1 = feature_origin[x+y*fpitch_o]; + // TODO: Could the origin depth actually be averaged with depth in other + // image? So as to not bias towards the original view? + float3 X = camera_origin.screenToCam((int)(x),(int)(y),d0); const float3 camPos = o_2_in * X; const int2 s = camera_in.camToScreen<int2>(camPos); + // Move point off of original surface + //X = camera_origin.screenToCam((int)(x),(int)(y),d0-0.005f); + // TODO: Could dynamically adjust the smoothing factors depending upon the // number of matches. Meaning, if lots of good local and feature matches // then be less likely to include poorer matches. Conversely, if only poor @@ -85,11 +102,21 @@ __device__ inline float featureWeight(int f1, int f2) { spatial_smoothing = min(spatial_smoothing, smoothing * fabsf(camPos.z - d)); } hf_intensity_smoothing = smoothing * fabsf(float(feature2.x) - float(feature1.x)); - mean_smoothing = smoothing * fabsf(float(feature2.y) - float(feature1.y)); + //mean_smoothing = smoothing * fabsf(float(feature2.y) - float(feature1.y)); + + // Make start point the average of the two sources... + const float3 reversePos = in_2_o * camera_in.screenToCam(s.x, s.y, d); + X = X + (reversePos) / 2.0f; } - if (spatial_smoothing < 0.001f || hf_intensity_smoothing <= 1.0f || mean_smoothing <= 1.0f) return; + // Make sure there is a minimum smoothing value + spatial_smoothing = max(0.01f, spatial_smoothing); + hf_intensity_smoothing = max(5.0f, hf_intensity_smoothing); + //mean_smoothing = max(10.0f, mean_smoothing); + // Check for neighbourhood symmetry and use to weight overall contribution + float symx = 0.0f; + float symy = 0.0f; // Neighbourhood for (int v=-SEARCH_RADIUS; v<=SEARCH_RADIUS; ++v) { @@ -109,22 +136,39 @@ __device__ inline float featureWeight(int f1, int f2) { // So take the minimum, must be close and feature close to get good value const float w_high_int = ftl::cuda::weighting(float(abs(int(feature1.x)-int(feature2.x))), hf_intensity_smoothing); const float w_mean_int = ftl::cuda::weighting(float(abs(int(feature1.y)-int(feature2.y))), mean_smoothing); - const float w_space = ftl::cuda::spatialWeighting(X,Xi,spatial_smoothing); + const float w_space = ftl::cuda::spatialWeighting(X,Xi,spatial_smoothing); + //const float w_space = ftl::cuda::weighting(biasedLength(Xi,X),spatial_smoothing); // TODO: Distance from cam squared // TODO: Angle from cam (dot of normal and ray) + //const float w_lateral = ftl::cuda::weighting(sqrt(Xi.x*X.x + Xi.y*X.y), float(SEARCH_RADIUS)*camera_origin.fx/Xi.z); const float w = (length(Ni) > 0.0f) - ? min(w_space, min(w_high_int, w_mean_int)) + ?w_space * w_high_int * w_mean_int // min(w_space, min(w_high_int, w_mean_int)) : 0.0f; + // Mark as a symmetry contribution + if (w > 0.0f) { + if (u < 0) symx -= 1.0f; + else if (u > 0) symx += 1.0f; + if (v < 0) symy -= 1.0f; + else if (v > 0) symy += 1.0f; + } + aX += Xi*w; nX += (in_2_o33 * Ni)*w; contrib += w; } } - normals_out[y*npitch_out+x] = make_half4(nX, 0.0f); - centroid_out[y*cpitch_out+x] = make_float4(aX, 0.0f); - contrib_out[y*wpitch_out+x] = contrib; + // Perfect symmetry means symx and symy == 0, therefore actual length can + // be measure of asymmetry, so when inverted it can be used to weight result + symx = fabsf(symx) / float(SEARCH_RADIUS); + symy = fabsf(symy) / float(SEARCH_RADIUS); + float l = 1.0f - sqrt(symx*symx+symy*symy); + l = l*l; + + normals_out[y*npitch_out+x] = make_half4(nX*l, 0.0f); + centroid_out[y*cpitch_out+x] = make_float4(aX*l, 0.0f); + contrib_out[y*wpitch_out+x] = contrib*l; } /** @@ -152,7 +196,7 @@ __device__ inline float featureWeight(int f1, int f2) { float contrib = contrib_out[y*wpitch+x]; //depth[x+y*dpitch] = X.z; - normals_out[x+y*npitch] = make_half4(0.0f, 0.0f, 0.0f, 0.0f); + //normals_out[x+y*npitch] = make_half4(0.0f, 0.0f, 0.0f, 0.0f); float d0 = depth[x+y*dpitch]; //depth[x+y*dpitch] = 0.0f;