使用 Pillow Python 库处理图像

使用 Pillow Python 库处理图像

许多应用程序都使用数字图像,因此通常需要处理所使用的图像。如果您使用 Python 构建应用程序,并且需要为其添加图像处理特性,那么您可以使用各种库。一些流行的是 OpenCV,scikit-image,Python 图像库和 Pillow。

我们不会争论这里哪个是最好的,它们都有自己的优点。这篇文章将集中在 Pillow,一个强大的库,提供了广泛的图像处理功能和简单易用。

Pillow 是 Python 图像库 (PIL) 的一个分支。PIL 是一个库,提供了几个标准的程序操作图像。它是一个强大的库,但是自2009年以来就没有更新过,并且不支持 Python 3。在此基础上,增加了更多的功能和对 Python 3的支持。它支持一系列图像文件格式,如 PNG、 JPEG、 PPM、 GIF、 TIFF 和 BMP。我们将看到如何使用这个库对图像执行各种操作,如裁剪、调整大小、向图像添加文本、旋转、灰度缩放等。

安装和项目设置

在安装 Pillow 前,你应注意以下事项:

  • Pillow 和 PIL 不能在同一个环境中共存,所以如果你已经安装了 PIL,在进行之前先卸载它。
  • 我们将在本文中使用目前稳定的 Pillow 版本 (撰写本文时为8.0.1版本)。这个版本需要 Python 3.6及以上版本。

我们在下面给出了如何安装 Pillow 的说明,但是最好先查看一下安装指南,以防稍后版本的 Pillow 需要先安装一些必要的库。

你可以使用 pip 安装 pillow,如下所示:

python3 -m pip install --upgrade pip
python3 -m pip install --upgrade Pillow

接下来,你可以下载我们将在文章中使用的图片(由 Unsplash 提供)。你也可以使用你自己的图片。

所有示例都假设所需的映像与运行的 python 脚本文件位于同一目录中。

The Image Object

Python 图像库中的一个关键类是 Image 类。它在 Image 模块中定义,并提供一个可以执行操作的 PIL 映像。可以通过几种方式创建此类的实例: 从文件加载图像、从头创建图像,或者处理其他图像的结果。

要从文件中加载图像,我们使用 Image 模块中的 open ()函数,将其传递到图像的路径。

from PIL import Image

image = Image.open('demo_image.jpg')

如果成功,上面的代码返回一个 Image 对象。如果打开文件时出现问题,则会引发 OSError 异常。

在获得 Image 对象之后,现在可以使用该类定义的方法和属性来处理和操作它。让我们从显示图像开始。可以通过对其调用 show ()方法来实现这一点。这将在外部查看器上显示图像(通常是 macOS 上的 Preview、 Unix 上的 xv 和 Windows 上的 Paint 程序)。

image.show()

您可以使用对象的属性获得关于图像的一些细节。

# The file format of the source file.
print(image.format) # Output: JPEG

# The pixel format used by the image. Typical values are "1", "L", "RGB", or "CMYK."
print(image.mode) # Output: RGB

# Image size, in pixels. The size is given as a 2-tuple (width, height).
print(image.size) # Output: (1920, 1280)

# Colour palette table, if any.
print(image.palette) # Output: None

有关 Image 类可以做什么的更多信息,请查看文档

改变图像类型

处理完图像后,可以使用 save ()方法将其保存到文件中,并传入用于标记图像文件的名称。保存图像时,可以指定与原始图像不同的扩展名,保存的图像将转换为指定的格式。

image = Image.open('demo_image.jpg')
image.save('new_image.png')

上面的代码创建了一个包含 demo _ Image.jpg 图像的 Image 对象,并将其保存到一个新文件 new _ Image.png 中。Pillow 看到文件扩展名已经被指定为 PNG,因此它在将其保存到文件之前将其转换为 PNG。可以提供第二个参数 save ()以显式指定文件格式。Save (‘ new _ image.PNG’,‘ PNG’) 将执行与前一次 save ()相同的操作。通常情况下,没有必要提供第二个参数,因为 Pillow 会决定文件的存储格式,但是如果你使用的是非标准的扩展,那么你应该总是用这种方式来指定文件的文件扩展名。

