【Python】scikit-image中的threshold_multiotsu函数

这篇主要是想调用threshold_multiotsu,但是该函数只有在scikit-image0.16.0版本以上才有,但是0.16.0版本以上仅支持python3.6及以上版本。但是我现在所有的环境都是python3.5,为了能使用该函数,从scikit-image中将这部分内容抠取出来。

 新建文件test.py

import matplotlib
import matplotlib.pyplot as plt
import numpy as np

from skimage import data
from multi_level.multi_thresh import threshold_multiotsu

# Setting the font size for all plots.
matplotlib.rcParams['font.size'] = 9

# The input image.
image = data.camera()

# Applying multi-Otsu threshold for the default value, generating
# three classes.
thresholds = threshold_multiotsu(image)

# Using the threshold values, we generate the three regions.
regions = np.digitize(image, bins=thresholds)

fig, ax = plt.subplots(nrows=1, ncols=3, figsize=(10, 3.5))

# Plotting the original image.
ax[0].imshow(image, cmap='gray')
ax[0].set_title('Original')
ax[0].axis('off')

# Plotting the histogram and the two thresholds obtained from
# multi-Otsu.
ax[1].hist(image.ravel(), bins=255)
ax[1].set_title('Histogram')
for thresh in thresholds:
    ax[1].axvline(thresh, color='r')

# Plotting the Multi Otsu result.
ax[2].imshow(regions, cmap='Accent')
ax[2].set_title('Multi-Otsu result')
ax[2].axis('off')

plt.subplots_adjust()

plt.show()

新建文件multi_thresh.py

import numpy as np
import pyximport
pyximport.install()
from multi_level._multiotsu import (_get_multiotsu_thresh_indices_lut, _get_multiotsu_thresh_indices)

_integer_types = (np.byte, np.ubyte,          # 8 bits
                  np.short, np.ushort,        # 16 bits
                  np.intc, np.uintc,          # 16 or 32 or 64 bits
                  np.int_, np.uint,           # 32 or 64 bits
                  np.longlong, np.ulonglong)  # 64 bits
_integer_ranges = {t: (np.iinfo(t).min, np.iinfo(t).max)
                   for t in _integer_types}
dtype_range = {np.bool_: (False, True),
               np.bool8: (False, True),
               np.float16: (-1, 1),
               np.float32: (-1, 1),
               np.float64: (-1, 1)}
dtype_range.update(_integer_ranges)

_supported_types = list(dtype_range.keys())

def dtype_limits(image, clip_negative=False):
    """Return intensity limits, i.e. (min, max) tuple, of the image's dtype.
    Parameters
    ----------
    image : ndarray
        Input image.
    clip_negative : bool, optional
        If True, clip the negative range (i.e. return 0 for min intensity)
        even if the image dtype allows negative values.
    Returns
    -------
    imin, imax : tuple
        Lower and upper intensity limits.
    """
    imin, imax = dtype_range[image.dtype.type]
    if clip_negative:
        imin = 0
    return imin, imax


def _offset_array(arr, low_boundary, high_boundary):
    """Offset the array to get the lowest value at 0 if negative."""
    if low_boundary < 0:
        offset = low_boundary
        dyn_range = high_boundary - low_boundary
        # get smallest dtype that can hold both minimum and offset maximum
        offset_dtype = np.promote_types(np.min_scalar_type(dyn_range),
                                        np.min_scalar_type(low_boundary))
        if arr.dtype != offset_dtype:
            # prevent overflow errors when offsetting
            arr = arr.astype(offset_dtype)
        arr = arr - offset
    else:
        offset = 0
    return arr, offset


