从 float64 到 uint8 的有损转换

Lossy conversion from float64 to uint8

代码来自 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.

还是很新手,有什么快速解决这个问题的方法吗?

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

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

color.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)。

Convert image to uint8 prior to saving to suppress this warning

告诉您在保存之前将图像元素转换为 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编程经验,请谨慎接受我的回答。

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

此外,警告本身 ("Lossy conversion from float64 to uint8. Range [0, 1]. Convert image to uint8 prior to saving to suppress this warning.") 来自 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')

要取消警告,您需要在保存前更改图像的数据类型。 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。