调整图片大小

若要调整图像的大小,可以对其调用 resize ()方法,并传入一个表示调整大小后的图像的宽度和高度的两个整数元组参数。该函数不修改使用的图像,而是返回具有新维度的另一个 Image。

image = Image.open('demo_image.jpg')
new_image = image.resize((400, 400))
new_image.save('image_400.jpg')

print(image.size) # Output: (1920, 1280)
print(new_image.size) # Output: (400, 400)

resize() 方法返回的图像的宽度和高度与传入的值完全匹配。这可能是您想要的,但有时您可能会发现此函数返回的图并不理想。这主要是因为这个函数没有考虑图像的纵横比,所以你可能最终得到的图像要么看起来拉伸了,要么看起来压扁了。

你可以从上面的代码中看到这个新创建的图片: image _ 400.jpg,它看起来有点水平压扁。

使用 Pillow Python 库处理图像

如果您想调整图像的大小并保持它们的长宽比,那么您应该使用 thumbnail ()函数来调整它们的大小。它还接受一个表示缩略图的最大宽度和最大高度的两个整数元组参数。

image = Image.open('demo_image.jpg')
image.thumbnail((400, 400))
image.save('image_thumbnail.jpg')

print(image.size) # Output: (400, 267)

在保持原始图像的长宽比的情况下,上面的图像将生成一个 400x267 的图像大小。正如你在下面看到的,这样可以得到一张更好看的图片。

使用 Pillow Python 库处理图像

Resize ()函数和 thumbnail()函数的另一个显著区别是,如果给定的参数大于原始图像,resize() 函数就会“炸毁”图像,而 thumbnail()函数则不会。例如,给定一个大小为400x200的图像,调整大小((1200,600))将创建一个大一些的图像1200x600; 因此,图像将失去一些清晰度,并可能比原来的模糊。另一方面,使用原始图像调用 thumbnail((1200,600)) 将导致图像保持其大小为400x200,因为宽度和高度都小于指定的最大宽度和高度。

裁剪图像

在裁剪图像时,选择并保留图像内部的矩形区域,同时删除区域外的其他所有内容。使用 Pillow 库,您可以使用 Image 类的 crop ()方法裁剪图像。该方法接受一个框元组,该元组定义被裁剪区域的位置和大小,并返回表示被裁剪图像的 Image 对象。这个盒子的坐标是(左,上,右,下)。被裁剪的部分包括左侧的列和上面的像素行,并且上升到(但不包括)右侧的列和底部的像素行。这最好用一个例子来解释。

image = Image.open('demo_image.jpg')
box = (200, 300, 700, 600)
cropped_image = image.crop(box)
cropped_image.save('cropped_image.jpg')

# Print size of cropped image
print(cropped_image.size) # Output: (500, 300)

这是最终的图像:

使用 Pillow Python 库处理图像

Python Imaging Library 使用了一个以左上角的(0,0)开头的坐标系。Box tuple 的前两个值指定裁剪框的左上角起始位置。第三个和第四个值分别指定从这个起始位置到右边和底部方向的距离(以像素为单位)。坐标指的是像素之间的位置,因此上面示例中的区域正好是 500x300 像素。

将图片粘贴到另一张图片上

Pillow 可以让你把一个图片粘贴到另一个上。一些例子中,这可能是有用的,在保护公开可用的图像,添加水印,图像的品牌,添加公司标志,在任何其他情况下,有必要合并两个图像。

粘贴是通过 paste ()函数完成的。这修改了 Image 对象,不像我们目前看到的其他处理函数,它们返回一个新的 Image 对象。因此,在执行粘贴之前,我们将首先复制演示图像,这样我们就可以使用未修改的图像继续执行其他示例。

