Pillow 是一个第三方 Python 模块,用于处理图像文件。该模块包含一些函数,可以很容易地裁剪图像、调整图像大小,以及编辑图像的内容。

1. 计算机图像基础

1.1 RGBA

计算机程序通常将图像中的颜色表示为 RGBA 值。 RGBA 值是一组数字,指定顔色中的红、绿、蓝和 alpha(透明度)的值。
在 Pillow 中, RGBA 值表示为四个整数值的元组。例如,红色表示为(255,0, 0, 255)。同时,pillow也使用标准的颜色名称代替常见颜色的RGBA值:

名称 RGBA值
White (255, 255, 255, 255)
Red (255, 0, 0, 255)
Green (0, 128, 0, 255)
Blue (0, 0, 255, 255)
Gray (128, 128, 128, 255)
Yellow (255, 255, 0, 255)
Black (0, 0, 0, 255)
Purple (128, 0, 128, 255)

1.2 坐标和box元组

图像像素用 x 和 y 坐标指定,分别指定像素在图像中的水平和垂直位置。原点是位于图像左上角的像素,用符号(0, 0)指定。第一个 0 表示 x 坐标,它以原点处为 0,从左至右增加。第二个 0 表示 y 坐标,它以原点处为 0,从上至下增加。

许多 Pillow 函数和方法需要一个矩形元组参数。这意味着 Pillow 需要一个四个整坐标的元组,表示图像中的一个矩形区域。四个整数按顺序分别是:

  • 左:该矩形的最左边的 x 坐标。
  • 顶:该矩形的顶边的 y 坐标
  • 右:该矩形的最右边右面一个像素的 x 坐标。此整数必须比左边整数大
  • 底:该矩形的底边下面一个像素的 y 坐标。此整数必须比顶边整数大。

2. Pillow图像处理

2.1 加载图像和Image对象

要加载图像,就从 Pillow 导入 Image 模块,并调用 Image.open(),传入图像的文件名。
通过 save()方法,对 Image 对象的所有更改都可以保存到图像文件中(也是任何格式)。所有的旋转、调整大小、裁剪、绘画和其他图像操作,都通过这个 Image 对象上的方法调用来完成。

  1. from PIL import Image
  2. cat = Image.open('media/cat.png') # 打开图像文件
  3. # 打印图像属性
  4. print(cat.size) # 宽,高元组
  5. print(cat.filename)
  6. print(cat.format)
  7. cat.save('media/cat.png')

Image.new()函数,它返回一个表示空白的Image对象,其参数有:

  • 字符串’RGBA’,将颜色模式设置为 RGBA(还有其他模式,但本书没有涉及)。
  • 大小,是两个整数元组,作为新图像的宽度和高度。
  • 图像开始采用的背景颜色,是一个表示 RGBA 值的四整数元组
  1. from PIL import Image
  2. im = Image.new('RGBA', (10,20), 'black')
  3. im.save('media/new.png')

2.2 裁剪图片

Image 对象的 crop()方法接受一个矩形元组,返回一个 Image 对象,表示裁剪后的图像。 裁剪不是在原图上发生的,也就是说,原始的 Image 对象原封不动, crop()方法返回一个新的 Image 对象。

  1. from PIL import Image
  2. cat = Image.open('media/cat.png')
  3. cropcat=cat.crop((335,345,565,560))
  4. cropcat.save('media/cropcat.png')

2.3 复制粘贴图像

copy()方法返回一个新的 Image 对象,它和原来的 Image 对象具有一样的图像。
paste()方法在 Image 对象调用,将另一个图像粘贴在它上面。

  1. # 复制粘贴图像
  2. copycat=cat.copy()
  3. copycat.paste(cropcat, (0,0))

2.4 调整图像大小

resize()方法在 Image 对象上调用,返回指定宽度和高度的一个新 Image 对象。它接受两个整数的元组作为参数,表示返回图像的新高度和宽度。

2.5 旋转和翻转