def _bincount_histogram(image, source_range):
    """
    Efficient histogram calculation for an image of integers.
    This function is significantly more efficient than np.histogram but
    works only on images of integers. It is based on np.bincount.
    Parameters
    ----------
    image : array
        Input image.
    source_range : string
        'image' determines the range from the input image.
        'dtype' determines the range from the expected range of the images
        of that data type.
    Returns
    -------
    hist : array
        The values of the histogram.
    bin_centers : array
        The values at the center of the bins.
    """
    if source_range not in ['image', 'dtype']:
        raise ValueError('Incorrect value for `source_range` argument: {}'.format(source_range))
    if source_range == 'image':
        image_min = int(image.min().astype(np.int64))
        image_max = int(image.max().astype(np.int64))
    elif source_range == 'dtype':
        image_min, image_max = dtype_limits(image, clip_negative=False)
    image, offset = _offset_array(image, image_min, image_max)
    hist = np.bincount(image.ravel(), minlength=image_max - image_min + 1)
    bin_centers = np.arange(image_min, image_max + 1)
    if source_range == 'image':
        idx = max(image_min, 0)
        hist = hist[idx:]
    return hist, bin_centers


def histogram(image, nbins=256, source_range='image', normalize=False):
    """Return histogram of image.
    Unlike `numpy.histogram`, this function returns the centers of bins and
    does not rebin integer arrays. For integer arrays, each integer value has
    its own bin, which improves speed and intensity-resolution.
    The histogram is computed on the flattened image: for color images, the
    function should be used separately on each channel to obtain a histogram
    for each color channel.
    Parameters
    ----------
    image : array
        Input image.
    nbins : int, optional
        Number of bins used to calculate histogram. This value is ignored for
        integer arrays.
    source_range : string, optional
        'image' (default) determines the range from the input image.
        'dtype' determines the range from the expected range of the images
        of that data type.
    normalize : bool, optional
        If True, normalize the histogram by the sum of its values.
    Returns
    -------
    hist : array
        The values of the histogram.
    bin_centers : array
        The values at the center of the bins.
    See Also
    --------
    cumulative_distribution
    Examples
    --------
    >>> from skimage import data, exposure, img_as_float
    >>> image = img_as_float(data.camera())
    >>> np.histogram(image, bins=2)
    (array([107432, 154712]), array([ 0. ,  0.5,  1. ]))
    >>> exposure.histogram(image, nbins=2)
    (array([107432, 154712]), array([ 0.25,  0.75]))
    """
    sh = image.shape
    if len(sh) == 3 and sh[-1] < 4:
        raise("This might be a color image. The histogram will be "
             "computed on the flattened image. You can instead "
             "apply this function to each color channel.")

    image = image.flatten()
    # For integer types, histogramming with bincount is more efficient.
    if np.issubdtype(image.dtype, np.integer):
        hist, bin_centers = _bincount_histogram(image, source_range)
    else:
        if source_range == 'image':
            hist_range = None
        elif source_range == 'dtype':
            hist_range = dtype_limits(image, clip_negative=False)
        else:
            ValueError('Wrong value for the `source_range` argument')
        hist, bin_edges = np.histogram(image, bins=nbins, range=hist_range)
        bin_centers = (bin_edges[:-1] + bin_edges[1:]) / 2.

    if normalize:
        hist = hist / np.sum(hist)
    return hist, bin_centers


