diff --git a/components/operators/include/ftl/operators/cuda/gt.hpp b/components/operators/include/ftl/operators/cuda/gt.hpp index 17ef345321b1f1c114bd2378adce665eb0789780..e98600e6d7f7d4bb00d47cf9ecaeadd1bbca89f8 100644 --- a/components/operators/include/ftl/operators/cuda/gt.hpp +++ b/components/operators/include/ftl/operators/cuda/gt.hpp @@ -8,11 +8,12 @@ namespace ftl { namespace cuda { struct GTAnalysisData { - int invalid; // number of invalid (missing depth and not masked) - int invalid_masked; // number of masked pixels with value - int masked; // number of pixels masked + int valid; // number of pixels with valid pixels + int missing; // number of missing non-masked pixels + int missing_masked; // number of missing masked pixels + int masked; // number of pixels masked (in gt) - int bad; // number of bad pixels (error outside min/max threshold) + int good; // number of good pixels (valid value and error within min/max threshold) float err; // sum of absolute error float err_sq; // sum of squared error }; @@ -21,6 +22,7 @@ void gt_analysis( ftl::cuda::TextureObject<uchar4> &colour, ftl::cuda::TextureObject<float> &depth, ftl::cuda::TextureObject<float> >, + ftl::cuda::TextureObject<uchar> &mask, ftl::cuda::GTAnalysisData *out, const ftl::rgbd::Camera &cam, float t_min, @@ -33,6 +35,7 @@ void gt_analysis( void gt_analysis( ftl::cuda::TextureObject<float> &depth, ftl::cuda::TextureObject<float> >, + ftl::cuda::TextureObject<uchar> &mask, ftl::cuda::GTAnalysisData *out, const ftl::rgbd::Camera &cam, float t_min, diff --git a/components/operators/src/gt_analysis.cpp b/components/operators/src/gt_analysis.cpp index 7010d1ead3b8c4f018984c2d9e8abc341f7b3890..066f04d94c1ec96c2a01d8094e99cf86a66136bf 100644 --- a/components/operators/src/gt_analysis.cpp +++ b/components/operators/src/gt_analysis.cpp @@ -15,10 +15,10 @@ GTAnalysis::~GTAnalysis() { template <typename T> std::string to_string_with_precision(const T a_value, const int n = 6) { - std::ostringstream out; - out.precision(n); - out << std::fixed << a_value; - return out.str(); + std::ostringstream out; + out.precision(n); + out << std::fixed << a_value; + return out.str(); } struct Options { @@ -28,28 +28,28 @@ struct Options { }; static const std::vector<Options> options_disparity = { - {-INFINITY, INFINITY, {0,0,224,255}}, // bad: over 2px error - {-INFINITY, 2.0, {66,174,255,255}}, // 1 to 2px error - {-INFINITY, 1.0, {16,192,16,255}}, // good: 0.1 to 1px error - {-INFINITY, 0.25, {64,255,64,255}}, // less than 0.25px error + {-INFINITY, INFINITY, {0,0,224,255}}, + {-INFINITY, 2.0, {66,174,255,255}}, + {-INFINITY, 1.0, {16,192,16,255}}, + {-INFINITY, 0.25, {64,255,64,255}}, }; static const std::vector<Options> options_depth = { - {-INFINITY, INFINITY, {0,0,224,255}}, // over 100mm - {-INFINITY, 0.1, {66,174,255,255}}, // 50 to 100mm - {-INFINITY, 0.05, {16,192,16,255}}, // 10 to 50mm - {-INFINITY, 0.01, {64,255,64,255}}, // less than 10 mm + {-INFINITY, INFINITY, {0,0,224,255}}, + {-INFINITY, 0.1, {66,174,255,255}}, + {-INFINITY, 0.025, {16,192,16,255}}, + {-INFINITY, 0.01, {64,255,64,255}}, }; static void report(std::vector<std::string> &msgs, const ftl::cuda::GTAnalysisData &data, const Options &o, float npixels, const std::string &unit="", float scale=1.0f) { msgs.push_back( "(" + to_string_with_precision(o.t_min, 2) - + "," + to_string_with_precision(o.t_max, 2) + "] " - + to_string_with_precision(100.0f*data.bad/npixels, 1) + "%"); - + + "," + to_string_with_precision(o.t_max, 2) + "] "); + msgs.push_back("valid: " + to_string_with_precision(100.0f*data.good/data.valid, 1) + "%, " + + "all: " + to_string_with_precision(100.0f*data.good/npixels, 1) + "%"); msgs.push_back( "RMS: " - + to_string_with_precision(sqrt(data.err_sq/data.bad) * scale, 2) + + to_string_with_precision(sqrt(data.err_sq/data.good) * scale, 2) + (unit.empty() ? "" : " " + unit)); } @@ -73,6 +73,7 @@ bool GTAnalysis::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t in.createTexture<uchar4>(Channel::Colour), in.createTexture<float>(Channel::Depth), in.createTexture<float>(Channel::GroundTruth), + in.createTexture<uchar>(Channel::Mask), output_, in.getLeft(), o.t_min, @@ -86,6 +87,7 @@ bool GTAnalysis::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t ftl::cuda::gt_analysis( in.createTexture<float>(Channel::Depth), in.createTexture<float>(Channel::GroundTruth), + in.createTexture<uchar>(Channel::Mask), output_, in.getLeft(), o.t_min, @@ -101,8 +103,6 @@ bool GTAnalysis::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t else { report(msgs, err, o, npixels, "mm", 1000.0); } } - //float pmasked = float(err.masked) / npixels; - in.create(Channel::Messages, msgs); return true; diff --git a/components/operators/src/gt_analysis.cu b/components/operators/src/gt_analysis.cu index 4cc83ad2b76b3a7488304c3b4a620ec28a7dc436..e3e524057868947c4220f7cd157ac2c939c4784b 100644 --- a/components/operators/src/gt_analysis.cu +++ b/components/operators/src/gt_analysis.cu @@ -16,25 +16,28 @@ __global__ void gt_analysis_kernel( int dpitch, const float* __restrict__ gt, int gpitch, + const uchar* __restrict__ mask, + int mpitch, ftl::cuda::GTAnalysisData *out, ftl::rgbd::Camera cam, float t_min, float t_max, uchar4 colour_value ) { - - __shared__ int sinvalid; - __shared__ int sinvalid_masked; + __shared__ int svalid; + __shared__ int smissing; + __shared__ int smissing_masked; __shared__ int smasked; - __shared__ int sbad; + __shared__ int sgood; __shared__ float serr; __shared__ float serr_sq; if (threadIdx.x == 0 && threadIdx.y == 0) { - sinvalid = 0; - sinvalid_masked = 0; + svalid = 0; + smissing = 0; + smissing_masked = 0; smasked = 0; - sbad = 0; + sgood = 0; serr = 0.0f; serr_sq = 0.0f; } @@ -42,10 +45,11 @@ __global__ void gt_analysis_kernel( const unsigned int x = blockIdx.x*blockDim.x + threadIdx.x; - int invalid = 0; - int invalid_masked = 0; + int valid = 0; + int missing = 0; + int missing_masked = 0; int masked = 0; - int bad = 0; + int good = 0; float err = 0.0f; float err_sq = 0.0f; @@ -54,16 +58,21 @@ __global__ void gt_analysis_kernel( if (x < width) { const float* __restrict__ gt_ptr = gt+x; const float* __restrict__ d_ptr = depth+x; + const uchar* __restrict__ m_ptr = mask+x; for (STRIDE_Y(y, height)) { // TODO: Verify gt and depth pitch are same float gtval = gt_ptr[y*dpitch]; float dval = d_ptr[y*dpitch]; - const int tmasked = (gtval > cam.minDepth && gtval < cam.maxDepth) ? 0 : 1; + const int tmasked = (m_ptr[y*mpitch] == 0) ? 0 : 1; const int tinvalid = (dval <= cam.minDepth || dval >= cam.maxDepth) ? 1 : 0; + const int tgtinvalid = (gtval > cam.minDepth && gtval < cam.maxDepth) ? 0 : 1; + + if (tinvalid == 0 && tgtinvalid == 0) { + // if there is valid value in both (gt and depth) + valid += 1; - if (tinvalid == 0 && tmasked == 0) { if (DISPARITY) { dval = (numer / dval); gtval = (numer / gtval); @@ -72,51 +81,51 @@ __global__ void gt_analysis_kernel( const float e = fabsf(dval-gtval); if ((t_min < e) && (e <= t_max)) { - bad += 1; + good += 1; err += e; err_sq += e*e; if (VISUALISE) { colour[x+y*cpitch] = colour_value; } } } - if (VISUALISE) { - if (tinvalid == 1 && tmasked == 1) { - // correctly missing - colour[x+y*cpitch] = {0, 0, 0, 255}; - } - else if (tinvalid == 0 && tmasked == 1) { - // masked and not missing - colour[x+y*cpitch] = {128, 0, 128, 255}; - invalid_masked += 1; - } - else if (tinvalid == 1 && tmasked == 0) { - // missing non-masked - colour[x+y*cpitch] = {192, 0, 0, 255}; - invalid += 1; - } + else if (tinvalid == 0 && tmasked == 1 && tgtinvalid == 1) { + // masked and not missing (but no gt value) + if (VISUALISE) { colour[x+y*cpitch] = {192, 0, 192, 255}; } // magenta + } + else if (tinvalid == 1 && (tmasked == 1 || tgtinvalid == 1)) { + // missing and (masked or missing gt) + if (VISUALISE) { colour[x+y*cpitch] = {0, 0, 0, 255}; } // black + missing_masked += 1; + } + else if (tinvalid == 1) { + // missing value (not masked) + if (VISUALISE) { colour[x+y*cpitch] = {224, 32, 32, 255}; } // blue + missing += 1; } - masked += tmasked; + masked += (tmasked == 1 || tgtinvalid == 1) ? 1 : 0; } } // Warp aggregate #pragma unroll for (int i = WARP_SIZE/2; i > 0; i /= 2) { - invalid += __shfl_xor_sync(FULL_MASK, invalid, i, WARP_SIZE); - invalid_masked += __shfl_xor_sync(FULL_MASK, invalid_masked, i, WARP_SIZE); + valid += __shfl_xor_sync(FULL_MASK, valid, i, WARP_SIZE); + missing += __shfl_xor_sync(FULL_MASK, missing, i, WARP_SIZE); + missing_masked += __shfl_xor_sync(FULL_MASK, missing_masked, i, WARP_SIZE); masked += __shfl_xor_sync(FULL_MASK, masked, i, WARP_SIZE); - bad += __shfl_xor_sync(FULL_MASK, bad, i, WARP_SIZE); + good += __shfl_xor_sync(FULL_MASK, good, i, WARP_SIZE); err += __shfl_xor_sync(FULL_MASK, err, i, WARP_SIZE); err_sq += __shfl_xor_sync(FULL_MASK, err_sq, i, WARP_SIZE); } // Block aggregate if (threadIdx.x % WARP_SIZE == 0) { - atomicAdd(&sinvalid, invalid); - atomicAdd(&sinvalid_masked, invalid_masked); + atomicAdd(&svalid, valid); + atomicAdd(&smissing, missing); + atomicAdd(&smissing_masked, missing_masked); atomicAdd(&smasked, masked); - atomicAdd(&sbad, bad); + atomicAdd(&sgood, good); atomicAdd(&serr, err); atomicAdd(&serr_sq, err_sq); } @@ -125,11 +134,11 @@ __global__ void gt_analysis_kernel( // Global aggregate if (threadIdx.x == 0 && threadIdx.y == 0) { - //atomicAdd(&out->totalerror, serr); - atomicAdd(&out->invalid, sinvalid); - atomicAdd(&out->invalid_masked, sinvalid_masked); + atomicAdd(&out->valid, svalid); + atomicAdd(&out->missing, smissing); + atomicAdd(&out->missing_masked, smissing_masked); atomicAdd(&out->masked, smasked); - atomicAdd(&out->bad, sbad); + atomicAdd(&out->good, sgood); atomicAdd(&out->err, serr); atomicAdd(&out->err_sq, serr_sq); } @@ -139,6 +148,7 @@ void ftl::cuda::gt_analysis( ftl::cuda::TextureObject<uchar4> &colour, ftl::cuda::TextureObject<float> &depth, ftl::cuda::TextureObject<float> >, + ftl::cuda::TextureObject<uchar> &mask, ftl::cuda::GTAnalysisData *out, const ftl::rgbd::Camera &cam, float t_min, @@ -165,6 +175,8 @@ void ftl::cuda::gt_analysis( depth.pixelPitch(), gt.devicePtr(), gt.pixelPitch(), + mask.devicePtr(), + mask.pixelPitch(), out, cam, t_min, @@ -182,6 +194,8 @@ void ftl::cuda::gt_analysis( depth.pixelPitch(), gt.devicePtr(), gt.pixelPitch(), + mask.devicePtr(), + mask.pixelPitch(), out, cam, t_min, @@ -199,6 +213,7 @@ void ftl::cuda::gt_analysis( void ftl::cuda::gt_analysis( ftl::cuda::TextureObject<float> &depth, ftl::cuda::TextureObject<float> >, + ftl::cuda::TextureObject<uchar> &mask, ftl::cuda::GTAnalysisData *out, const ftl::rgbd::Camera &cam, float t_min, @@ -224,6 +239,8 @@ void ftl::cuda::gt_analysis( depth.pixelPitch(), gt.devicePtr(), gt.pixelPitch(), + mask.devicePtr(), + mask.pixelPitch(), out, cam, t_min, @@ -241,6 +258,8 @@ void ftl::cuda::gt_analysis( depth.pixelPitch(), gt.devicePtr(), gt.pixelPitch(), + mask.devicePtr(), + mask.pixelPitch(), out, cam, t_min,