From c9d4fa68750a51aa8689c20200adda21e3c73d99 Mon Sep 17 00:00:00 2001 From: Rachel Finck Date: Sun, 26 Jun 2016 23:39:27 -0700 Subject: [PATCH] Fix threshold_triangle to work with non-integer images. --- skimage/filters/tests/test_thresholding.py | 17 ++++++++++++++++- skimage/filters/thresholding.py | 21 +++++++++++---------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/skimage/filters/tests/test_thresholding.py b/skimage/filters/tests/test_thresholding.py index dd08e36b..d6433f62 100644 --- a/skimage/filters/tests/test_thresholding.py +++ b/skimage/filters/tests/test_thresholding.py @@ -320,13 +320,28 @@ def test_mean(): assert(threshold_mean(img) == 1.) -def test_triangle_images(): +def test_triangle_uint_images(): assert(threshold_triangle(np.invert(data.text())) == 151) assert(threshold_triangle(data.text()) == 104) assert(threshold_triangle(data.coins()) == 80) assert(threshold_triangle(np.invert(data.coins())) == 175) +def test_triangle_float_images(): + text = data.text() + int_bins = text.max() - text.min() + 1 + # Set nbins to match the uint case and threshold as float. + assert(round(threshold_triangle( + text.astype(np.float), nbins=int_bins)) == 104) + # Check that rescaling image to floats in unit interval is equivalent. + assert(round(threshold_triangle(text / 255., nbins=int_bins) * 255) == 104) + # Repeat for inverted image. + assert(round(threshold_triangle( + np.invert(text).astype(np.float), nbins=int_bins)) == 151) + assert (round(threshold_triangle( + np.invert(text) / 255., nbins=int_bins) * 255) == 151) + + def test_triangle_flip(): # Depending on the skewness, the algorithm flips the histogram. # We check that the flip doesn't affect too much the result. diff --git a/skimage/filters/thresholding.py b/skimage/filters/thresholding.py index 06493880..2cf01357 100644 --- a/skimage/filters/thresholding.py +++ b/skimage/filters/thresholding.py @@ -687,6 +687,8 @@ def threshold_triangle(image, nbins=256): .. [1] Zack, G. W., Rogers, W. E. and Latt, S. A., 1977, Automatic Measurement of Sister Chromatid Exchange Frequency, Journal of Histochemistry and Cytochemistry 25 (7), pp. 741-753 + .. [2] ImageJ AutoThresholder code, + http://fiji.sc/wiki/index.php/Auto_Threshold Examples -------- @@ -695,10 +697,10 @@ def threshold_triangle(image, nbins=256): >>> thresh = threshold_triangle(image) >>> binary = image > thresh """ - # nbins is ignored for interger arrays + # nbins is ignored for integer arrays # so, we recalculate the effective nbins. hist, bin_centers = histogram(image.ravel(), nbins) - nbins = bin_centers[-1] - bin_centers[0] + 1 + nbins = len(hist) # Find peak, lowest and highest gray levels. arg_peak_height = np.argmax(hist) @@ -727,14 +729,13 @@ def threshold_triangle(image, nbins=256): width /= norm # Maximize the length. - d = peak_height * arg_low_level - width * hist[arg_low_level] - length = peak_height * x1 - width * y1 - d - level = np.argmax(length) + arg_low_level + # The ImageJ implementation includes an additional constant when calculating + # the length, but here we omit it as it does not affect the location of the + # minimum. + length = peak_height * x1 - width * y1 + arg_level = np.argmax(length) + arg_low_level if flip: - level = nbins - level - 1 + arg_level = nbins - arg_level - 1 - # The histogram doesn't start at zero, shift it. - level += bin_centers[0] - - return level + return bin_centers[arg_level]