从PIL获取像素值列表

33 python image python-imaging-library

伙计们,我正在寻求一些帮助.我是一个新手程序员,我现在遇到的一个问题是尝试将黑白.jpg图像转换为列表,然后我可以将其调制为音频信号.这是创建python SSTV程序的大型项目的一部分.

我导入了PIL模块,并尝试调用内置函数:list(im.getdata()).当我调用它时,python崩溃了.有没有办法将图像(总是320x240)分解为240行,以使计算更容易?或者我只是调用了错误的功能.

如果有人有任何建议请开火.如果有人有使用python生成调制音频音调的经验,我很乐意接受他们愿意传授的任何"智慧珍珠".提前致谢

Nad*_*mli 60

调用getdata()时,Python不应该崩溃.图像可能已损坏或PIL安装有问题.尝试使用其他图像或发布您正在使用的图像.

这应该按照您想要的方式分解图像:

from PIL import Image
im = Image.open('um_000000.png')

pixels = list(im.getdata())
width, height = im.size
pixels = [pixels[i * width:(i + 1) * width] for i in xrange(height)]
Run Code Online (Sandbox Code Playgroud)

  • *`名单(im.getdata())`.当我调用它时,python崩溃.* (7认同)
  • 当我调用 list(im.getdata()) 时,不仅 python 崩溃(大概),而且我的整个 Linux 系统变得无响应。硬重启解决了这个问题。 (2认同)
  • 问题似乎是转换为标准 python 列表。如果我只调用`pixels=im.getdata()`(它返回一个特殊的、简化的列表类型),一切都很好。但是,如果我添加演员表,python 开始使用大量 RAM,如果没有足够的可用 PC 开始交换并最终崩溃。也许使用 python 列表来保存几百万像素值有点大材小用了。 (2认同)
  • 谢谢你 我没有崩溃的问题,但我为其他希望使用numpy数组的人提供了以下补充:`pixels = np.array(im.getdata())。reshape((im.size [1],im.size [0] ))` (2认同)

tom*_*m10 35

如果您安装了numpy,可以尝试:

data = numpy.asarray(im)
Run Code Online (Sandbox Code Playgroud)

(我在这里说"试试",因为不清楚为什么getdata()不适合你,我不知道是否asarray使用了getdata,但是值得一试.)


dbr*_*dbr 15

我猜你得到的错误就像.. TypeError: 'PixelAccess' object is not iterable...?

有关如何访问像素,请参阅Image.load文档.

基本上,要获取图像中的像素列表,请使用PIL:

from PIL import Image
i = Image.open("myfile.png")

pixels = i.load() # this is not a list, nor is it list()'able
width, height = i.size

all_pixels = []
for x in range(width):
    for y in range(height):
        cpixel = pixels[x, y]
        all_pixels.append(cpixel)
Run Code Online (Sandbox Code Playgroud)

将每个像素附加到all_pixels- 如果文件是RGB图像(即使它只包含黑白图像),这些将是一个元组,例如:

(255, 255, 255)
Run Code Online (Sandbox Code Playgroud)

要将图像转换为单色,您只需平均三个值 - 因此,最后三行代码将变为..

cpixel = pixels[x, y]
bw_value = int(round(sum(cpixel) / float(len(cpixel))))
# the above could probably be bw_value = sum(cpixel)/len(cpixel)
all_pixels.append(bw_value)
Run Code Online (Sandbox Code Playgroud)

或者获得亮度(加权平均值):

cpixel = pixels[x, y]
luma = (0.3 * cpixel[0]) + (0.59 * cpixel[1]) + (0.11 * cpixel[2])
all_pixels.append(luma)
Run Code Online (Sandbox Code Playgroud)

或纯粹的1位黑白色:

cpixel = pixels[x, y]
if round(sum(cpixel)) / float(len(cpixel)) > 127:
    all_pixels.append(255)
else:
    all_pixels.append(0)
Run Code Online (Sandbox Code Playgroud)

PIL中可能有一些方法可以RGB -> BW更快地进行此类转换,但这种方法很有效,并且速度不是特别慢.

如果您只想对每一行执行计算,则可以跳过将所有像素添加到中间列表中.例如,要计算每行的平均值:

from PIL import Image
i = Image.open("myfile.png")

pixels = i.load() # this is not a list
width, height = i.size
row_averages = []
for y in range(height):
    cur_row_ttl = 0
    for x in range(width):
        cur_pixel = pixels[x, y]
        cur_pixel_mono = sum(cur_pixel) / len(cur_pixel)
        cur_row_ttl += cur_pixel_mono

    cur_row_avg = cur_row_ttl / width
    row_averages.append(cur_row_avg)

print "Brighest row:",
print max(row_averages)
Run Code Online (Sandbox Code Playgroud)