A-A+

PIL Image使用方法详解

2020年05月20日 23:57 汪洋大海 暂无评论 共5343字 (阅读1,608 views次)

使用Image类

PIL中最重要的类是Image类,可以通过多种方法创建这个类的实例。可以从文件加载图像,或者处理其他图像,或者从scratch创建。

要从文件加载图像,可使用Image模块的open()函数:

1
2
>>> from PIL import Image
>>> im = Image.open('lena.jpg')

示例用的图片如下:

PIL Image使用方法详解

加载成功将返回一个Image对象。可以使用如下命令检查文件内容:

1
2
3
4
>>> print im
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=500x750 at 0x10B9E3890>
>>> print(im.format, im.size, im.mode)
('JPEG', (500, 750), 'RGB')

format这个属性标识了图像来源。如果图像不是从文件读取那它的值为None。size属性是一个二元tuple,包含width和height(单位px)。mode属性定义了图像bands的数量和名称,以及像素类型和深度。常见的modes有“L”(luminance)表示灰度图像,“RGB”表示真彩色图像,“CMYK”表示出版图像。

如果文件打开错误,则返回IOError错误。

只要有了Image类的实例,就可以通过类的方法处理图像。比如下面的方法可以用来显示图像:

1
>>> im.show()
注解:标准的show()效率不高,它需要保存图像到临时文件然后通过xv显示图像。

读写图像

PIL模块支持大量图片格式。使用在Image模块的open()函数从磁盘读取文件。不需要知道文件格式就能打开它,这个库能够根据文件内容自动确定文件格式。

要保存文件,使用Image类的save()方法。保存文件时文件名变得重要了。除非指定格式,否则这个库将会以文件名的扩展名作为格式保存。

创建略缩图

1
2
3
4
5
6
7
8
>>> from PIL import Image
>>> im = Image.open('lena.jpg')
>>> print im.size
(500, 750)
>>> size = (250, 375)
>>> im.thumbnail(size)
>>> print im.size
(250, 375)

使用thumbnail()方法需要注意的是,指定的size应当比原尺寸小,且转换后的图片比例与原图片比例相同。

保存图片

继续执行下述步骤,将转换后的图片保存:

1
>>> im.save('lena_thumbnail.jpg', 'JPEG')

剪切、粘贴、合并图像

Image类包含的方法允许操作图像部分选区,使用Image.crop()方法获取图像的一个子矩形选区。

从图像中复制出一个矩形选区

1
2
3
4
5
>>> print im.size
(500, 750)
>>> box = (100, 100, 400, 400)
>>> region = im.crop(box)
>>> region.show()

矩形选区有一个四元元组定义,分别表示左上、右下的坐标。这个库以左上角为坐标原点,单位是px,所以上述代码复制了一个 300x300 pixels 的矩形选区。这个选区现在可以被处理并且粘贴到原图。

剪下来的 300x300px 图片如下所示:

PIL Image使用方法详解

处理复制的矩形选区并粘贴到原图

继续上面的步骤:

1
2
3
>>> region = region.transpose(Image.ROTATE_180)
>>> im.paste(region, box)
>>> im.show()

当粘贴矩形选区的时候必须保证尺寸一致。此外,矩形选区不能在图像外。然而不必保证矩形选区和原图的颜色模式一致,因为矩形选区会被自动转换颜色。

效果图如下:

PIL Image使用方法详解

分离和合并颜色通道

由于上面例子已经对im进行了改变,我们重新将im指向原图片:

1
2
>>> im = Image.open('lena.jpg')
>>> r, g, b = im.split()

如果是单色通道的图片,使用split()之后会返回图片本身。你可以使用r.show()来查看分离颜色通道后的图片。

PIL Image使用方法详解

将分离的颜色合并为RGB可用merge()方法:

1
2
>>> img = Image.merge('RGB', (b, g, r))
>>> img.show()

以b,g,r顺序合并成的图片如图所示:

PIL Image使用方法详解

几何变换

PIL.Image.Image类包含了设置图像大小resize()和旋转图像rotate()的方法。resize()接收一个元组来指定新大小。rotate()接收一个逆时针的角度值。

简单的几何变换

1
2
3
4
5
6
>> print im.size
(500, 750)
>>> im_resize = im.resize((250, 250))
>>> im_resize.show()
>>> im_rotate = im.rotate(45)
>>> im_rotate.show()

im_resize.show()效果图如下:

PIL Image使用方法详解

im_rotate.show()效果图如下:

PIL Image使用方法详解

旋转图像

如果要将图片旋转90°的整数倍,可以使用rotate()方法或者transpose()方法。transpose()还可以将图片按照其竖直或水平边缘翻转,由于图片过多不一一展示。

1
2
3
4
5
out = im.transpose(Image.FLIP_LEFT_RIGHT)
out = im.transpose(Image.FLIP_TOP_BOTTOM)
out = im.transpose(Image.ROTATE_90)
out = im.transpose(Image.ROTATE_180)
out = im.transpose(Image.ROTATE_270)

使用transpose(ROTATE)rotate()是没有区别的。更普遍的方法是使用transform()方法。

颜色变换

Python Imaging Library可以使用convert()方法来实现像素的变换。

颜色模式转换

1
>>> im.convert('L').show()

