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

后端 未结 5 815
失恋的感觉
失恋的感觉 2021-01-05 06:47

While executing the below code:

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


        
相关标签:
5条回答
  • 2021-01-05 06:57

    The scipy.misc.toimage() function was deprecated in Scipy 1.0.0, and was completely removed in version 1.3.0. From the 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.

    The notes link to the v1.1.0 documentation that shows what to use instead; from the scipy.misc.toimage() documentation for v1.1.0:

    Use Pillow’s Image.fromarray directly instead.

    The function does more work than just Image.fromarray could do, however. You could 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
    

    This could be further simplified based on the actual arguments used; your sample code doesn't use the pal argument, for example.

    0 讨论(0)
  • 2021-01-05 06:58

    @Martijn Pieters worked for me but I also found another solution that may suit some people better. You can also use the code below that imports keras.preprocessing.image, array_to_img instead of scipy.misc.toimage which was deprecated in Scipy 1.0.0 as @Martijn Pieters has already mentioned.

    So as an example of using keras API to handle converting images:

    # example of converting an image with the Keras API
    from keras.preprocessing.image import load_img
    from keras.preprocessing.image import img_to_array
    from keras.preprocessing.image import array_to_img
    
    # load the image
    img = load_img('image.jpg')
    print(type(img))
    
    # convert to numpy array
    img_array = img_to_array(img)
    print(img_array.dtype)
    print(img_array.shape)
    
    # convert back to image
    img_pil = array_to_img(img_array)
    print(type(img_pil))
    
    # show image
    fig = plt.figure()
    ax = fig.add_subplot()
    ax.imshow(img_pil)
    

    and to save an image with keras:

    from keras.preprocessing.image import save_img
    from keras.preprocessing.image import load_img
    from keras.preprocessing.image import img_to_array
    
    # load image
    img = load_img('image.jpg')
    
    # convert image to a numpy array
    img_array = img_to_array(img)
    
    # save the image with a new filename
    save_img('image_save.jpg', img_array)
    
    # load the image to confirm it was saved correctly
    img = load_img('image_save.jpg')
    
    print(type(img))
    print(img.format)
    print(img.mode)
    print(img.size)
    
    0 讨论(0)
  • 2021-01-05 07:04

    Try !pip install scipy==1.1.0

    This worked for me.

    0 讨论(0)
  • 2021-01-05 07:15

    Current scipy version 1.3.0 doesn't include toimage() 1.3.0 docs here Try to install scipy 1.2.0 or 1.1.0 1.2.0 docs here with toimage() included.

    0 讨论(0)
  • 2021-01-05 07:19

    Uninstall SciPy and install SciPy v1.2.0

    $ pip uninstall scipy
    
    $ pip install scipy==1.2.0
    
    0 讨论(0)
提交回复
热议问题