图像可以用 rotate()方法旋转,该方法返回旋转后的新 Image 对象,并保持原始 Image 对象不变。 rotate()的参数是一个整数或浮点数,表示图像逆时针旋转的度数。
利用 transpose()方法,还可以得到图像的“镜像翻转”。必须向transpose()方法传入 Image.FLIP_LEFT_RIGHT 或 Image.FLIP_TOP_BOTTOM表示水平翻转还是垂直翻转。

2.6 修改单个像素

通过 getpixel()和 putpixel()方法可以获取和修改单个像素。它们都接受一个元组,表示像素的 x 和 y 坐标。 putpixel()方法还接受一个元组,作为该像素的颜色。

  1. im.putpixel((x,y), (210, 210, 210))
  2. im.getpixel((0, 0))
  3. >>>(210, 210, 210, 255)

3. pillow绘图

将Image 对象传入 ImageDraw.Draw()函数,得到一个 ImageDraw 对象。这个对象有一些方法,可以在 Image 对象上绘制形状和文字。

3.1 绘制形状

下面的 ImageDraw 方法在图像上绘制各种形状。这些方法的 fill 和 outline 参数是可选的,如果未指定,默认为白色。

  • 点: point(xy, fill)方法绘制单个像素。 xy 参数表示要画的点的列表。该列表可以是 x 和 y 坐标的元组的列表,例如[(x, y), (x, y), …],或是没有元组的 x 和 y 坐标的列表,例如[x1, y1, x2, y2, …]。 fill 参数是点的颜色,要么是一个 RGBA 元组,要么是颜色名称的字符串。
  • 线: line(xy, fill, width)方法绘制一条线或一系列的线。 xy 要么是一个元组的列表,例如[(x, y), (x, y), …],要么是一个整数列表,例如[x1, y1, x2, y2, …]。每个点都是正在绘制的线上的一个连接点。可选的 width 参数是线的宽度,如果未指定,缺省值为 1
  • 矩形: rectangle(xy, fill, outline)方法绘制一个矩形。 xy 参数是一个矩形元组,形式为(left,top, right, bottom)。可选的 fill 参数是颜色,将填充该矩形的内部。可选的 outline 参数是矩形轮廓的颜色。
  • 椭圆: ellipse(xy, fill, outline)方法绘制一个椭圆。如果椭圆的宽度和高度一样,该方法将绘制一个圆。 xy 参数是一个矩形元组(left, top, right, bottom)。
  • 多边形: polygon(xy, fill, outline)方法绘制任意的多边形。 xy 参数是一个元组列表,例如 [(x, y), (x, y), …],或者是一个整数列表,例如[x1, y1, x2, y2, …],表示多边形边的连接点。最后一对坐标将自动连接到第一对坐标.

Example:

  1. from PIL import Image, ImageDraw
  2. im = Image.new('RGBA', (200, 200), 'white')
  3. draw = ImageDraw.Draw(im)
  4. draw.line([(0, 0), (199, 0), (199, 199), (0, 199), (0, 0)], fill='black')
  5. draw.rectangle((20, 30, 60, 60), fill='blue')
  6. draw.ellipse((120, 30, 160, 60), fill='red')
  7. draw.polygon(((57, 87), (79, 62), (94, 85), (120, 90), (103, 113)),fill='brown')
  8. im.save('media/drawing.png')

3.2 绘制文字

ImageDraw 对象text()方法,用于在图像上绘制文本。 text()方法有 4 个参数: xy、 text、 fill 和 font。

  • xy 参数是两个整数的元组,指定文本区域的左上角。
  • text 参数是想写入的文本字符串。
  • 可选参数 fill 是文本的颜色。
  • 可选参数 font 是一个 ImageFont 对象,用于设置文本的字体和大小。可以调用 ImageFont.truetype()函数,第一个参数是字符串,表示字体的 TrueType 文件;第二个参数是一个整数,表示字体大小。

Example:

  1. draw.text((20, 150), 'Hello', fill='purple')
  2. fontsFolder = 'FONT_FOLDER' # e.g. ‘/Library/Fonts’
  3. arialFont = ImageFont.truetype(os.path.join(fontsFolder,'arial.ttf'), 32)
  4. draw.text((100, 150), 'Howdy', fill='gray', font=arialFont)