PIL库支持各种不同模式之间的转换,比如“L”和“RGB”模式。为了转成其他的模式,需要用一张中间模式图像,典型的为RGB图片。

颜色增强

PIL库提供了许多方法和模块可以用来增强图像

过滤器

ImageFilter模块包含了许多预定义的增强过滤器,通过filter方法调用。

1
2
>>> from PIL import ImageFilter
>>> out = im.filter(ImageFilter.DETAIL)

点操作

point()方法能够用来实现图片像素值的转换(比如图像对比度处理)。在大多数情况下,point()方法接收一个函数体作为参数,每一个像素都根据此函数处理:

1
>>> out = im.point(lambda i: i * 1.2)

效果图如下,相比原图有增强:

PIL Image使用方法详解

处理个别bands:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# split the image into individual bands
source = im.split()
R, G, B = 0, 1, 2
# select regions where red is less than 100
mask = source[R].point(lambda i: i < 100 and 255)
# process the green band
out = source[G].point(lambda i: i * 0.7)
# paste the processed band back, but only where red was < 100
source[G].paste(out, None, mask)
# build a new multiband image
im = Image.merge(im.mode, source)

效果和原图差异不大,就不上图了。需要注意的是这个语法:

1
imout = im.point(lambda i: expression and 255)

如果expression的值为false/0,则and之后的不再检查,直接返回0。如果expression的值为true/非0,判断and之后的表达式,并返回最后一个检查的值,语句返回255。

增强

要使用更多先进的图片增强功能,可以使用模块ImageEnhance中的类。你可以通过它调整对比度、亮度、颜色平衡度和尖锐度。

1
2
3
4
from PIL import ImageEnhance
enh = ImageEnhance.Contrast(im)
enh.enhance(0.5).show("50% less contrast")

对比度降低50%后效果如下:

PIL Image使用方法详解

多帧图像序列

PIL支持图像序列(动画格式)。支持的序列格式包括FLI/FLC,GIF等。TIFF文件也能包含许多帧。打开一个序列文件时,PIL自动装载序列的第一帧。你可以使用函数来移动帧。参考图片如下:

PIL Image使用方法详解

读取序列

1
2
3
4
5
6
7
8
9
10
11
from PIL import Image
im = Image.open("niko.gif")
im.seek(0) # 跳到第一帧
try:
while 1:
im.seek(im.tell()+1) # 跳到下一帧,tell()方法返回目前的帧序号
im.show()
except EOFError:
pass

以前的PIL库只允许seek到下一帧,如果要倒回去需要重新打开。而现在的PIL库你可以seek到任意帧。

序列迭代类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from PIL import Image
class ImageSequence:
def __init__(self, im):
self.im = im
def __getitem__(self, ix):
try:
if ix:
self.im.seek(ix)
return self.im
except EOFError:
raise IndexError
im = Image.open('niko.gif')
for frame in ImageSequence(im):
frame.show()

更多关于读取图像

Image.open()方法是用来打开一个图片文件的。大多数情况下可以简单的将图像文件名作参数传入:

1
im = Image.open('lena.jpg')

正常返回结果是一个PIL.Image.Image实例。否则会抛出IOError错误。

你可以传入一个类文件代替文件名。这个类文件必须实现read()seek()tell()方法,并且以二进制模式打开。

从文件读取

1
2
>>> fp = open('lena.jpg', 'rb')
>>> im = Image.open(fp)

从string读取

1
2
3
4
5
6
7
8
>>> import urllib2
>>> import StringIO
>>> from PIL import Image
>>> headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'}
>>> req = urllib2.Request('http://tupian.enterdesk.com/2014/mxy/06/19/1/8.jpg', headers=headers)
>>> buffer = urllib2.urlopen(req).read()
>>> im = Image.open(StringIO.StringIO(buffer))
>>> im.show()

使用的示例图片如下:

PIL Image使用方法详解

从压缩包读取

为示范,先将一些文件例如”lena.jpg”和”niko.gif”打包,压缩包名假设为”Imaging.tar”。从压缩包中读取”lena.jpg”可使用TarIO.TarIO()方法获取图片,并交由Image.open()处理。(Linux/Unix系统下可以简单使用tar -cvf Imaging.tar lena.jpg niko.gif 打包为tar压缩格式)

1
2
3
>>> from PIL import Image, TarIO
>>> fp = TarIO.TarIO('Imaging.tar', 'lena.jpg')
>>> im = Image.open(fp)

注意:对zip压缩包进行操作时可能会出现解码错误。

控制解码器

部分解码器支持在读取图片文件的时候对图像进行处理,常用于创建略缩图时加速解码速度(当速度比质量重要时)和传输给单色激光打印机时()。draft()方法可以在图像尚未加载完时对其进行处理,所以给定的模式和大小尽可能的匹配。这是通过重新配置图像解码器完成的。

在草稿模式读取

1
2
3
4
5
>>> from PIL import Image
>>> im = Image.open(file)
>>> print("original =", im.mode, im.size)
>>> im.draft("L", (100, 100))
>>> print("draft =", im.mode, im.size)

输出结果:

1
2
original= RGB (500, 750)
draft= L (125, 188)

注意得到的图片可能不会完全的匹配给定的模式和大小。为了保证图像不比给定的大小大,使用im.thumbnail()方法来代替。

布施恩德可便相知重

微信扫一扫打赏

支付宝扫一扫打赏

×

给我留言