python 从PIL获取像素值列表

k4ymrczo  于 2022-12-21  发布在  Python
关注(0)|答案(9)|浏览(126)

我正在尝试将一个白色.jpg图像转换成一个列表,然后我可以将其调制成音频信号。
我已经导入了PIL模块,并尝试调用内置函数:list(im.getdata()) .当我调用它的时候,python崩溃了。有没有什么方法可以把图像(总是320x240)分解成240行来使计算更容易?或者我只是调用了错误的函数?

ozxc1zmp

ozxc1zmp1#

当你调用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)]
czfnxgou

czfnxgou2#

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

data = numpy.asarray(im)

(我在这里说“尝试”,是因为不清楚为什么getdata()不适合您,也不知道asarray是否使用getdata,但值得一试。)

cigdeys3

cigdeys33#

我假设您会得到类似.. 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)
cuxqih21

cuxqih214#

或者如果你想计算白色或黑色像素
这也是一个解决方案:

from PIL import Image
import operator

img = Image.open("your_file.png").convert('1')
black, white = img.getcolors()

print black[0]
print white[0]
jexiocij

jexiocij5#

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)]
wqlqzqxt

wqlqzqxt6#

不是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
i34xakig

i34xakig7#

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)
ldfqzlk8

ldfqzlk88#

正如我上面所评论的,问题似乎是从PIL内部列表格式到标准python列表类型的转换。我发现Image.tostring()要快得多,并且根据您的需要,它可能已经足够了。在我的情况下,我需要计算图像数据的CRC32摘要,它非常适合。
如果需要执行更复杂的计算,那么可能需要包含numpy的tom10响应。

to94eoyn

to94eoyn9#

看起来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

相关问题