image = Image.open('demo_image.jpg')
logo = Image.open('logo.png')
image_copy = image.copy()
position = ((image_copy.width - logo.width), (image_copy.height - logo.height))
image_copy.paste(logo, position)
image_copy.save('pasted_image.jpg')

在上面的代码中,我们加载了两个图像,unsplash _ 01.jpg 和 logo.png,然后用 copy ()复制前者。我们想粘贴的标志图像到复制的形象,我们希望它被放置在底部的右角。这将被计算并保存在一个元组中。元组可以是一个给出左上角的2元组、一个定义左、上、右和下像素坐标的4元组,或者是 None (与(0,0)相同)。然后,我们将这个元组与要粘贴的图像一起传递到 paste ()。

你可以看到下面的结果。

使用 Pillow Python 库处理图像

这不是我们所期待的结果。

默认情况下,当您执行粘贴时,透明像素被粘贴为实心像素,因此围绕标志的黑色(白色)框。大多数时候,这并不是你想要的。你不能让你的水印覆盖底层图像的内容。我们宁愿让透明像素呈现出这样的效果。

要实现这一点,您需要向 paste ()函数传入第三个参数。这个参数是透明遮罩 Image 对象。mask 是一个 Image 对象,其 alpha 值很重要,但是它的绿色、红色和蓝色值会被忽略。如果给定了mask,则 paste ()只更新 mask 指示的区域。您可以使用1、 L 或 RGBA 图像作为 mask。粘贴一个 RGBA 图像,也使用它作为蒙版将粘贴图像的不透明部分,但不是它的透明背景。如果你修改粘贴如下所示,你应该有一个透明背景的粘贴图。

image_copy.paste(logo, position, logo)
使用 Pillow Python 库处理图像

旋转图像

您可以使用 rotate ()方法旋转 Pillow 图像。这需要一个表示旋转图像的度的整数或浮点参数,并返回旋转图像的新 Image 对象。

image = Image.open('demo_image.jpg')

image_rot_90 = image.rotate(90)
image_rot_90.save('image_rot_90.jpg')

image_rot_180 = image.rotate(180)
image_rot_180.save('image_rot_180.jpg')

在上面的例子中,我们将两张图片保存到磁盘上: 一张以90度旋转,另一张以180度旋转。得到的图像如下所示。

使用 Pillow Python 库处理图像
使用 Pillow Python 库处理图像

默认情况下,旋转后的图像保持原始图像的尺寸。这意味着,对于180倍以外的其他角度,图像将被切割和/或填充以适应原始尺寸。如果你仔细观察上面的第一张图片,你会注意到其中一些已经被裁剪以适应原来的高度,并且它的侧面已经用黑色背景填充( 一些系统可能使用透明背景 )以适应原来的宽度。下面的例子更清楚地说明了这一点。

image.rotate(18).save('image_rot_18.jpg')

得到的图像如下:

使用 Pillow Python 库处理图像

若要扩展已旋转图像的尺寸以适应整个视图,请传递第二个参数以使其旋转() ,如下所示。

image.rotate(18, expand=True).save('image_rot_18.jpg')

现在图像的内容将是完全可见的,图像的尺寸将有所增加,以解决这个问题。

使用 Pillow Python 库处理图像

翻转图片

您还可以翻转图像,以获得他们的镜像版本。这是通过 transpose ()函数完成的。它采用以下选项之一: PIL.Image.FLIP_LEFT_RIGHTPIL.Image.FLIP_TOP_BOTTOMPIL.Image.ROTATE_90PIL.Image.ROTATE_180PIL.Image.ROTATE_270 PIL.Image.TRANSPOSE or PIL.Image.TRANSVERSE.

image = Image.open('demo_image.jpg')

