scikit-image:使用imsave将ndarray写入图像,使用imread读回,但数据不匹配

10
这是最小工作示例:
import numpy as np
from skimage.io import imsave, imread

image = np.array([[[109, 232, 173],
                [ 55,  35, 144]],
                [[ 43, 124, 185],
                [234, 127, 246]]], dtype=np.uint8)

imsave("test.jpg", image)
rb_image = imread("test.jpg")
print("original image")
print(image)
print("read back image")
print(rb_image)

运行后,从文件读回的 ndarray 与原数组不匹配。
original image
[[[109 232 173]
  [ 55  35 144]]

 [[ 43 124 185]
  [234 127 246]]]
read back image
[[[111 208 255]
  [ 42  61 138]]

 [[ 72 140 201]
  [141 131 218]]]

有人可以给我一些建议吗?

2个回答

23

JPEG是一种有损图像压缩算法,旨在通过去除人眼难以察觉的信息来减小文件大小。这意味着将图片保存为jpg格式可以节省一些磁盘空间,但会改变数组的像素值。

您可以选择使用无损PNG格式来避免这个问题。以下代码片段对我有效:

import numpy as np
from skimage.io import imsave, imread

image = np.array([[[109, 232, 173],
                [ 55,  35, 144]],
                [[ 43, 124, 185],
                [234, 127, 246]]], dtype=np.uint8)

imsave("test.png", image)
rb_image = imread("test.png")
print("original image")
print(image)
print("read back image")
print(rb_image)

这是结果。

original image
[[[109 232 173]
  [ 55  35 144]]

 [[ 43 124 185]
  [234 127 246]]]
read back image
[[[109 232 173]
  [ 55  35 144]]

 [[ 43 124 185]
  [234 127 246]]]

是的,这对我也有效。我也尝试了两次保存和读取jpg。图像中的数据仍然会改变,所以jpg中的数据损失非常巨大。顺便说一句,在这种情况下,png文件的大小比jpg文件小得多,这非常奇怪,我猜测这是因为数据非常小,试图像JPG一样压缩它,反而会增加文件大小,这不符合算法的意图。 - scott huang
@scotthuang 当然可以...那个数据甚至没有一个宏块那么大(而且单通道可能也很重要,也许...)。如果你感兴趣,为什么不阅读维基关于JPEG的内容来理解这一点呢?既然你从这里获得了一些东西,为什么不给这个答案点个赞呢? - sascha
我稍后会尝试查阅维基百科,我现在正忙于项目中。有太多事情要处理,不想分心。我已经点赞了你的回答,我会等一天看看是否有其他人评论你的回答,分享一些想法... - scott huang

0
Scikit在底层使用了PIL,你尝试过使用纯PIL吗?
在示例中
   import numpy as np
   from skimage.io import imsave, imread
   from PIL import Image

   image = np.array([[[109, 232, 173],
                [ 55,  35, 144]],
                [[ 43, 124, 185],
                [234, 127, 246]]], dtype=np.uint8)

   Image.fromarray(image).save()
   rb_image = imread("test.jpg")
   print("original image")
   print(image)
   print("read back image")
   print(rb_image)

将 imsave("test.jpg", image) 替换为 Image.fromarray(image).save("test.jpg"),仍然可以获得相同的结果。 - scott huang
我昨天尝试了这个,问题仍然存在。在保存和读回后,数据发生了变化。 - scott huang

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