diff --git a/src/nyx/features/focus_score.cpp b/src/nyx/features/focus_score.cpp index b5c0df18..43a62212 100644 --- a/src/nyx/features/focus_score.cpp +++ b/src/nyx/features/focus_score.cpp @@ -3,6 +3,10 @@ using namespace Nyxus; +int FocusScoreFeature::kernel[9] = { 0, 1, 0, + 1, -4, 1, + 0, 1, 0 }; + FocusScoreFeature::FocusScoreFeature() : FeatureMethod("FocusScoreFeature") { provide_features(FocusScoreFeature::featureset); } @@ -70,6 +74,19 @@ void FocusScoreFeature::reduce (size_t start, size_t end, std::vector* ptrL } } +void FocusScoreFeature::osized_calculate(LR& r, ImageLoader& imloader) { + + // Skip calculation in case of noninformative data + if (r.aux_max == r.aux_min) return; + + WriteImageMatrix_nontriv Im0 ("FocusScoreFeature-osized_calculate-Im0", r.label); + Im0.allocate_from_cloud (r.raw_pixels_NT, r.aabb, false); + + focus_score_ = get_focus_score_NT(Im0, 1); + + save_value(r.fvals); +} + void FocusScoreFeature::save_value(std::vector>& feature_vals) { feature_vals[(int)FeatureIMQ::FOCUS_SCORE][0] = focus_score_; @@ -77,6 +94,102 @@ void FocusScoreFeature::save_value(std::vector>& feature_val } +double FocusScoreFeature::get_focus_score_NT(WriteImageMatrix_nontriv& Im, int ksize) { + + int n = 3; // size of kernel nxn + + if (ksize != 1) { + + kernel[0] = 2; + kernel[1] = 0; + kernel[2] = 2; + + kernel[3] = 0; + kernel[4] = -8; + kernel[5] = 0; + + kernel[6] = 2; + kernel[7] = 0; + kernel[8] = 2; + } + + auto width = Im.get_width(), + height = Im.get_height(); + auto xy0 = (int)ceil(double(n) / 2.); + + // Window (N-fold kernel size) + int winX = n * 10, + winY = n * 10; + std::vector W (winY * winX); + + // Convolution result buffer + std::vector conv_buffer ((winY + n - 1) * (winX + n - 1) * 2); + + // Iterate the image window by window + int n_winHor = width / winX, //ceil (float(width) / float(win)), + n_winVert = height / winY; //ceil (float(height) / float(win)); + + + // ROI smaller than kernel? + if (n_winVert == 0 || n_winHor == 0) + { + // Fill the window with data + for (int row=0; row < height; row++) { + for (int col = 0; col < width; col++) + { + size_t idx = row * width + col; + W[idx] = Im.get_at(idx); + } + } + + // Convolve + laplacian (W, conv_buffer, width, height, ksize); + + return variance(conv_buffer); + } + + // Variables for Welford Algorithm for calculating variance + double mean = 0.; + double M2 = 0.; // sum of squared distance + int count = 0; + + std::vector> tile_variance; // vector of tuples containing 0: abs sum of tile, 1: variance of tile, 2: buffer size + + // ROI larger than kernel + // Calculate laplacian of window and then use Welford algorithm to calculate variance of image + for (int winVert = 0; winVert < n_winVert; winVert++) + { + for (int winHor = 0; winHor < n_winHor; winHor++) + { + + // Fill the window with data + for (int row=0; row& image, int height, int width, int ksize, int scale) { double local_focus_score = 0; @@ -113,18 +226,15 @@ void FocusScoreFeature::laplacian(const std::vector& image, std::vect int m_kernel = 3; int n_kernel = 3; - // use c-style array for compile time initialization - int kernel[9] = { 0, 1, 0, - 1, -4, 1, - 0, 1, 0 }; - if (ksize != 1) { kernel[0] = 2; kernel[1] = 0; kernel[2] = 2; + kernel[3] = 0; kernel[4] = -8; kernel[5] = 0; + kernel[6] = 2; kernel[7] = 0; kernel[8] = 2; diff --git a/src/nyx/features/focus_score.h b/src/nyx/features/focus_score.h index 7119f7c4..69d6c3ee 100644 --- a/src/nyx/features/focus_score.h +++ b/src/nyx/features/focus_score.h @@ -26,7 +26,8 @@ class FocusScoreFeature: public FeatureMethod //=== Non-trivial ROIs === void osized_add_online_pixel(size_t x, size_t y, uint32_t intensity) {} - void osized_calculate(LR& r, ImageLoader& imloader){}; + void osized_calculate(LR& r, ImageLoader& imloader); + double get_focus_score_NT(WriteImageMatrix_nontriv& Im, int ksize); // Result saver void save_value(std::vector>& feature_vals); @@ -50,5 +51,6 @@ class FocusScoreFeature: public FeatureMethod static double variance(const std::vector& image); + static int kernel[9]; }; diff --git a/src/nyx/python/nyxus/nyxus.py b/src/nyx/python/nyxus/nyxus.py index 24bd5c2f..1ce1efea 100644 --- a/src/nyx/python/nyxus/nyxus.py +++ b/src/nyx/python/nyxus/nyxus.py @@ -1296,7 +1296,7 @@ def __init__( 'neighbor_distance', 'pixels_per_micron', 'coarse_gray_depth', 'n_feature_calc_threads', 'n_loader_threads', 'ibsi', 'gabor_kersize', 'gabor_gamma', 'gabor_sig2lam', 'gabor_f0', - 'channel_signature', 'min_intensity', 'max_intensity' + 'channel_signature', 'min_intensity', 'max_intensity', 'ram_limit', } # Check for unexpected keyword arguments @@ -1316,6 +1316,7 @@ def __init__( dynamic_range = kwargs.get('dynamic_range', 10000) min_intensity = kwargs.get('min_intensity', 0.0) max_intensity = kwargs.get('max_intensity', 1.0) + ram_limit = kwargs.get('ram_limit', -1) if neighbor_distance <= 0: raise ValueError("Neighbor distance must be greater than zero.") @@ -1339,8 +1340,6 @@ def __init__( if(using_gpu > -1 and not gpu_available()): print("No gpu available.") using_gpu = -1 - - ram_limit = -1 initialize_environment( 2, # 2D