image_flip = image.transpose(Image.FLIP_LEFT_RIGHT)
image_flip.save('image_flip.jpg')

最终的图像可以在下面看到。

使用 Pillow Python 库处理图像

图像绘制

使用Pillow,您还可以使用 ImageDraw 模块绘制图像。您可以绘制直线、点、椭圆形、矩形、弧线、位图、和弦、饼图、多边形、形状和文本。

from PIL import Image, ImageDraw

canvas = Image.new('RGB', (400, 300), 'white')
img_draw = ImageDraw.Draw(canvas)
img_draw.rectangle((70, 50, 270, 200), outline='red', fill='blue')
img_draw.text((70, 250), 'Hello World', fill='green')
canvas.save('drawn_image.jpg')

在本例中,我们使用 new ()方法创建了一个 Image 对象。这将返回一个没有载入图像的 Image 对象。然后,在保存图像之前,我们向其添加一个矩形和一些文本。

使用 Pillow Python 库处理图像

颜色变换

模式之间的转换

Pillow 库使您能够使用 convert ()方法在不同的像素表示之间转换图像。它支持 L (灰度)、 RGB 和 CMYK 模式之间的转换。

在下面的示例中,我们将图像从 RGB 转换为 L (亮度)模式,这将导致一个灰度图像。

image = Image.open('demo_image.jpg')

greyscale_image = image.convert('L')
greyscale_image.save('greyscale_image.jpg')

print(image.mode) # Output: RGB
print(greyscale_image.mode) # Output: L
使用 Pillow Python 库处理图像

分裂和合并

您还可以使用 split ()方法将多波段图像(如 RGB)拆分为单个波段。Split ()创建新的图像,每个图像包含原始图像的一个波段。

您可以使用 merge ()函数将一组单波段图像合并到一个新的多波段图像中。Merge ()接受一个模式和一个图像元组,并将它们组合成一个新图像。

image = Image.open('demo_image.jpg')

red, green, blue = image.split()

print(image.mode) # Output: RGB
print(red.mode) # Output: L
print(green.mode) # Output: L
print(blue.mode) # Output: L

new_image = Image.merge("RGB", (green, red, blue))
new_image.save('new_image.jpg')

print(new_image.mode) # Output: RGB

在上面的代码中,我们将一个 RGB 图像分割成独立的波段,交换它们,然后合并它们。下面是最终的图片。

使用 Pillow Python 库处理图像

图像增强

Pillow 允许你通过使用 image enhancement 模块中的类调整图像的对比度、颜色、亮度和清晰度来增强图像。

from PIL import Image, ImageEnhance

image = Image.open('demo_image.jpg')

contrast = ImageEnhance.Contrast(image)
contrast.enhance(1.5).save('contrast.jpg')

在上面的例子中,我们将图像的对比度调整为1.5倍。增强类中使用的因子是决定增强级别的浮点值。因子1.0返回原始图像的一个副本; 因子越低意味着特定增强越少,值越高。对此值没有限制。

你可以看到下面的增强图像。

使用 Pillow Python 库处理图像

下面,我们增加图像的颜色。如果我们使用0.0的因子,我们将得到一个黑白图像。

color = ImageEnhance.Color(image)
color.enhance(1.5).save('color.jpg')
使用 Pillow Python 库处理图像

下面我们把图像调亮,调亮0.0就会产生黑色的图像。

brightness = ImageEnhance.Brightness(image)
brightness.enhance(1.5).save('brightness.jpg')
使用 Pillow Python 库处理图像
sharpness = ImageEnhance.Sharpness(image)
sharpness.enhance(1.5).save('sharpness.jpg')
使用 Pillow Python 库处理图像

给TA打赏
共{{data.count}}人
人已打赏
后端/架构

WordPress主题激活时创建菜单

2021-10-18 12:44:43

后端/架构存储架构

Atomic Read Modify Write Primitives for I/O Devices

2022-2-21 10:40:43

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索