def threshold_multiotsu(image, classes=3, nbins=256):
    r"""Generate `classes`-1 threshold values to divide gray levels in `image`.
    The threshold values are chosen to maximize the total sum of pairwise
    variances between the thresholded graylevel classes. See Notes and [1]_
    for more details.
    Parameters
    ----------
    image : (N, M) ndarray
        Grayscale input image.
    classes : int, optional
        Number of classes to be thresholded, i.e. the number of resulting
        regions.
    nbins : int, optional
        Number of bins used to calculate the histogram. This value is ignored
        for integer arrays.
    Returns
    -------
    thresh : array
        Array containing the threshold values for the desired classes.
    Raises
    ------
    ValueError
         If ``image`` contains less grayscale value then the desired
         number of classes.
    Notes
    -----
    This implementation relies on a Cython function whose complexity
    is :math:`O\left(\frac{Ch^{C-1}}{(C-1)!}\right)`, where :math:`h`
    is the number of histogram bins and :math:`C` is the number of
    classes desired.
    The input image must be grayscale.
    References
    ----------
    .. [1] Liao, P-S., Chen, T-S. and Chung, P-C., "A fast algorithm for
           multilevel thresholding", Journal of Information Science and
           Engineering 17 (5): 713-727, 2001. Available at:
           <http://ftp.iis.sinica.edu.tw/JISE/2001/200109_01.pdf>
           :DOI:`10.6688/JISE.2001.17.5.1`
    .. [2] Tosa, Y., "Multi-Otsu Threshold", a java plugin for ImageJ.
           Available at:
           <http://imagej.net/plugins/download/Multi_OtsuThreshold.java>
    Examples
    --------
    >>> from skimage.color import label2rgb
    >>> from skimage import data
    >>> image = data.camera()
    >>> thresholds = threshold_multiotsu(image)
    >>> regions = np.digitize(image, bins=thresholds)
    >>> regions_colorized = label2rgb(regions)
    """

    if len(image.shape) > 2 and image.shape[-1] in (3, 4):
        msg = ("threshold_multiotsu is expected to work correctly only for "
               "grayscale images; image shape {0} looks like an RGB image")
        raise (msg.format(image.shape))

    # calculating the histogram and the probability of each gray level.
    prob, bin_centers = histogram(image.ravel(),
                                  nbins=nbins,
                                  source_range='image',
                                  normalize=True)
    prob = prob.astype('float32')

    nvalues = np.count_nonzero(prob)
    if nvalues < classes:
        msg = ("The input image has only {} different values. "
               "It can not be thresholded in {} classes")
        raise ValueError(msg.format(nvalues, classes))
    elif nvalues == classes:
        thresh_idx = np.where(prob > 0)[0][:-1]
    else:
        # Get threshold indices
        try:
            thresh_idx = _get_multiotsu_thresh_indices_lut(prob, classes - 1)
        except MemoryError:
            # Don't use LUT if the number of bins is too large (if the
            # image is uint16 for example): in this case, the
            # allocated memory is too large.
            thresh_idx = _get_multiotsu_thresh_indices(prob, classes - 1)

    thresh = bin_centers[thresh_idx]

    return thresh

新建文件_multiotsu.pyx

#cython: cdivision=True
#cython: boundscheck=False
#cython: nonecheck=False
#cython: wraparound=False
import numpy as np

cimport numpy as cnp
cimport cython


def _get_multiotsu_thresh_indices_lut(float [::1] prob,
                                      Py_ssize_t thresh_count):
    """Finds the indices of Otsu thresholds according to the values
    occurence probabilities.

    This implementation uses a LUT to reduce the number of floating
    point operations (see [1]_). The use of the LUT reduces the
    computation time at the price of more memory consumption.

    Parameters
    ----------
    prob : array
        Value occurence probabilities.
    thresh_count : int
        The desired number of thresholds (classes-1).


    Returns
    -------
    py_thresh_indices : ndarray
        The indices of the desired thresholds.

    References
    ----------
    .. [1] Liao, P-S., Chen, T-S. and Chung, P-C., "A fast algorithm for
           multilevel thresholding", Journal of Information Science and
           Engineering 17 (5): 713-727, 2001. Available at:
           <http://ftp.iis.sinica.edu.tw/JISE/2001/200109_01.pdf>
           :DOI:`10.6688/JISE.2001.17.5.1`

    """

    cdef Py_ssize_t nbins = prob.shape[0]
    py_thresh_indices = np.empty(thresh_count, dtype=np.intp)
    cdef Py_ssize_t[::1] thresh_indices = py_thresh_indices
    cdef Py_ssize_t[::1] current_indices = np.empty(thresh_count, dtype=np.intp)
    cdef float [::1] var_btwcls = np.zeros((nbins * (nbins + 1)) / 2,
                                           dtype=np.float32)
    cdef float [::1] zeroth_moment = np.empty(nbins, dtype=np.float32)
    cdef float [::1] first_moment = np.empty(nbins, dtype=np.float32)

    with nogil:
        _set_var_btwcls_lut(prob, nbins, var_btwcls, zeroth_moment,
                            first_moment)
        _set_thresh_indices_lut(var_btwcls, hist_idx=0,
                                thresh_idx=0, nbins=nbins,
                                thresh_count=thresh_count, sigma_max=0,
                                current_indices=current_indices,
                                thresh_indices=thresh_indices)

    return py_thresh_indices


