【问题标题】:Reading bytes for an image读取图像的字节
【发布时间】:2018-03-16 23:05:24
【问题描述】:

我从一个文件中读取了 784 个字节(一个 28x28 的图像):

with open(self.filePath, 'rb') as f:
    aLetter = f.read(784)
    print ('A Letter',aLetter)
    image = Image.frombytes('1',[79,78],aLetter)

当我打印并将那个“字母”扔到文本垫时,我计算的是 764 个字节,而不是 784 个字节。但是当我以 frombytes 将字母传递给枕头时,我可以将它传递到 [79,78] 字节数组的大小。

什么给了?我有多少字节?如何让我的 784 字节数组创建 28x28 字母图像? Pillow 是如何看到比那里更多的字节的?

对于那些感兴趣的人,数据来自这里: http://cis.jhu.edu/~sachin/digit/digit.html

解释:

每个训练示例的大小为 28x28 像素。像素存储为无符号字符(1 字节),取值范围为 0 到 255

【问题讨论】:

  • 如果 len(aLetter) 真的只有 764 字节,那么尝试创建 79 x 78 大小的图像将失败并出现 ValueError: not enough image data 异常。
  • 如果创建了图像,则您拥有正确的字节数。试试len(aLetter),不要打印二进制对象,手动计数..

标签: python python-3.x image byte pillow


【解决方案1】:

你没有 764 字节,因为如果你太短就会抛出异常:

>>> Image.frombytes('1', [79, 78], bytes(764))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mjpieters/Development/venvs/stackoverflow-3.7/lib/python3.7/site-packages/PIL/Image.py", line 2331, in frombytes
    im.frombytes(data, decoder_name, args)
  File "/Users/mjpieters/Development/venvs/stackoverflow-3.7/lib/python3.7/site-packages/PIL/Image.py", line 786, in frombytes
    raise ValueError("not enough image data")
ValueError: not enough image data

虽然您可以制作 784 字节的过大图像:

>>> Image.frombytes('1', [79, 78], bytes(784))
<PIL.Image.Image image mode=1 size=79x78 at 0x104D2ACF8>

PIL 接受的 79 x 78 图像的最小字节数是 780 字节。因为您正在创建一个'1' 模式图像,所以每个字节都有 8 个像素,因此您只需要math.ceil(79 / 8),即每行 10 个字节。

要查看bytes 对象的长度,请打印len() 函数结果:

>>> with open('data0', 'rb') as f:
...     letter_data = f.read(28 * 28)
...     print(len(letter_data))
...
784

但是,您对数据使用了错误的模式。 '1' 是一种on 或off 的图像格式,只有0 或1 有意义。图像训练数据每像素使用一个完整字节或 256 个可能的值,因此您希望使用 'L' 模式加载它:

letter_image = Image.frombytes('L', (28, 28), letter_data)

使用'L'时,会使用每个字节的全部256个可能值,并且必须传入28 * 28字节,否则如果真的只有764字节就会报错:

>>> image = Image.frombytes('L', (28, 28), letter_data[:764])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mjpieters/Development/venvs/stackoverflow-3.7/lib/python3.7/site-packages/PIL/Image.py", line 2331, in frombytes
    im.frombytes(data, decoder_name, args)
  File "/Users/mjpieters/Development/venvs/stackoverflow-3.7/lib/python3.7/site-packages/PIL/Image.py", line 786, in frombytes
    raise ValueError("not enough image data")
ValueError: not enough image data

使用letter_image.save('/tmp/0.png')data0 中的第一张图片导出为 PNG 图像,如下所示:

【讨论】:

  • 再次感谢 Martijn。如果这是真正的代码,你会把它保留为 f.read(28 * 28) 吗?对我来说似乎更清楚了。
  • 我会将值移动到一个常量,但使用28 * 28; Python 在编译时优化文字算术并存储乘法的结果。
猜你喜欢
  • 2014-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-13
  • 2015-04-07
  • 1970-01-01
  • 2016-12-21
  • 1970-01-01
相关资源
最近更新 更多