Skip to main content
 首页 » 编程设计

python之属性错误 : module 'scipy.misc' has no attribute 'toimage'

2025年05月04日15jyk

执行以下代码时:

scipy.misc.toimage(output * 255, high=255, low=0, cmin=0, cmax=255).save( 
    params.result_dir + 'final/%5d_00_%d_out.png' % (test_id, ratio)) 

我收到以下错误:

AttributeError: module 'scipy.misc' has no attribute 'toimage'

我尝试按照此处所述安装 Pillow:scipy.misc module has no attribute imread?但同样的错误仍然存​​在。请帮忙。谢谢。

请您参考如下方法:

scipy.misc.toimage() 函数在 Scipy 1.0.0 中被弃用,并在 1.3.0 版中被完全删除。来自1.3.0 release notes :

Funtions from scipy.interpolate (spleval, spline, splmake, and spltopp) and functions from scipy.misc (bytescale, fromimage, imfilter, imread, imresize, imrotate, imsave, imshow, toimage) have been removed. The former set has been deprecated since v0.19.0 and the latter has been deprecated since v1.0.0.

注释链接到 v1.1.0 文档,显示了使用的内容;来自 scipy.misc.toimage() documentation for v1.1.0 :

Use Pillow’s Image.fromarray directly instead.

不过,该函数所做的工作不仅仅是 Image.fromarray 所能做的。你可以 port the original function :

import numpy as np 
from PIL import Image 
 
 
_errstr = "Mode is unknown or incompatible with input array shape." 
 
 
def bytescale(data, cmin=None, cmax=None, high=255, low=0): 
    """ 
    Byte scales an array (image). 
    Byte scaling means converting the input image to uint8 dtype and scaling 
    the range to ``(low, high)`` (default 0-255). 
    If the input image already has dtype uint8, no scaling is done. 
    This function is only available if Python Imaging Library (PIL) is installed. 
    Parameters 
    ---------- 
    data : ndarray 
        PIL image data array. 
    cmin : scalar, optional 
        Bias scaling of small values. Default is ``data.min()``. 
    cmax : scalar, optional 
        Bias scaling of large values. Default is ``data.max()``. 
    high : scalar, optional 
        Scale max value to `high`.  Default is 255. 
    low : scalar, optional 
        Scale min value to `low`.  Default is 0. 
    Returns 
    ------- 
    img_array : uint8 ndarray 
        The byte-scaled array. 
    Examples 
    -------- 
    >>> from scipy.misc import bytescale 
    >>> img = np.array([[ 91.06794177,   3.39058326,  84.4221549 ], 
    ...                 [ 73.88003259,  80.91433048,   4.88878881], 
    ...                 [ 51.53875334,  34.45808177,  27.5873488 ]]) 
    >>> bytescale(img) 
    array([[255,   0, 236], 
           [205, 225,   4], 
           [140,  90,  70]], dtype=uint8) 
    >>> bytescale(img, high=200, low=100) 
    array([[200, 100, 192], 
           [180, 188, 102], 
           [155, 135, 128]], dtype=uint8) 
    >>> bytescale(img, cmin=0, cmax=255) 
    array([[91,  3, 84], 
           [74, 81,  5], 
           [52, 34, 28]], dtype=uint8) 
    """ 
    if data.dtype == np.uint8: 
        return data 
 
    if high > 255: 
        raise ValueError("`high` should be less than or equal to 255.") 
    if low < 0: 
        raise ValueError("`low` should be greater than or equal to 0.") 
    if high < low: 
        raise ValueError("`high` should be greater than or equal to `low`.") 
 
    if cmin is None: 
        cmin = data.min() 
    if cmax is None: 
        cmax = data.max() 
 
    cscale = cmax - cmin 
    if cscale < 0: 
        raise ValueError("`cmax` should be larger than `cmin`.") 
    elif cscale == 0: 
        cscale = 1 
 
    scale = float(high - low) / cscale 
    bytedata = (data - cmin) * scale + low 
    return (bytedata.clip(low, high) + 0.5).astype(np.uint8) 
 
 