cdef void _set_var_btwcls_lut(float [::1] prob,
                              Py_ssize_t nbins,
                              float [::1] var_btwcls,
                              float [::1] zeroth_moment,
                              float [::1] first_moment) nogil:
    """Builds the lookup table containing the variance between classes.

    The variance between classes are stored in
    ``var_btwcls``. ``zeroth_moment`` and ``first_moment`` are buffers
    for storing the first row of respectively the zeroth and first
    order moments lookup table (respectively H, P and S in [1]_).

    Parameters
    ----------
    prob : array
        Value occurence probabilities.
    nbins : int
        The number of intensity values.
    var_btwcls : array
        The upper triangular part of the lookup table containing the
        variance between classes (referred to as H in [1]_). Its size
        is equal to nbins*(nbins + 1) / 2.
    zeroth_moment : array
        First row of the zeroth order moments LUT (referred to as P in
        [1]_).
    first_moment : array
        First row of the first order moments LUT (referred to as S in
        [1]_).

    Notes
    -----
    Only the first rows of the moments lookup tables are necessary to
    build the lookup table containing the variance between
    classes. ``var_btwcls`` is stored in the compressed upper
    triangular matrix form (i.e. the seros of the lower triangular
    part are not stored).

    References
    ----------
    .. [1] Liao, P-S., Chen, T-S. and Chung, P-C., "A fast algorithm for
           multilevel thresholding", Journal of Information Science and
           Engineering 17 (5): 713-727, 2001. Available at:
           <http://ftp.iis.sinica.edu.tw/JISE/2001/200109_01.pdf>
           :DOI:`10.6688/JISE.2001.17.5.1`
    """
    cdef cnp.intp_t i, j, idx
    cdef float zeroth_moment_ij, first_moment_ij

    zeroth_moment[0] = prob[0]
    first_moment[0] = prob[0]
    for i in range(1, nbins):
        zeroth_moment[i] = zeroth_moment[i - 1] + prob[i]
        first_moment[i] = first_moment[i - 1] + i * prob[i]
        if zeroth_moment[i] > 0:
            var_btwcls[i] = (first_moment[i]**2) / zeroth_moment[i]

    idx = nbins

    for i in range(1, nbins):
        for j in range(i, nbins):
            zeroth_moment_ij = zeroth_moment[j] - zeroth_moment[i - 1]
            if zeroth_moment_ij > 0:
                first_moment_ij = first_moment[j] - first_moment[i - 1]
                var_btwcls[idx] = (first_moment_ij**2) / zeroth_moment_ij
            idx += 1


cdef float _get_var_btwclas_lut(float [::1] var_btwcls, Py_ssize_t i,
                                Py_ssize_t j, Py_ssize_t nbins) nogil:
    """Returns the variance between classes stored in compressed upper
    triangular matrix form at the desired 2D indices.

    Parameters
    ----------
    var_btwcls : array
        The lookup table containing the variance between classes in
        compressed upper triangular matrix form.
    i, j : int
        2D indices in the uncompressed lookup table.
    nbins : int
        The number of columns in the lookup table.

    Returns
    -------
    value : float
        The value of the lookup table corresponding to index (i, j).
    """
    cdef cnp.intp_t idx = (i * (2 * nbins - i + 1)) / 2 + j - i
    return var_btwcls[idx]


