从float64到uint8的有损转换

12

来自 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'))

将 float64 转换为 uint8 时会出现信息丢失。范围为 [0,1]。在保存图像之前将其转换为 uint8 可以抑制此警告。

我还很没有经验,有什么快速解决方法吗?

2个回答

16
警告信息已经很明显了:color.convert_colorspace(in_hsv_h, 'HSV', 'RGB') 的类型是 float64,而 imsave 函数需要将元素转换为 uint8 类型。
PNG 图像的像素以每个分量一个字节存储(例如一个字节红色、一个字节绿色和一个字节蓝色)。 每个分量都是在 [0, 255] 范围内的整数值(类型为uint8color.convert_colorspace 的输出是 float64 类型,每个颜色分量的取值范围是 [0, 1],类型为 float64(在内存中以64位存储,比 uint8 更精确)。
float64 取值范围 [0, 1] 到 uint8 取值范围[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编程经验,请对我的答案持谨慎态度。


正如denis_smyslov下面的回答提醒:Skimage库警告不要使用astype更改图像的数据类型。(https://scikit-image.org/docs/dev/user_guide/data_types.html) - user115625

5
没有理由使用imageio库保存您的图像,因为您已经在使用来自skimage库的skimage.color模块。您可以继续使用skimageskimage.save保存图像。
此外,警告本身(“从float64到uint8的有损转换。范围[0,1]。在保存之前将图像转换为uint8以抑制此警告。”)来自于skimage库。
出现此警告是因为在保存时将图像的dtype从原始的'float64'更改为'uint8'。
但保存图像会将dtype更改为'uint8':
要消除此警告,您需要在保存之前更改图像的dtype。 Skimage提供了实用函数img_as_ubyte来完成这项工作:
Skimage库警告不要使用astype来更改图像的dtype。

一般来说,根据生成浮点数组的方式,您可能需要在转换dtype之前使用exposure.rescale_intensity。 - user115625

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接