diff --git a/CHANGELOG.md b/CHANGELOG.md index dc3c5e8ff..9e7fb8a17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Render item lists faster ([#1036](../../pull/1036)) - Reduce bioformats source memory usage ([#1038](../../pull/1038)) - Better pick the largest image from bioformats ([#1039](../../pull/1039), [#1040](../../pull/1040)) +- Cache histogram thresholds ([#1042](../../pull/1042)) ## 1.19.3 diff --git a/large_image/tilesource/utilities.py b/large_image/tilesource/utilities.py index 279a74311..c4342441c 100644 --- a/large_image/tilesource/utilities.py +++ b/large_image/tilesource/utilities.py @@ -908,6 +908,9 @@ def getTileFramesQuadInfo(metadata, options=None): return status +_recentThresholds = {} + + def histogramThreshold(histogram, threshold, fromMax=False): """ Given a histogram and a threshold on a scale of [0, 1], return the bin @@ -922,6 +925,9 @@ def histogramThreshold(histogram, threshold, fromMax=False): :returns: the value the excludes no more than the threshold from the specified end. """ + key = (id(histogram), threshold, fromMax) + if key in _recentThresholds: + return _recentThresholds[key] hist = histogram['hist'] edges = histogram['bin_edges'] samples = histogram['samples'] if not histogram.get('density') else 1 @@ -929,13 +935,19 @@ def histogramThreshold(histogram, threshold, fromMax=False): hist = hist[::-1] edges = edges[::-1] tally = 0 + result = edges[-1] for idx in range(len(hist)): - if tally >= threshold * samples: + if tally + hist[idx] > threshold * samples: if not idx: - return histogram['min' if not fromMax else 'max'] - return edges[idx] + result = histogram['min' if not fromMax else 'max'] + else: + result = edges[idx] + break tally += hist[idx] - return edges[-1] + if len(_recentThresholds) > 100: + _recentThresholds.empty() + _recentThresholds[key] = result + return result def addPILFormatsToOutputOptions(): diff --git a/test/test_source_tiff.py b/test/test_source_tiff.py index da0f0b239..d469e195a 100644 --- a/test/test_source_tiff.py +++ b/test/test_source_tiff.py @@ -668,7 +668,7 @@ def testStyleMinMaxThreshold(): output={'maxWidth': 256, 'maxHeight': 256}, format=constants.TILE_FORMAT_NUMPY) assert numpy.any(image != imageB) assert image[0][0][0] == 252 - assert imageB[0][0][0] == 254 + assert imageB[0][0][0] == 246 sourceC = large_image_source_tiff.open( imagePath, style=json.dumps({'min': 'full', 'max': 'full'})) imageC, _ = sourceC.getRegion(