【Pillow库的内涵】01/3 进行基本图像操作

news2024/11/15 18:52:28

一、说明

        Pillow 具有被 Python 社区广泛使用的优势,并且它不像其他一些图像处理库那样具有陡峭的学习曲线。应用PIL库的Image对象,益处很多,首先它可以处理网上URL文件,其次,图片可以方面转化成int32、64或float类型,因而可以方便实现变换和显示uint8。尤其和Tkinter搭配,用起来非常方便顺手。

二、内容提要

  • 使用 Python Pillow 库进行基本图像操作
  • Pillow 中的图像模块和图像类
  • 基本图像处理
  • Python Pillow 库中图像的波段和模式
  • 在 Python 中使用 Pillow 进行图像处理
  • 使用卷积核的图像过滤器
  • 图像模糊、锐化和平滑
  • 边缘检测、边缘增强和压花
  • 图像分割和叠加:一个例子
  • 图像阈值处理
  • 腐蚀和膨胀
  • 使用阈值分割图像
  • 使用 Image.paste() 叠加图像
  • 创建水印
  • 使用 NumPy 和 Pillow 进行图像处理
  • 使用 NumPy 相互减去图像
  • 使用 NumPy 创建图像
  • 创建动画
  • 结论

三、使用 Python Pillow 库进行基本图像操作

        Python Pillow 库是一个名为 PIL 的旧库的分支。PIL 代表 Python Imaging Library,它是使 Python 能够处理图像的原始库。PIL 于 2011 年停产,仅支持 Python 2。按照开发人员自己的描述,Pillow 是友好的 PIL 分支,它使库保持活力并包含对 Python 3 的支持。

        Python 中有不止一个模块来处理图像并执行图像处理。如果您想通过操作像素直接处理图像,那么您可以使用NumPy和SciPy。其他流行的图像处理库是OpenCV、scikit-image和Mahotas。其中一些库比 Pillow 更快、更强大。

        然而,Pillow 仍然是处理图像的重要工具。它提供的图像处理功能类似于 Photoshop 等图像处理软件中的功能。Pillow 通常是不需要更高级图像处理专业知识的高级图像处理任务的首选。它也经常用于处理图像时的探索性工作。      

        您需要先安装该库才能使用它。您可以pip在虚拟环境中使用以下命令安装 Pillow :

  • 视窗
  • Linux + macOS
PS> python -m venv venv
PS> .\venv\Scripts\activate
(venv) PS> python -m pip install Pillow

        现在您已经安装了该软件包,您可以开始熟悉Python Pillow 库并执行基本的图像操作。

3.1 Pillow 中的模块ImageImage

        Pillow 中定义的主要类是Image类。当您使用 Pillow 读取图像时,图像将存储在 类型的对象中Image

        对于本部分中的代码,您将需要名为buildings.jpg( imagecredit ) 的图像文件,您可以在本教程的图像存储库中找到该文件:

        获取图像: 单击此处访问您将使用 Pillow 操作和处理的图像。

        您可以将此图像文件放置在您正在使用的项目文件夹中。

        使用 Pillow 探索图像时,最好使用交互式 REPL 环境。首先打开刚刚下载的图像:

>>>

>>> from PIL import Image
>>> filename = "buildings.jpg"
>>> with Image.open(filename) as img:
...     img.load()
...

>>> type(img)
<class 'PIL.JpegImagePlugin.JpegImageFile'>

>>> isinstance(img, Image.Image)
True

        您可能希望从 Pillow 导入,而不是从 PIL 导入。Pillow毕竟你确实安装了,而不是PIL。然而,Pillow 是 PIL 库的一个分支。PIL因此,在导入代码时您仍然需要使用。

        您调用该open()函数从文件中读取图像并将.load()图像读入内存,以便现在可以关闭文件。您可以使用with语句创建上下文管理器,以确保文件在不再需要时立即关闭。

        在此示例中,对象是 JPEG 图像特定类型,它是该类的子类Image,正如您通过调用 来确认的那样isinstance()。请注意,类和定义该类的模块共享相同的名称Image。您可以使用以下命令显示图像.show():

>>>

>>> img.show()

.show()方法将图像保存为临时文件,并使用操作系统的本机软件处理图像来显示它。当您运行上面的代码时,您将看到显示以下图像:

