mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-04 19:49:32 +08:00
106 lines
2.8 KiB
Python
106 lines
2.8 KiB
Python
import numpy as np
|
|
|
|
|
|
__all__ = ['otsu_threshold', 'binarize']
|
|
|
|
|
|
def otsu_threshold(image, bins=256):
|
|
"""Return threshold value based on Otsu's method.
|
|
|
|
Parameters
|
|
----------
|
|
image : array
|
|
Input image.
|
|
bins : int
|
|
Number of bins used to calculate histogram. This value is ignored for
|
|
integer arrays.
|
|
|
|
Returns
|
|
-------
|
|
threshold : numeric
|
|
Threshold value. int or float depending on input image.
|
|
|
|
References
|
|
----------
|
|
.. [1] Wikipedia, http://en.wikipedia.org/wiki/Otsu's_Method
|
|
|
|
"""
|
|
hist, bin_centers = histogram(image, bins)
|
|
hist = hist.astype(float)
|
|
|
|
# class probabilities for all possible thresholds
|
|
weight1 = np.cumsum(hist)
|
|
weight2 = np.cumsum(hist[::-1])[::-1]
|
|
# class means for all possible thresholds
|
|
mean1 = np.cumsum(hist * bin_centers) / weight1
|
|
mean2 = (np.cumsum((hist * bin_centers)[::-1]) / weight2[::-1])[::-1]
|
|
|
|
# Clip ends to align class 1 and class 2 variables:
|
|
# The last value of `weight1`/`mean1` should pair with zero values in
|
|
# `weight2`/`mean2`, which do not exist.
|
|
variance12 = weight1[:-1] * weight2[1:] * (mean1[:-1] - mean2[1:])**2
|
|
|
|
idx = np.argmax(variance12)
|
|
threshold = bin_centers[:-1][idx]
|
|
return threshold
|
|
|
|
|
|
_threshold_funcs = {'otsu': otsu_threshold}
|
|
def binarize(image, method='otsu'):
|
|
"""Return binary image using an automatic thresholding method.
|
|
|
|
Parameters
|
|
----------
|
|
image : array
|
|
Input array.
|
|
method : {'otsu'}
|
|
Method used to calculate threshold value. Currently, only Otsu's method
|
|
is implemented.
|
|
|
|
Returns
|
|
-------
|
|
out : array
|
|
Thresholded image.
|
|
"""
|
|
get_threshold = _threshold_funcs[method]
|
|
threshold = get_threshold(image)
|
|
return image > threshold
|
|
|
|
|
|
def histogram(image, bins):
|
|
"""Return histogram of image.
|
|
|
|
Unlike `numpy.histogram`, this function returns the centers of bins and
|
|
does not rebin integer arrays.
|
|
|
|
Parameters
|
|
----------
|
|
image : array
|
|
Input image.
|
|
bins : int
|
|
Number of bins used to calculate histogram. This value is ignored for
|
|
integer arrays.
|
|
|
|
Returns
|
|
-------
|
|
hist : array
|
|
The values of the histogram.
|
|
bin_centers : array
|
|
The values at the center of the bins.
|
|
"""
|
|
if np.issubdtype(image.dtype, np.integer):
|
|
if np.min(image) < 0:
|
|
msg = "Images with negative values not allowed"
|
|
raise NotImplementedError(msg)
|
|
hist = np.bincount(image.flat)
|
|
bin_centers = np.arange(len(hist))
|
|
|
|
# clip histogram to return only non-zero bins
|
|
idx = np.nonzero(hist)[0][0]
|
|
return hist[idx:], bin_centers[idx:]
|
|
else:
|
|
hist, bin_edges = np.histogram(image, bins=bins)
|
|
bin_centers = (bin_edges[:-1] + bin_edges[1:]) / 2.
|
|
return hist, bin_centers
|
|
|