def toimage(arr, high=255, low=0, cmin=None, cmax=None, pal=None, 
            mode=None, channel_axis=None): 
    """Takes a numpy array and returns a PIL image. 
    This function is only available if Python Imaging Library (PIL) is installed. 
    The mode of the PIL image depends on the array shape and the `pal` and 
    `mode` keywords. 
    For 2-D arrays, if `pal` is a valid (N,3) byte-array giving the RGB values 
    (from 0 to 255) then ``mode='P'``, otherwise ``mode='L'``, unless mode 
    is given as 'F' or 'I' in which case a float and/or integer array is made. 
    .. warning:: 
        This function uses `bytescale` under the hood to rescale images to use 
        the full (0, 255) range if ``mode`` is one of ``None, 'L', 'P', 'l'``. 
        It will also cast data for 2-D images to ``uint32`` for ``mode=None`` 
        (which is the default). 
    Notes 
    ----- 
    For 3-D arrays, the `channel_axis` argument tells which dimension of the 
    array holds the channel data. 
    For 3-D arrays if one of the dimensions is 3, the mode is 'RGB' 
    by default or 'YCbCr' if selected. 
    The numpy array must be either 2 dimensional or 3 dimensional. 
    """ 
    data = np.asarray(arr) 
    if np.iscomplexobj(data): 
        raise ValueError("Cannot convert a complex-valued array.") 
    shape = list(data.shape) 
    valid = len(shape) == 2 or ((len(shape) == 3) and 
                                ((3 in shape) or (4 in shape))) 
    if not valid: 
        raise ValueError("'arr' does not have a suitable array shape for " 
                         "any mode.") 
    if len(shape) == 2: 
        shape = (shape[1], shape[0])  # columns show up first 
        if mode == 'F': 
            data32 = data.astype(np.float32) 
            image = Image.frombytes(mode, shape, data32.tostring()) 
            return image 
        if mode in [None, 'L', 'P']: 
            bytedata = bytescale(data, high=high, low=low, 
                                 cmin=cmin, cmax=cmax) 
            image = Image.frombytes('L', shape, bytedata.tostring()) 
            if pal is not None: 
                image.putpalette(np.asarray(pal, dtype=np.uint8).tostring()) 
                # Becomes a mode='P' automagically. 
            elif mode == 'P':  # default gray-scale 
                pal = (np.arange(0, 256, 1, dtype=np.uint8)[:, np.newaxis] * 
                       np.ones((3,), dtype=np.uint8)[np.newaxis, :]) 
                image.putpalette(np.asarray(pal, dtype=np.uint8).tostring()) 
            return image 
        if mode == '1':  # high input gives threshold for 1 
            bytedata = (data > high) 
            image = Image.frombytes('1', shape, bytedata.tostring()) 
            return image 
        if cmin is None: 
            cmin = np.amin(np.ravel(data)) 
        if cmax is None: 
            cmax = np.amax(np.ravel(data)) 
        data = (data*1.0 - cmin)*(high - low)/(cmax - cmin) + low 
        if mode == 'I': 
            data32 = data.astype(np.uint32) 
            image = Image.frombytes(mode, shape, data32.tostring()) 
        else: 
            raise ValueError(_errstr) 
        return image 
 
    # if here then 3-d array with a 3 or a 4 in the shape length. 
    # Check for 3 in datacube shape --- 'RGB' or 'YCbCr' 
    if channel_axis is None: 
        if (3 in shape): 
            ca = np.flatnonzero(np.asarray(shape) == 3)[0] 
        else: 
            ca = np.flatnonzero(np.asarray(shape) == 4) 
            if len(ca): 
                ca = ca[0] 
            else: 
                raise ValueError("Could not find channel dimension.") 
    else: 
        ca = channel_axis 
 
    numch = shape[ca] 
    if numch not in [3, 4]: 
        raise ValueError("Channel axis dimension is not valid.") 
 
    bytedata = bytescale(data, high=high, low=low, cmin=cmin, cmax=cmax) 
    if ca == 2: 
        strdata = bytedata.tostring() 
        shape = (shape[1], shape[0]) 
    elif ca == 1: 
        strdata = np.transpose(bytedata, (0, 2, 1)).tostring() 
        shape = (shape[2], shape[0]) 
    elif ca == 0: 
        strdata = np.transpose(bytedata, (1, 2, 0)).tostring() 
        shape = (shape[2], shape[1]) 
    if mode is None: 
        if numch == 3: 
            mode = 'RGB' 
        else: 
            mode = 'RGBA' 
 
    if mode not in ['RGB', 'RGBA', 'YCbCr', 'CMYK']: 
        raise ValueError(_errstr) 
 
    if mode in ['RGB', 'YCbCr']: 
        if numch != 3: 
            raise ValueError("Invalid array shape for mode.") 
    if mode in ['RGBA', 'CMYK']: 
        if numch != 4: 
            raise ValueError("Invalid array shape for mode.") 
 
    # Here we know data and mode is correct 
    image = Image.frombytes(mode, shape, strdata) 
    return image 

这可以根据实际使用的参数进一步简化;例如,您的示例代码不使用 pal 参数。