cdef float _set_thresh_indices_lut(float[::1] var_btwcls, Py_ssize_t hist_idx,
                                   Py_ssize_t thresh_idx, Py_ssize_t nbins,
                                   Py_ssize_t thresh_count, float sigma_max,
                                   Py_ssize_t[::1] current_indices,
                                   Py_ssize_t[::1] thresh_indices) nogil:
    """Recursive function for finding the indices of the thresholds
    maximizing the  variance between classes sigma.

    This implementation use a lookup table of variance between classes
    to perform a brute force evaluation of sigma over all the
    combinations of threshold to find the indices maximizing sigma
    (see [1]_).

    Parameters
    ----------
    var_btwcls : array
        The upper triangular part of the lookup table containing the
        variance between classes (referred to as H in [1]_). Its size
        is equal to nbins*(nbins + 1) / 2.
    hist_idx  : int
        Current index in the histogram.
    thresh_idx : int
        Current index in thresh_indices.
    nbins : int
        number of bins used in the histogram
    thresh_count : int
        The desired number of thresholds (classes-1).
    sigma_max : float
        Current maximum variance between classes.
    current_indices : array
        Current evalueted threshold indices.
    thresh_indices : array
        The indices of thresholds maximizing the variance between
        classes.

    Returns
    -------
    max_sigma : float
        Maximum variance between classes.

    Notes
    -----
    For any candidate current_indices {t_0, ..., t_n}, sigma equals
    var_btwcls[0, t_0] + var_btwcls[t_0+1, t_1] + ...
    + var_btwcls[t_(i-1) + 1, t_i] + ... + var_btwcls[t_n, nbins-1]

    References
    ----------
    .. [1] Liao, P-S., Chen, T-S. and Chung, P-C., "A fast algorithm for
           multilevel thresholding", Journal of Information Science and
           Engineering 17 (5): 713-727, 2001. Available at:
           <http://ftp.iis.sinica.edu.tw/JISE/2001/200109_01.pdf>
           :DOI:`10.6688/JISE.2001.17.5.1`
    """
    cdef cnp.intp_t idx
    cdef float sigma

    if thresh_idx < thresh_count:

        for idx in range(hist_idx, nbins - thresh_count + thresh_idx):
            current_indices[thresh_idx] = idx
            sigma_max = _set_thresh_indices_lut(var_btwcls, hist_idx=idx + 1,
                                                thresh_idx=thresh_idx + 1,
                                                nbins=nbins,
                                                thresh_count=thresh_count,
                                                sigma_max=sigma_max,
                                                current_indices=current_indices,
                                                thresh_indices=thresh_indices)

    else:

        sigma = (_get_var_btwclas_lut(var_btwcls, 0, current_indices[0], nbins)
                 + _get_var_btwclas_lut(var_btwcls,
                                        current_indices[thresh_count - 1] + 1,
                                        nbins - 1, nbins))
        for idx in range(thresh_count - 1):
            sigma += _get_var_btwclas_lut(var_btwcls, current_indices[idx] + 1,
                                          current_indices[idx + 1], nbins)

        if sigma > sigma_max:
            sigma_max = sigma
            thresh_indices[:] = current_indices[:]

    return sigma_max


def _get_multiotsu_thresh_indices(float [::1] prob, Py_ssize_t thresh_count):
    """Finds the indices of Otsu thresholds according to the values
    occurence probabilities.

    This implementation, as opposed to `_get_multiotsu_thresh_indices_lut`,
    does not use LUT. It is therefore slower.

    Parameters
    ----------
    prob : array
        Value occurence probabilities.
    thresh_count : int
        The desired number of threshold.

    Returns
    -------
    py_thresh_indices : array
        The indices of the desired thresholds.

    """

    cdef Py_ssize_t nbins = prob.shape[0]
    py_thresh_indices = np.empty(thresh_count, dtype=np.intp)
    cdef Py_ssize_t[::1] thresh_indices = py_thresh_indices
    cdef Py_ssize_t[::1] current_indices = np.empty(thresh_count, dtype=np.intp)
    cdef float [::1] zeroth_moment = np.empty(nbins, dtype=np.float32)
    cdef float [::1] first_moment = np.empty(nbins, dtype=np.float32)

    with nogil:
        _set_moments_lut_first_row(prob, nbins, zeroth_moment, first_moment)
        _set_thresh_indices(zeroth_moment, first_moment, hist_idx=0,
                            thresh_idx=0, nbins=nbins,
                            thresh_count=thresh_count, sigma_max=0,
                            current_indices=current_indices,
                            thresh_indices=thresh_indices)

    return py_thresh_indices