Python Pillow 教程中使用的建筑物图像

        在某些系统上,调用.show()将阻止 REPL,直到您关闭映像。这取决于操作系统和您使用的默认图像查看软件。

        在处理 Python Pillow 库中的图像时,您需要熟悉三个关键属性。您可以使用Image类属性.format、.size和来探索这些.mode:

>>>

>>> img.format
'JPEG'

>>> img.size
(1920, 1273)

>>> img.mode
'RGB'

        图像的格式显示了您正在处理的图像类型。在本例中,图像的格式为'JPEG'. 尺寸显示图像的宽度和高度(以像素为单位)。该图像的模式是'RGB'. 您很快就会了解有关模式的更多信息。

        通常,您可能需要裁剪图像并调整图像大小。该类有两个Image方法可用于执行这些操作.crop():.resize()

>>>

>>> cropped_img = img.crop((300, 150, 700, 1000))
>>> cropped_img.size
(400, 850)

>>> cropped_img.show()

>>> low_res_img = cropped_img.resize(
...     (cropped_img.width // 4, cropped_img.height // 4)
... )
>>> low_res_img.show()

        的参数.crop()必须是一个 4 元组,用于定义要裁剪的区域的左边缘、上边缘、右边缘和下边缘。Pillow 中使用的坐标系将坐标 (0, 0) 分配给左上角的像素。这与通常用于二维数组的坐标系相同。4 元组代表图像的以下部分:

裁剪操作显示从原点获取的尺寸

.crop()上面代码中返回的新图像的大小为400x850像素。裁剪后的图像仅显示原始图片中的一栋建筑物:

Python Pillow 教程中的裁剪图像

        在上面的代码中,您还可以使用 更改裁剪图像的分辨率.resize(),这需要一个元组作为必需参数。用作参数的元组定义图像的新宽度和高度(以像素为单位)。

        在上面的示例中,您使用楼层除法运算符( //) 以及Image属性.width和,将新的宽度和高度设置为其原始值的四分之一.height。最后调用show()显示裁剪和调整大小的图像:

在 Python Pillow 教程中调整图像大小

        您可以使用其他可选参数来.resize()控制图像的重新采样方式。或者,您可以使用以下方法实现类似的缩放.reduce():

>>>

>>> low_res_img = cropped_img.reduce(4)

        该参数决定了缩小图像的因子。如果您更喜欢设置最大尺寸而不是缩放因子,那么您可以使用.thumbnail()。缩略图的大小将小于或等于您设置的大小。

        注意:.thumbnail()方法会Image就地更改对象,并且不会返回新对象。但是,.crop().resize().reduce()都返回一个新Image对象。并非 Pillow 库中的所有方法都具有相同的行为方式。

Image一旦您对返回的图像感到满意,您可以使用以下命令将任何对象保存到文件中.save():

>>>

>>> cropped_img.save("cropped_image.jpg")
>>> low_res_img.save("low_resolution_cropped_image.png")

        调用该方法后,它会在项目文件夹中创建图像文件。在此示例中,其中一个图像是 JPEG 图像,另一个是 PNG 图像。用作文件名的扩展名会自动确定文件格式,或者您可以将格式指定为附加可选参数。

3.2 基本图像处理

        除了裁剪和调整大小之外,您还可以对图像进行操作。另一个常见的要求是旋转或翻转图像。您可以使用该.transpose()方法进行一些转换。继续执行您在上一节中开始的相同 REPL 会话:

>>>

>>> converted_img = img.transpose(Image.FLIP_TOP_BOTTOM)
>>> converted_img.show()

        此代码显示以下图像:

Python Pillow 教程中的翻转图像

        您可以将七个选项作为参数传递给.transpose()

  1. Image.FLIP_LEFT_RIGHT将图像从左向右翻转,形成镜像
  2. Image.FLIP_TOP_BOTTOM将图像从上到下翻转
  3. Image.ROTATE_90将图像逆时针旋转 90 度
  4. Image.ROTATE_180将图像旋转 180 度
  5. Image.ROTATE_270将图像逆时针旋转 270 度,与顺时针旋转 90 度相同
  6. Image.TRANSPOSE以左上角像素为原点转置行和列,转置图像中的左上角像素与原始图像中的相同
  7. Image.TRANSVERSE使用左下像素作为原点转置行和列,左下像素是原始版本和修改版本之间保持固定的像素

        上面的所有旋转选项都以 90 度为步长定义旋转。如果您需要将图像旋转另一个角度,那么您可以使用.rotate():

>>>

>>> rotated_img = img.rotate(45)
>>> rotated_img.show()

        此方法调用将图像逆时针旋转 45 度,得到以下图像:

Python Pillow 教程中的旋转图像

        返回的对象Image与原始对象大小相同Image。因此,该显示中缺少图像的角点。您可以使用命名参数更改此行为expand

>>>

>>> rotated_img = img.rotate(45, expand=True)
>>> rotated_img.show()

        此方法返回完全包含旋转图像的更大图像:

Python Pillow 教程中带有展开参数的旋转图像

您可以使用其他可选参数进一步自定义旋转。您现在可以更改图像的大小和方向。在下一节中,您将了解 Python Pillow 库中不同类型的图像。

3.3 Python Pillow 库中图像的波段和模式

        图像是像素的二维阵列,其中每个像素对应一种颜色。每个像素可以由一个或多个值表示。例如,在RGB图像中,每个像素由与该像素的红色、绿色和蓝色值相对应的三个值表示。

        因此,ImageRBG 图像的对象包含三个波段,每个波段对应一种颜色。像素大小的 RGB 图像由值数组100x100表示。100x100x3

        RGBA图像还包括 alpha 值,其中包含有关每个像素透明度的信息。RGBA 图像有四个色带,一个色带代表每种颜色,第四个色带包含 Alpha 值。每个带具有与图像尺寸相同的尺寸。因此,尺寸为像素的 RGBA 图像由值数组100x100表示。100x100x4

        图像的模式描述了您正在使用的图像类型。Pillow 支持大多数标准模式,包括黑白(二进制)、灰度、RGB、RGBA 和CMYK。您可以在有关模式的 Pillow 文档中查看支持的模式的完整列表。

   Image您可以使用该方法找出对象中有多少个带.getbands(),并且可以使用在模式之间进行转换.convert()。现在,您将在本教程中使用图像存储库中名为strawberry.jpg( image Credit )的图像:

Python Pillow 教程的草莓图像

        该图像的模式也是 RGB。您可以将此图像转换为其他模式。此代码使用您在前面部分中启动的相同 REPL 会话:

>>>

>>> filename = "strawberry.jpg"
>>> with Image.open(filename) as img:
...     img.load()
...

>>> cmyk_img = img.convert("CMYK")
>>> gray_img = img.convert("L")  # Grayscale

>>> cmyk_img.show()
>>> gray_img.show()

>>> img.getbands()
('R', 'G', 'B')
>>> cmyk_img.getbands()
('C', 'M', 'Y', 'K')
>>> gray_img.getbands()
('L',)

        您调用.convert()两次将 RGB 图像转换为 CMYK 和灰度版本。CMYK 图像看起来与原始图像相似,但使用印刷材料而不是数字显示的常见模式进行编码。转换为灰度给出以下输出:

        调用的输出.getbands()确认 RGB 图像中有 3 个波段、CMYK 图像中有 4 个波段、灰度图像中有 1 个波段。

        您可以使用 将图像分成多个波段.split(),并Image使用 将单独的波段重新组合回对象中merge()。当您使用 时.split(),该方法将所有带区作为单独的Image对象返回。您可以通过显示返回的对象之一的字符串表示形式来确认这一点:

>>>

>>> red, green, blue = img.split()
>>> red
<PIL.Image.Image image mode=L size=1920x1281 at 0x7FDD80C9AFA0>
>>> red.mode
'L'

        返回对象的模式.split()为,表示这是一张灰度图像,或者是只显示每个像素的亮度'L'值的图像。

   merge()现在,您可以使用模块中的函数创建三个新的 RGB 图像,分别显示红色、绿色和蓝色通道Image

>>>

>>> zeroed_band = red.point(lambda _: 0)

>>> red_merge = Image.merge(
...     "RGB", (red, zeroed_band, zeroed_band)
... )

>>> green_merge = Image.merge(
...     "RGB", (zeroed_band, green, zeroed_band)
... )

>>> blue_merge = Image.merge(
...     "RGB", (zeroed_band, zeroed_band, blue)
... )

>>> red_merge.show()
>>> green_merge.show()
>>> blue_merge.show()

        第一个参数merge()确定您要创建的图像的模式。第二个参数包含要合并到单个图像中的各个波段。

        单独存储在变量 中的红色波段red是模式为 L 的灰度图像。要创建仅显示红色通道的图像,请将原始图像中的红色波段与仅包含零的绿色和蓝色波段合并。要创建一个到处都包含零的带,可以使用该.point()方法。

        该方法需要一个函数作为参数。您使用的函数决定每个点的变换方式。在本例中,您使用lambda函数将每个点映射到0

        当您将红色波段与包含零的绿色和蓝色波段合并时,您会得到一个名为 的 RGB 图像red_merge。因此,您创建的 RGB 图像仅在红色通道中具有非零值,但由于它仍然是 RGB 图像,因此它将以彩色显示。

        您还可以重复类似的过程来获取green_mergeblue_merge,其中包含带有来自原始图像的绿色和蓝色通道的 RGB 图像。该代码显示以下三张图像:

Python Pillow 教程的草莓图像单独通道

        红色图像在代表草莓的像素中包含强信号,因为这些像素大部分是红色的。绿色和蓝色通道将这些像素显示为黑色,因为它们的值较小。例外的是那些代表草莓表面上的光反射的像素,因为这些像素几乎是白色的。

        创建本教程中所示的并排显示显示隐藏.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1119557.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

蓝桥杯 (猜生日、棋盘放麦子、MP3储存 C++)

思路&#xff1a; 1、用循环。 2、满足条件&#xff0c;能整除2012、3、12且month等于6、day<30 #include<iostream> using namespace std; int main() {for (int i 19000101; i < 20120312; i){int month i / 100 % 100;int day i % 100;if (i % 2012 0 &…

互联网Java工程师面试题·Java 面试篇·第二弹

目录 15、什么是不可变对象&#xff08;immutable object&#xff09;&#xff1f;Java 中怎么创建一个不可变对象&#xff1f; 16、我们能创建一个包含可变对象的不可变对象吗&#xff1f; 17、Java 中应该使用什么数据类型来代表价格&#xff1f; 18、怎么将 byte 转换为 Str…

图论03-【无权无向】-图的深度优先遍历-路径问题/检测环/二分图

文章目录 1. 代码仓库2. 单源路径2.1 思路2.2 主要代码 3. 所有点对路径3.1 思路3.2 主要代码 4. 路径问题的优化-提前结束递归4.1 思路4.2 主要代码 5. 检测环5.1 思路5.2 主要代码 5. 二分图5.1 思路5.2 主要代码5.2.1 遍历每个联通分量5.2.2 递归判断相邻两点的颜色是否一致…

192:最近的系列思考2/犬岛APP 的使用理解

最近的一些契机&#xff0c;导致一些思考&#xff1a; ​ * 与产品经理意志相悖的产品* 与最初的设计定位不匹配的产品社交大牛的APP一上线就引来诸多关注&#xff0c;作为总设计的纯大大非常简明扼要的说明了这个APP的定位&#xff1a;给内涵&#xff08;含&#xff09;有趣的…

图论04-【无权无向】-图的广度优先遍历

文章目录 1. 代码仓库2. 广度优先遍历图解3.主要代码4. 完整代码 1. 代码仓库 https://github.com/Chufeng-Jiang/Graph-Theory 2. 广度优先遍历图解 3.主要代码 原点入队列原点出队列的同时&#xff0c;将与其相邻的顶点全部入队列下一个顶点出队列出队列的同时&#xff0c;将…

布尔盲注知识点

概念&#xff1a;布尔盲注一般适用于页面没有回显字段(不支持联合查询)&#xff0c;且web页面返回True 或者 false&#xff0c;构造SQL语句&#xff0c;利用and&#xff0c;or等关键字来其后的语句 true 、 false使web页面返回true或者false&#xff0c;从而达到注入的目的来获…

Python---练习:while循环案例:猜数字

需求&#xff1a; 计算机从1 ~ 10之间随机生成一个数字&#xff0c;然后提示输入数字&#xff0c;如果我们输入的数字与随机数相等&#xff0c;则提示恭喜你&#xff0c;答对了。如果输入的数字比随机数大&#xff0c;则提示&#xff0c;猜大了。反之&#xff0c;则提示猜小了…

晶振与晶体

文章目录 基础知识无源晶振 & 有源晶振 博文链接 基础知识 无源晶振 & 有源晶振 博文链接 晶振原理解析

在Vue中使用Mock.js虚拟接口数据实例详解

在Vue项目中使用Mock.js可以方便地模拟接口数据&#xff0c;用于前端开发和测试。Mock.js是一个生成随机数据的库&#xff0c;可以帮助我们快速构建虚拟接口数据。在本文中&#xff0c;我将通过一个实例来详细讲解在Vue中使用Mock.js虚拟接口数据的方法。 首先&#xff0c;我们…

H5前端开发——事件处理

H5前端开发——事件处理 在H5前端开发中,事件处理是非常重要的一部分。通过事件处理,可以实现对用户操作的响应和交互。以下是几种常见的事件处理方式: HTML事件处理: 在HTML标签上直接设定事件处理函数,如<button onclick="myFunction()">点击我</bu…

【每周一测】Java阶段三第二周学习

目录 1、以下哪个过程可以创建Class对象? 2、下列switch代码段输出结果是&#xff08;&#xff09; 3、redis的数据类型 4、⭐以下关于Servlet生命周期说法错误的是&#xff08; &#xff09; 5、⭐下面有关SPRING的事务传播特性&#xff0c;说法错误的是&#xff1f; 6…

自然语言处理---huggingface平台使用指南

1 huggingface介绍 Huggingface总部位于纽约&#xff0c;是一家专注于自然语言处理、人工智能和分布式系统的创业公司。他们所提供的聊天机器人技术一直颇受欢迎&#xff0c;但更出名的是他们在NLP开源社区上的贡献。Huggingface一直致力于自然语言处理NLP技术的平民化(democr…

数据结构 MapSet(搜索)

数据结构 Map&Set(搜索) 文章目录 数据结构 Map&Set(搜索)1. 搜索树1.1 概念1.2 初始构建1.3 操作-插入1.4 操作-查找1.5 操作-删除1.6 性能分析 2. 搜索介绍2.1 概念及场景2.2 模型 3. Map的使用3.1 关于Map的说明3.2 关于Map.Entry<K, V>的说明3.3 Map的常用方…

Hadoop3教程(三十一):(生产调优篇)异构存储

文章目录 &#xff08;157&#xff09;异构存储概述概述异构存储的shell操作 &#xff08;158&#xff09;异构存储案例实操参考文献 &#xff08;157&#xff09;异构存储概述 概述 异构存储&#xff0c;也叫做冷热数据分离。其中&#xff0c;经常使用的数据被叫做是热数据&…

寻找Windows API 原始字节(x64dbg)

首先我们将我们的木马移入x64dbg 第一种方法 通过命令寻找 disasm CreateRemoteThreadEx第二种方法 将调试器附加到kernelbase.dll后转到符号选项卡&#xff0c;最后&#xff0c;在搜索栏中&#xff0c;我们可以搜索CreateRemoteThreadEx函数并双击它以获取下列&#xff1a…

深度学习---神经网络基础

深度学习概述 机器学习是实现人工智能的一种途径&#xff0c;深度学习是机器学习的一个子集&#xff0c;深度学习是实现机器学习的一种方法。与机器学习算法的主要区别如下图所示&#xff1a; 传统机器学习算术依赖人工设计特征&#xff0c;并进行特征提取&#xff0c;而深度学…

java新特性流 stream01

案例描述 今天跟着黑马程序员的视频&#xff0c;完成“瑞吉外卖”项目的菜品信息管理模块的时候&#xff0c;遇到了一个比较陌生的写法 用到了Java8的新特性 stream().map((item) -> {}).collect() List<DishDto> collect records.stream().map((item) -> {DishDt…

Elasticsearch 8.9 Master节点处理请求源码

大家看可以看ElasticSearch源码&#xff1a;Rest请求与Master节点处理流程&#xff08;1&#xff09; 这个图非常好&#xff0c;下午的讲解代码在各个类和方法之间流转&#xff0c;都体现这个图上 一、Master节点处理请求的逻辑1、节点(数据节点)要和主节点进行通讯&#xff0…

H5随机短视频滑动版带打赏源码,可封装APP软件或嵌入式观看

H5随机短视频滑动版带打赏源码&#xff0c;可封装APP软件或嵌入式观看&#xff0c;网站引流必备源码&#xff01; 数据来源抖音和快手官方短视频链接&#xff0c;无任何违规内容&#xff01;可自行添加广告等等&#xff01; 手机端完美支持滑动屏幕观看&#xff08;向上或向右…

STM32不使用 cubeMX实现外部中断

这篇文章将介绍如何不使用 cubeMX完成外部中断的配置和实现。 文章目录 前言一、文件加入工程二、代码解析exti.cexti.hmain.c 注意&#xff1a;总结 前言 实验开发板&#xff1a;STM32F103C8T6。所需软件&#xff1a;keil5 &#xff0c; cubeMX 。实验目的&#xff1a;如何不…