使用PIL从图像获取像素

时间:2019-01-21 12:05:49

标签: python python-imaging-library bmp

我想编写一个脚本,该脚本读取bmp文件,然后记录x-y轴上的像素,其中图像是白色以外的颜色。然后将这些数据保存到.txt文件中。

我已经开始使用Pillow库,但是还没有找到解决该问题的方法。我用Pillow打开了bmp文件,并尝试使用Image中的模块,但是找不到如何使之工作。

谢谢!

2 个答案:

答案 0 :(得分:1)

您可以使用Image.getpixel()从PIL读取像素。

下面的代码将以二维列表的形式为您提供所有非白色像素。

from PIL import Image

im = Image.open('x.bmp')

imageSizeW, imageSizeH = im.size

nonWhitePixels = []

for i in range(1, imageSizeW):
    for j in range(1, imageSizeH):
        pixVal = im.getpixel((i, j))
        if pixVal != (255, 255, 255):
            nonWhitePixels.append([i, j])

print(nonWhitePixels)

答案 1 :(得分:1)

编辑: 刚刚意识到,问题在于要找到与白色不同的所有像素的索引...
对于这种情况,只需用其补数函数替换布尔数组的计算即可:

white = (img[:, :, :3] != 255).any(2)

只需在~中的布尔数组前面添加一个np.where

coords = np.array(np.where(~white))[::-1].T

测试结果将相反

enter image description here


在这里,我认为“使用PIL” 不是严格的要求,而只是您尝试开始的方式的标志。

也就是说,您可以使用imread中的imageio执行以下操作:

import numpy as np
from imageio import imread

img = imread(filename)
white = (img[:, :, :3] == 255).all(2)
coords = np.array(np.where(white))[::-1].T

写入ASCII文件的操作可以像

with open('xycoordinates.txt', 'w') as f:
    for c in coords:
        f.write(f'{c[0]},{c[1]}\n')

说明
img是形状为(nr, nc, c)的3D数组,即行数,列数和RGBA值。
img[:, :, :3] == 255返回一个形状与img相同的布尔数组,表示单个RGB值的分量匹配(不考虑A。如果A也应为255,则不使用完整的索引括号) 。
.all(2)通过仅将那些索引设置为(nr, nc)(将完整的RGBA数组与之匹配)将其缩小为形状为True的数组。

np.where(white)返回行和列索引的元组。
np.array()将其强制转换为numpy数组,以便对其应用numpy索引和转换。
由于row/columnx/y命名法的顺序相反,因此[::-1]颠倒了两个索引数组的顺序。 通过.T进行的转换不会输出n个索引的两个数组(xy),而是输出(x, y)个索引的n个数组。

示例

img = imread(samplefile)
plt.imshow(img)

enter image description here

white = (img == [255, 255, 255, 255]).all(2)

array([[False, False,  True, False, False, False],
       [False, False,  True,  True, False, False],
       [False,  True, False, False, False, False],
       [ True,  True, False, False, False, False],
       [False, False, False, False, False,  True]])

coords = np.array(np.where(white))[::-1].T

array([[2, 0],
       [2, 1],
       [3, 1],
       [1, 2],
       [0, 3],
       [1, 3],
       [5, 4]], dtype=int64)

plt.plot(*coords.T, 'ro')

enter image description here