cdef void _set_moments_lut_first_row(float [::1] prob,
                                     Py_ssize_t nbins,
                                     float [::1] zeroth_moment,
                                     float [::1] first_moment) nogil:
    """Builds the first rows of the zeroth and first moments lookup table
    necessary to the computation of the variance between class.

    Parameters
    ----------
    prob : array
        Value occurence probabilities.
    nbins : int
        The number of intensity values.
    zeroth_moment : array
        First row of the zeroth order moments LUT (referred to as P in
        [1]_).
    first_moment : array
        First row of the first order moments LUT (referred to as S in
        [1]_).

    References
    ----------
    .. [1] Liao, P-S., Chen, T-S. and Chung, P-C., "A fast algorithm for
           multilevel thresholding", Journal of Information Science and
           Engineering 17 (5): 713-727, 2001. Available at:
           <http://ftp.iis.sinica.edu.tw/JISE/2001/200109_01.pdf>
           :DOI:`10.6688/JISE.2001.17.5.1`
    """
    cdef cnp.intp_t i

    zeroth_moment[0] = prob[0]
    first_moment[0] = prob[0]
    for i in range(1, nbins):
        zeroth_moment[i] = zeroth_moment[i - 1] + prob[i]
        first_moment[i] = first_moment[i - 1] + i * prob[i]


cdef float _get_var_btwclas(float [::1] zeroth_moment,
                            float [::1] first_moment,
                            Py_ssize_t i, Py_ssize_t j) nogil:
    """Computes the variance between two classes.

    Parameters
    ----------
    zeroth_moment : array
        First row of the zeroth order moments LUT (referred to as P in
        [1]_).
    first_moment : array
        First row of the first order moments LUT (referred to as S in
        [1]_).
    i, j : int
        The indices of the two considred classes.

    Returns
    -------
    value : float
        The variance between the classes i and j.
    """

    cdef float zeroth_moment_ij, first_moment_ij

    if i == 0:
        if zeroth_moment[i] > 0:
            return (first_moment[j]**2) / zeroth_moment[j]
    else:
        zeroth_moment_ij = zeroth_moment[j] - zeroth_moment[i - 1]
        if zeroth_moment_ij > 0:
            first_moment_ij = first_moment[j] - first_moment[i - 1]
            return (first_moment_ij**2) / zeroth_moment_ij
    return 0


cdef float _set_thresh_indices(float[::1] zeroth_moment,
                               float[::1] first_moment,
                               Py_ssize_t hist_idx,
                               Py_ssize_t thresh_idx, Py_ssize_t nbins,
                               Py_ssize_t thresh_count, float sigma_max,
                               Py_ssize_t[::1] current_indices,
                               Py_ssize_t[::1] thresh_indices) nogil:
    """Recursive function for finding the indices of the thresholds
    maximizing the  variance between classes sigma.

    This implementation uses the first rows of the zeroth and first
    moments lookup table to compute the variance between class and
    performs a brute force evaluation of sigma over all the
    combinations of threshold to find the indices maximizing sigma
    (see [1]_)..

    Parameters
    ----------
    zeroth_moment : array
        First row of the zeroth order moments LUT (referred to as P in
        [1]_).
    first_moment : array
        First row of the first order moments LUT (referred to as S in
        [1]_).
    hist_idx : int
        Current index in the histogram.
    thresh_idx : int
        Current index in thresh_indices.
    nbins : int
        number of bins used in the histogram
    thresh_count : int
        The desired number of thresholds (classes-1).
    sigma_max : float
        Current maximum variance between classes.
    current_indices : array
        Current evalueted threshold indices.
    thresh_indices : array
        The indices of thresholds maximizing the variance between
        classes.

    Returns
    -------
    max_sigma : float
        Maximum variance between classes.

    References
    ----------
    .. [1] Liao, P-S., Chen, T-S. and Chung, P-C., "A fast algorithm for
           multilevel thresholding", Journal of Information Science and
           Engineering 17 (5): 713-727, 2001. Available at:
           <http://ftp.iis.sinica.edu.tw/JISE/2001/200109_01.pdf>
           :DOI:`10.6688/JISE.2001.17.5.1`
    """
    cdef cnp.intp_t idx
    cdef float sigma

    if thresh_idx < thresh_count:

        for idx in range(hist_idx, nbins - thresh_count + thresh_idx):
            current_indices[thresh_idx] = idx
            sigma_max = _set_thresh_indices(zeroth_moment,
                                            first_moment,
                                            hist_idx=idx + 1,
                                            thresh_idx=thresh_idx + 1,
                                            nbins=nbins,
                                            thresh_count=thresh_count,
                                            sigma_max=sigma_max,
                                            current_indices=current_indices,
                                            thresh_indices=thresh_indices)

    else:

        sigma = (_get_var_btwclas(zeroth_moment, first_moment, 0,
                                  current_indices[0])
                 + _get_var_btwclas(zeroth_moment, first_moment,
                                    current_indices[thresh_count - 1] + 1,
                                    nbins - 1))
        for idx in range(thresh_count - 1):
            sigma += _get_var_btwclas(zeroth_moment, first_moment,
                                      current_indices[idx] + 1,
                                      current_indices[idx + 1])
        if sigma > sigma_max:
            sigma_max = sigma
            thresh_indices[:] = current_indices[:]

    return sigma_max

