【问题标题】:Lossy conversion from float64 to uint8从 float64 到 uint8 的有损转换
【发布时间】:2023-03-20 15:40:01
【问题描述】:

代码来自https://www.makeartwithpython.com/blog/visualizing-sort-algorithms-in-python/

from imageio import imsave

import numpy as np

newImage = np.random.randint(0, 255, (300, 300, 3))

in_hsv_h = color.convert_colorspace(newImage, 'RGB', 'HSV')
in_hsv_s = in_hsv_h.copy()
in_hsv_v = in_hsv_h.copy()

for i in range(newImage.shape[0]):
    in_hsv_h[i,:,0] = np.sort(in_hsv_h[i,:,0])
    in_hsv_s[i,:,1] = np.sort(in_hsv_s[i,:,1])
    in_hsv_v[i,:,2] = np.sort(in_hsv_v[i,:,2])

imsave('testing-sorted-hue.png', color.convert_colorspace(in_hsv_h, 'HSV', 'RGB'))
imsave('testing-sorted-saturation.png', color.convert_colorspace(in_hsv_s, 'HSV', 'RGB'))

Lossy conversion from float64 to uint8. Range [0, 1]. Convert image to uint8 prior to saving to suppress this warning.

还是很缺乏经验,有什么快速解决这个问题的方法吗?

【问题讨论】:

    标签: python rgb hsv


    【解决方案1】:

    警告是不言自明的:color.convert_colorspace(in_hsv_h, 'HSV', 'RGB') 的类型为 float64,而 imsave,将元素转换为 uint8

    PNG 图像的像素,每个组件存储为一个字节(红色一个字节,绿色一个字节,蓝色一个字节)。
    每个分量都是 [0, 255] 范围内的整数值(类型 uint8)。

    color.convert_colorspace 的输出是float64,每个颜色分量在float64 类型的范围[0, 1] 内(在内存中存储为64 位,比uint8 精确得多)。

    float64 range [0, 1] 到 uint8 range [0, 255] 的转换执行如下:uint8_val = round(float64_val*255)
    舍入操作会丢失一些数据(例如:如果 float64_val*255 = 132.658,则结果舍入为 133)。

    在保存之前将图像转换为 uint8 以抑制此警告

    告诉您在保存之前将图像元素转换为uint8

    解决方案很简单。
    乘以 255,然后加上 .astype(np.uint8)

    imsave('testing-sorted-hue.png', (color.convert_colorspace(in_hsv_h, 'HSV', 'RGB')*255).astype(np.uint8))
    

    为了让您的代码正常工作,您还应该在构建newImage 时添加.astype(np.uint8)

    newImage = np.random.randint(0, 255, (300, 300, 3)).astype(np.uint8)
    

    完整代码:

    from imageio import imsave
    from skimage import color
    
    import numpy as np
    
    newImage = np.random.randint(0, 255, (300, 300, 3)).astype(np.uint8)
    
    
    in_hsv_h = color.convert_colorspace(newImage, 'RGB', 'HSV')
    in_hsv_s = in_hsv_h.copy()
    in_hsv_v = in_hsv_h.copy()
    
    for i in range(newImage.shape[0]):
        in_hsv_h[i,:,0] = np.sort(in_hsv_h[i,:,0])
        in_hsv_s[i,:,1] = np.sort(in_hsv_s[i,:,1])
        in_hsv_v[i,:,2] = np.sort(in_hsv_v[i,:,2])
    
    imsave('testing-sorted-hue.png', (color.convert_colorspace(in_hsv_h, 'HSV', 'RGB')*255).astype(np.uint8))
    imsave('testing-sorted-saturation.png', (color.convert_colorspace(in_hsv_s, 'HSV', 'RGB')*255).astype(np.uint8))
    

    备注:
    makeartwithpython 中的示例使用from imageio import imsave 而不是from scipy.misc import imsave,并且站点中的示例工作正常。

    注意:
    我没有很多Python编程经验,请谨慎回答。

    【讨论】:

      【解决方案2】:

      没有理由使用imageio 库来保存您的图像,因为您已经使用了skimage 库中的skimage.color 模块。您可以继续使用skimage 以使用skimage.save 保存图像。

      此外,警告本身(“从 float64 到 uint8 的有损转换。范围 [0, 1]。在保存之前将图像转换为 uint8 以抑制此警告。”)来自 skimage 库。

      出现此警告是因为图像的 dtype 在保存过程中从原始“float64”更改为“uint8”。

      print(color.convert_colorspace(in_hsv_h, 'HSV', 'RGB').dtype) float64

      但保存图像会将 dtype 更改为“uint8”:

      from skimage import io io.imread('testing-sorted-hue.png').dtype dtype('uint8')

      要抑制警告,您需要在保存之前更改图像的 dtype。 Skimage 提供了实用函数img_as_ubyte 来做到这一点:

      in_hsv_h = color.convert_colorspace(in_hsv_h, 'HSV', 'RGB') print('dtype before:', in_hsv_h.dtype) dtype before: float64

      from skimage.util import img_as_ubyte in_hsv_h=img_as_ubyte(in_hsv_h) print('dtype after: ', in_hsv_h.dtype) dtype after: uint8

      Skimage 库警告不要使用 astype 更改图像的 dtype。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-12-28
        • 1970-01-01
        • 2019-12-28
        • 2016-08-12
        • 2018-03-23
        • 2020-07-16
        • 1970-01-01
        • 2017-03-11
        相关资源
        最近更新 更多