从 PIL 获取像素值列表
Posted
技术标签:
【中文标题】从 PIL 获取像素值列表【英文标题】:Getting list of pixel values from PIL 【发布时间】:2009-07-10 13:08:07 【问题描述】:各位,我正在寻求帮助。我是一名新手程序员,我现在遇到的一个问题是尝试将黑白.jpg
图像转换为一个列表,然后我可以将其调制为音频信号。这是创建 python SSTV 程序的大型项目的一部分。
我已导入 PIL 模块并尝试调用内置函数:list(im.getdata())
。当我调用它时,python 崩溃了。是否有某种方法可以将图像(始终为 320x240)分解为 240 行以使计算更容易?还是我只是调用了错误的函数。
如果有人有任何建议,请开火。如果有人有使用 python 生成调制音频的经验,我很乐意接受他们愿意传授的任何“智慧之珠”。 提前致谢
【问题讨论】:
包含您在崩溃时收到的消息会非常有帮助 【参考方案1】:调用 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)]
【讨论】:
list(im.getdata())
。当我调用它时,python 崩溃了。
当我调用 list(im.getdata()) 时,不仅 python 崩溃(大概),而且我的整个 linux 系统都变得无响应。硬重启解决了这个问题。
问题似乎是转换为标准 python 列表。如果我只调用pixels=im.getdata()
(它返回一个特殊的、简化的列表类型),一切都很好。但是,如果我添加演员表,python 开始使用大量 RAM,如果没有足够的可用 PC 开始交换并最终崩溃。也许使用 python 列表来保存几百万个像素值有点过头了。
您能添加以下几行吗? import Image; im = Image.open('um_000000.png')
谢谢。我没有崩溃问题,但我为其他想要一个 numpy 数组的人提供了以下补充:pixels = np.array(im.getdata()).reshape((im.size[1], im.size[0]))
【参考方案2】:
如果你安装了numpy,你可以试试:
data = numpy.asarray(im)
(我在这里说“尝试”,因为不清楚为什么getdata()
不适合你,我不知道asarray
是否使用getdata,但值得一试。)
【讨论】:
【参考方案3】:我假设您收到类似..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)
这会将每个像素附加到all_pixels
- 如果文件是 RGB 图像(即使它只包含黑白图像),这些将是一个元组,例如:
(255, 255, 255)
要将图像转换为单色,只需平均三个值 - 所以,最后三行代码将变为..
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)
或者获取亮度(加权平均):
cpixel = pixels[x, y]
luma = (0.3 * cpixel[0]) + (0.59 * cpixel[1]) + (0.11 * cpixel[2])
all_pixels.append(luma)
或纯 1 位的黑白:
cpixel = pixels[x, y]
if round(sum(cpixel)) / float(len(cpixel)) > 127:
all_pixels.append(255)
else:
all_pixels.append(0)
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)
【讨论】:
【参考方案4】:不是 PIL,但 scipy.misc.imread
可能仍然很有趣:
import scipy.misc
im = scipy.misc.imread('um_000000.png', flatten=False, mode='RGB')
print(im.shape)
给予
(480, 640, 3)
就是这样(高度、宽度、通道)。所以你可以通过
迭代它for y in range(im.shape[0]):
for x in range(im.shape[1]):
color = tuple(im[y][x])
r, g, b = color
【讨论】:
scipy.misc.imread
现已弃用,请使用import imageio im=imageio.imread('sogreche.jpg')
【参考方案5】:
或者如果你想计算白色或黑色像素
这也是一种解决方案:
from PIL import Image
import operator
img = Image.open("your_file.png").convert('1')
black, white = img.getcolors()
print black[0]
print white[0]
【讨论】:
【参考方案6】:data = numpy.asarray(im)
注意:在 PIL 中,img 是 RGBA。在cv2中,img是BGRA。
我的强大解决方案:
def cv_from_pil_img(pil_img):
assert pil_img.mode=="RGBA"
return cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGBA2BGRA)
【讨论】:
【参考方案7】:pixVals = list(pilImg.getdata())
输出是图片中所有 RGB 值的列表:
[(248, 246, 247), (246, 248, 247), (244, 248, 247), (244, 248, 247), (246, 248, 247), (248, 246, 247), (250, 246, 247), (251, 245, 247), (253, 244, 247), (254, 243, 247)]
【讨论】:
【参考方案8】:正如我在上面评论的,问题似乎是从 PIL 内部列表格式到标准 python 列表类型的转换。我发现 Image.tostring() 更快,根据您的需要,它可能就足够了。在我的例子中,我需要计算图像数据的 CRC32 摘要,它非常适合。
如果您需要执行更复杂的计算,可能需要涉及 numpy 的 tom10 响应。
【讨论】:
【参考方案9】:看起来 PILlow 可能已将 tostring()
更改为 tobytes()
。在尝试提取 RGBA 像素以将它们放入 OpenGL 纹理时,以下方法对我有用(在 glTexImage2D
调用中,为简洁起见,我省略了)。
from PIL import Image
img = Image.open("mandrill.png").rotate(180).transpose(Image.FLIP_LEFT_RIGHT)
# use img.convert("RGBA").tobytes() as texels
【讨论】:
以上是关于从 PIL 获取像素值列表的主要内容,如果未能解决你的问题,请参考以下文章