【问题标题】:How to convert a grayscale image into a list of pixel values?如何将灰度图像转换为像素值列表?
【发布时间】:2017-04-05 07:09:12
【问题描述】:

我正在尝试创建一个 python 程序,它采用灰度、24*24 像素图像文件(我还没有决定类型,所以欢迎提出建议)并将其转换为从 0 开始的像素值列表(白色) 到 255(黑色)。

我打算用这个数组来创建一个类似MNIST的图片字节文件,可以被Tensor-Flow手写识别算法识别。

我发现Pillow library 在这项任务中最有用,它遍历每个像素并将其值附加到数组中

from PIL import Image

img = Image.open('eggs.png').convert('1')
rawData = img.load()
data = []
for y in range(24):
    for x in range(24):
        data.append(rawData[x,y])

然而这个解决方案有两个问题:

  1. 像素值不存储为整数,而是像素对象,无法进一步进行数学操作,因此无用。
  2. 即使Pillow docs 声明:

    访问单个像素相当慢。如果您要遍历图像中的所有像素,则可能有更快的方法使用 Pillow API 的其他部分。

【问题讨论】:

  • 当我在我的机器上运行你的代码时,data 是一个常规整数列表。
  • 文档可能指的是getdata,我希望它比逐像素访问更快。
  • 我不知道有任何 Python 库在单个像素访问方面并不慢。

标签: python image python-imaging-library mnist


【解决方案1】:

您可以通过访问 r、g 或 b 值来访问每个单独像素的灰度值,这对于灰度图像都是相同的。

img = Image.open('eggs.png').convert('1')
rawData = img.load()
data = []
for y in range(24):
    for x in range(24):
        data.append(rawData[x,y][0])

这并不能解决访问速度的问题。

我比 Pillow 更熟悉 scikit-image。在我看来,如果您所追求的只是列出灰度值,您可以使用 scikit-image,它将图像存储为 numpy 数组,并使用 img_as_ubyte 将图像表示为 uint 数组,包含 0 到 255 之间的值。

Images are NumPy Arrays 提供了一个很好的起点来查看代码的样子。

【讨论】:

  • 您所说的关于访问图像中单个像素的内容在将图像转换为模式'1' 后不适用,并且您当前的代码将导致rawData[x,y][0] 中的TypeError: 'int' object is not subscriptable最后一行。 rawData 中的值都是0255 的单个整数值。
【解决方案2】:

您可以将图像数据转换为 Python 列表(或列表列表),如下所示:

from PIL import Image

img = Image.open('eggs.png').convert('L')  # convert image to 8-bit grayscale
WIDTH, HEIGHT = img.size

data = list(img.getdata()) # convert image data to a list of integers
# convert that to 2D list (list of lists of integers)
data = [data[offset:offset+WIDTH] for offset in range(0, WIDTH*HEIGHT, WIDTH)]

# At this point the image's pixels are all in memory and can be accessed
# individually using data[row][col].

# For example:
for row in data:
    print(' '.join('{:3}'.format(value) for value in row))

# Here's another more compact representation.
chars = '@%#*+=-:. '  # Change as desired.
scale = (len(chars)-1)/255.
print()
for row in data:
    print(' '.join(chars[int(value*scale)] for value in row))

这是我用于测试的 24x24 RGB eggs.png 小图像的放大版:

这是第一个访问示例的输出:

这里是第二个例子的输出:

@ @ % * @ @ @ @ % - . * @ @ @ @ @ @ @ @ @ @ @ @
@ @ .   . + @ # .     = @ @ @ @ @ @ @ @ @ @ @ @
@ *             . .   * @ @ @ @ @ @ @ @ @ @ @ @
@ #     . .   . .     + % % @ @ @ @ # = @ @ @ @
@ %       . : - - - :       % @ % :     # @ @ @
@ #     . = = - - - = - . . = =         % @ @ @
@ =     - = : - - : - = . .     . : .   % @ @ @
%     . = - - - - : - = .   . - = = =   - @ @ @
=   .   - = - : : = + - : . - = - : - =   : * %
-   .   . - = + = - .   . - = : - - - = .     -
=   . : : . - - .       : = - - - - - = .   . %
%   : : .     . : - - . : = - - - : = :     # @
@ # :   .   . = = - - = . = + - - = - .   . @ @
@ @ #     . - = : - : = - . - = = : . .     # @
@ @ %     : = - - - : = -     : -   . . .   - @
@ @ *     : = : - - - = .   . - .   .     . + @
@ #       . = - : - = :     : :   .   - % @ @ @
*     . . . : = = - : . .   - .     - @ @ @ @ @
*   . .       . : .   . .   - = . = @ @ @ @ @ @
@ :     - -       . . . .     # @ @ @ @ @ @ @ @
@ @ = # @ @ *     . .     . - @ @ @ @ @ @ @ @ @
@ @ @ @ @ @ @ .   .   . # @ @ @ @ @ @ @ @ @ @ @
@ @ @ @ @ @ @ -     . % @ @ @ @ @ @ @ @ @ @ @ @
@ @ @ @ @ @ @ # . : % @ @ @ @ @ @ @ @ @ @ @ @ @

现在访问像素数据应该比使用对象 img.load() 返回更快(并且值将是 0..255 范围内的整数)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-28
    • 2013-06-11
    • 1970-01-01
    • 1970-01-01
    • 2011-12-15
    • 2010-11-20
    相关资源
    最近更新 更多