PIL - 对每个像素应用相同的操作

时间:2016-06-16 15:54:15

标签: python python-imaging-library

我创建一个图像并填充像素:

AccountId

这可以做得更优雅(也可能更快,因为理论上循环可以并行化)?

1 个答案:

答案 0 :(得分:3)

注意:我将首先回答这个问题,然后在我看来提出一个更好的选择

回答问题

很难在不知道您打算应用哪些更改的情况下提供建议,以及将图像作为PIL图像加载是问题还是给定的一部分。

  • 更优雅的Python语言通常意味着使用列表推导
  • 对于并行化,您会看到类似multiprocessing模块或joblib
  • 的内容

根据您在图片中创建/加载的方法,您可能会对list_of_pixels = list(img.getdata())img.putdata(new_list_of_pixels)函数感兴趣。

这可能是一个例子:

from PIL import Image
from multiprocessing import Pool

img = Image.new( 'RGB', (2000,2000), "black")

# a function that fixes the green component of a pixel to the value 50
def update_pixel(p):
    return (p[0], 50, p[2])

list_of_pixels = list(img.getdata())
pool = Pool(4)
new_list_of_pixels = pool.map(update_pixel, list_of_pixels)
pool.close()
pool.join()
img.putdata(new_list_of_pixels)

但是,我认为这不是一个好主意...当你看到Python中的数千个元素的循环(和列表推导)并且你有你的想法,你可以肯定有一个库,会让这更快。

更好的选择

首先,指向Channel Operations module的快速指针, 既然你没有指定你打算做的像素操作的类型,而且你已经清楚地知道了PIL库,我会假设你已经意识到它并且它没有按照你想要的那样做。

然后,Python中任何适度复杂的矩阵操作都会受益于引入PandasNumpyScipy ......

纯粹的numpy例子:

import numpy as np
import matplotlib.pyplot as plt
#black image
img = np.zeros([100,100,3],dtype=np.uint8)
#show
plt.imshow(img)
#make it green
img[:,:, 1] = 50
#show
plt.imshow(img)

由于您只是使用标准的numpy.ndarray,您可以使用任何可用的功能,例如np.vectorize,apply,map等。使用update_pixel函数显示与上面类似的解决方案:

import numpy as np
import matplotlib.pyplot as plt
#black image
img = np.zeros([100,100,3],dtype=np.uint8)
#show
plt.imshow(img)
#make it green
def update_pixel(p):
    return (p[0], 50, p[2])
green_img = np.apply_along_axis(update_pixel, 2, img)
#show
plt.imshow(green_img)

再举一个例子,这次直接从索引计算图像内容,而不是从现有的图像像素内容计算(不需要先创建空图像):

import numpy as np
import matplotlib.pyplot as plt

def calc_pixel(x,y):
    return np.array([100-x, x+y, 100-y])

img = np.frompyfunc(calc_pixel, 2, 1).outer(np.arange(100), np.arange(100))    
plt.imshow(np.array(img.tolist()))
#note: I don't know any other way to convert a 2D array of arrays to a 3D array...

而且,低,看,scipy有读取和写入图像的方法,你可以使用numpy来操作它们作为“经典”的多维数组。 (顺便说一下,scipy.misc.imread取决于PIL)

More example code.