新建文件setup.py

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
from Cython.Distutils import build_ext
import numpy as np

# ext_module = cythonize("TestOMP.pyx")    
ext_module = Extension(
    "_multiotsu",
    ["_multiotsu.pyx"],
)

setup(
    cmdclass={'build_ext': build_ext},
    ext_modules=[ext_module],
    include_dirs=[np.get_include()]
) 

编译_multiotsu.pyx,首先cd到该文件所在目录,然后使用python setup.py build_ext  --inplace,然后会出现以下文件夹

将_multiotsu.cp35-win_amd64.pyd复制到与_multiotsu.pyx同一文件夹下,然后重命名为_multiotsu.pyd。

直接python test.py命令即可。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我会尽力帮助你解决这个问题。首先,确保你已经安装了 `scikit-image` 和 `sunpy` 库。 以下是一个简单的代码示例,它演示如何使用 `skimage.feature.blob_log()` 函数来检测太阳黑子,并使用 `sunpy` 库获取太阳黑子的经纬度信息和转化为像素值的位置。然后,使用 `matplotlib` 库将结果可视化,并在图标识位置和像素坐标值。 ```python import sunpy.map from skimage.feature import blob_log import matplotlib.pyplot as plt # 读取FITS文件 sunpy_map = sunpy.map.Map('sunspot.fits') # 获取图像数据 image = sunpy_map.data # 检测太阳黑子 blobs_log = blob_log(image, max_sigma=30, num_sigma=10, threshold=.1) # 获取太阳黑子的像素坐标和经纬度信息 pix_coords = [(int(blob[0]), int(blob[1])) for blob in blobs_log] world_coords = sunpy_map.pixel_to_world(blobs_log[:, 0], blobs_log[:, 1]) # 可视化结果 fig, ax = plt.subplots(figsize=(8, 8)) ax.set_title('Sunspots') ax.imshow(image, cmap='gray') for i in range(len(pix_coords)): ax.plot(pix_coords[i][1], pix_coords[i][0], 'ro', markersize=10) ax.text(pix_coords[i][1]+10, pix_coords[i][0]+10, f'{pix_coords[i]}', color='r', fontsize=12) ax.text(pix_coords[i][1]+10, pix_coords[i][0]-20, f'{world_coords[i]}', color='w', fontsize=12) plt.show() ``` 这段代码将打开名为 `sunspot.fits` 的文件,并使用 `sunpy` 库将它转换为 `sunpy.map.Map` 对象。然后,它从地图提取图像数据,并使用 `skimage.feature.blob_log()` 函数检测太阳黑子。接下来,它使用 `sunpy` 库将太阳黑子的像素坐标转换为经纬度信息。最后,它使用 `matplotlib` 库将结果可视化,并在图标识位置和像素坐标值。 请注意,这只是一个简单的示例,你需要根据具体的需求进行修改和优化。希望这可以帮助你解决问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值