使用缓冲区协议,用C语言实现的Python对象有一个所谓的“缓冲区接口”。无需复制,此类Python对象允许其他对象直接访问它们的数据成员。缓冲区协议使我们能方便地在NumPy和其他Python软件(例如Python图像库PIL)之间交换信息。我们来看一个直接把NumPy数组保存为PIL图像的例子。
准备工作
如有必要,请先安装PIL和SciPy。
具体步骤
首先,我们需要一个操作对象——NumPy数组。
- 用图像数据创建一个数组。
在之前的章节中,我们已经介绍了怎样加载范例图像Lena。我们将创建一个用0填充的数组,并且把图像数据填充到alpha通道中。
lena = scipy.misc.lena()
data = numpy.zeros((lena.shape[0], lena.shape[1], 4), dtype=numpy.int8)
data[:,:,3] = lena.copy()
- 把数据保存为PIL图像。
我们现在使用PIL API,把数据保存为RGBA格式的图像。
img = Image.frombuffer("RGBA", lena.shape, data)
img.save('lena_frombuffer.png')
- 修改数组
data
并保存图像。
修改数组data
,删除图像数据,使图像显示为红色。用PIL API保存图像。
data[:,:,3] = 255
data[:,:,0] = 222
img.save('lena_modified.png')
下图是修改数组内容之前保存的图像。
由于使用了缓冲区接口,数组data
的改变会导致PIL图像对象的数据改变。因此,我们会看到如下图像。
本章的完整代码如下。
import numpy
import Image
import scipy.misc
lena = scipy.misc.lena()
data = numpy.zeros((lena.shape[0], lena.shape[1], 4), dtype=numpy.int8)
data[:,:,3] = lena.copy()
img = Image.frombuffer("RGBA", lena.shape, data)
img.save('lena_frombuffer.png')
data[:,:,3] = 255
data[:,:,0] = 222
img.save('lena_modified.png')
小结
我们从一个缓冲区——NumPy数组,创建了一个PIL图像。改变缓冲区内容后,我们看到图像对象也会相应发生改变。实现这些并不需要复制PIL图像对象。我们直接访问和修改NumPy数组,把一个模特的肖像变成了一个红色图像。