在 Python 中使用 Pillow 进行图像处理【2/4】

news2024/11/19 18:22:04
第二部分

一、说明

        该文是《在 Python 中使用 Pillow 进行图像处理》的第二部分,主要介绍pil库进行一般性处理:如:图像卷积、钝化、锐化、阈值分割。

二、在 Python 中使用 Pillow 进行图像处理

        您已经学习了如何裁剪和旋转图像、调整图像大小以及从彩色图像中提取色带。但是,到目前为止您所采取的所有操作都没有对图像的内容进行任何更改。在本部分中,您将了解 Python Pillow 库中的图像处理功能。您将在 Pillow 中使用该ImageFilter模块。

2.1 使用卷积核的图像过滤器

        图像处理中使用的方法之一是使用内核的图像卷积。本教程的目的不是详细解释图像处理理论。如果您对图像处理科学感兴趣,您可以使用的最佳资源之一是Gonzalez 和 Woods 的《数字图像处理》。

        在本节中,您将学习如何使用卷积核执行图像处理的基础知识。但什么是卷积核呢?核是一个矩阵:

卷积核

        您可以考虑一个简单的图像来理解使用内核进行卷积的过程。该图像具有像素大小30x30并包含一条垂直线和一个点。该线有四个像素宽,点由一个4x4像素正方形组成。出于显示目的,下图已放大:

演示卷积核的图像

        您可以将内核放置在图像上的任何位置,并使用内核中心单元的位置作为参考。下图是图像左上角部分的表示:

核卷积图

        该图中的元素代表图像和内核的不同方面:

  • 白色方块表示图像中值为 的像素0
  • 红色方块表示图像中值为 的像素255。这些构成了上图中的点。
  • 每个紫色区域代表内核。该内核由一个3x3区域组成,内核中的每个单元格的值为1/9。该图显示了标记为 1、2 和 3 的三个不同位置的内核。

图像与内核卷积的结果可以创建新图像。可以通过以下步骤来理解卷积过程:

  1. 定位内核:考虑内核位置之一并查看内核的九个单元覆盖的图像像素。
  2. 乘以内核和像素值:将每个内核单元中的值与图像中相应的像素值相乘。九次乘法将得到九个值。
  3. 乘法结果求和:将这九个值加在一起。结果将是新图像中与内核中心像素具有相同坐标的像素值。
  4. 对所有像素重复:对图像中的每个像素重复该过程,每次移动内核,以便内核的中心单元每次对应不同的图像像素。

        您可以通过上图中标记为 1、2 和 3 的三个内核位置来查看此过程。考虑标记为 1 的内核位置。该内核的位置是(3, 2),这是其中心单元的位置,因为它位于第四行 (index = 3) 和第三列 (index = 2)。内核覆盖区域中的每个图像像素的值都为零。

因此,步骤 2 中的所有乘法都将为零,并且它们的加法也将为零。新图像的像素值为零(3, 2)

        对于所示的其他内核位置,情况有所不同。接下来,考虑标记为 2 的内核,位于(4, 7)。与此重叠的图像像素之一不为零。该像素值与核值相乘将得到255 x (1/9) = 28.33。剩余的八次乘法仍然为零,因为图像像素为零。(4, 7)因此,新图像中位置处的像素值为28.33

        上面所示的第三个内核位置位于(8, 11)。有四个非零图像像素与该内核重叠。每个像素位置的值为255,因此乘法结果将再次28.33针对每个像素位置。该内核位置的总体结果是28.33 x 4 = 113.33。新图像的该值将为(8, 11)

        该图和上面的讨论仅考虑了三个内核位置。卷积过程对图像中每个可能的内核位置重复此过程。这给出了新图像中每个像素位置的值。

        卷积的结果如下图右侧所示,左侧为原始图像:

使用 Python Pillow 的卷积核演示

        您使用的内核是框模糊内核。因子1/9存在,因此内核的总体权重为1。卷积的结果是原始图像的模糊版本。还有其他内核执行不同的功能,包括不同的模糊方法、边缘检测、锐化等。

        Python Pillow 库有几个内置内核和函数,可以执行上述卷积。您无需了解通过卷积进行过滤的数学原理即可使用这些过滤器,但了解使用这些工具时幕后发生的情况总是有帮助的。

        接下来的部分将介绍ImageFilterPillow 模块中可用的内核和图像过滤功能。

2.2 图像模糊、锐化和平滑

您将返回使用在本教程开始时使用的建筑物图像。您可以为此部分启动一个新的 REPL 会话:

>>>

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

除了 之外Image,您还可以ImageFilter从 Pillow 导入该模块。您可以使用该.filter()方法对图像应用过滤。此方法需要一个卷积核作为其参数,您可以使用 Pillow 模块中可用的几个内核之一ImageFilter。您将了解的第一组滤镜用于处理图像的模糊、锐化和平滑。

您可以使用预定义的滤镜模糊图像ImageFilter.BLUR

>>>

>>> blur_img = img.filter(ImageFilter.BLUR)
>>> blur_img.show()

显示的图像是原始图像的模糊版本。您可以使用放大以更详细地观察差异.crop(),然后使用以下命令再次显示图像.show()

>>>

>>> img.crop((300, 300, 500, 500)).show()
>>> blur_img.crop((300, 300, 500, 500)).show()

两张裁剪后的图像显示了两个版本之间的差异:

Python Pillow 中显示模糊的图像

ImageFilter.BoxBlur()您可以使用或自定义所需的模糊类型和数量ImageFilter.GaussianBlur():

>>>

>>> img.filter(ImageFilter.BoxBlur(5)).show()
>>> img.filter(ImageFilter.BoxBlur(20)).show()
>>> img.filter(ImageFilter.GaussianBlur(20)).show()

您可以看到下面的三个模糊图像,其显示顺序与上面代码中的顺序相同:

Python Pillow 中显示模糊的图像

.BoxBlur()滤波器与上一节介绍卷积核时描述的滤波器类似。参数是框模糊滤镜的半径。在前面讨论内核的部分中,您使用的框模糊滤镜是一个3x3滤镜。这意味着它的半径为1,因为滤镜从中心延伸了一个像素。

模糊图像显示,半径为 的框模糊滤镜20生成的图像比半径为 的框模糊滤镜生成的图像更模糊5

您还可以使用.GaussianBlur()过滤器,它使用高斯模糊内核。高斯核对核中心像素的权重比边缘像素的权重更大,这会导致比框模糊获得的模糊更平滑。因此,高斯模糊在很多情况下可以给出更好的结果。

如果你想锐化图像怎么办?在这种情况下,您可以使用ImageFilter.SHARPEN过滤器并将结果与​​原始图像进行比较:

>>>

>>> sharp_img = img.filter(ImageFilter.SHARPEN)
>>> img.crop((300, 300, 500, 500)).show()
>>> sharp_img.crop((300, 300, 500, 500)).show()

您正在比较两个图像的裁剪版本,显示建筑物的一小部分。锐化后的图像如右图所示:

显示 Python Pillow 中锐化的图像

也许您需要平滑图像,而不是锐化图像。ImageFilter.SMOOTH您可以通过作为参数传递来实现此目的.filter()

>>>

>>> smooth_img = img.filter(ImageFilter.SMOOTH)
>>> img.crop((300, 300, 500, 500)).show()
>>> smooth_img.crop((300, 300, 500, 500)).show()

下面,您可以看到左侧为原始图像,右侧为平滑后的图像:

显示 Python Pillow 中锐化的图像

        您将在下一节中看到平滑过滤器的应用,其中您将了解模块中的更多过滤器ImageFilter。这些滤镜作用于图像中对象的边缘。

2.3 边缘检测、边缘增强和压花

        当您查看图像时,确定该图像中对象的边缘相对容易。算法也可以使用边缘检测内核自动检测边缘。

        Pillow 中的模块ImageFilter有一个预定义的内核来实现此目的。在本部分中,您将再次使用建筑物图像并将其转换为灰度,然后再应用边缘检测滤镜。您可以继续上一节中的 REPL 会话:

>>> img_gray = img.convert("L")
>>> edges = img_gray.filter(ImageFilter.FIND_EDGES)
>>> edges.show()

结果是显示原始图像边缘的图像:

Python Pillow 中的边缘检测

该过滤器识别图像中的边缘。ImageFilter.SMOOTH在查找边缘之前应用过滤器可以获得更好的结果:

>>>

>>> img_gray_smooth = img_gray.filter(ImageFilter.SMOOTH)
>>> edges_smooth = img_gray_smooth.filter(ImageFilter.FIND_EDGES)
>>> edges_smooth.show()

您可以在下面看到原始灰度图像和两个边缘检测结果的比较。边缘检测之前进行平滑的版本显示在底部:

Python Pillow 中的边缘检测

您还可以使用滤镜增强原始图像的边缘ImageFilter.EDGE_ENHANCE

>>>

>>> edge_enhance = img_gray_smooth.filter(ImageFilter.EDGE_ENHANCE)
>>> edge_enhance.show()

您使用灰度图像的平滑版本来增强边缘。下面并排显示了原始灰度图像的一部分和边缘增强的图像。右侧是经过边缘增强的图像:

Python Pillow 中的边缘增强

另一个ImageFilter处理对象边缘的预定义过滤器是ImageFilter.EMBOSS。您可以将其作为参数传递给.filter()本节中的其他过滤器:

>>>

>>> emboss = img_gray_smooth.filter(ImageFilter.EMBOSS)
>>> emboss.show()

您使用平滑的灰度版本作为此过滤器的起点。您可以看到下面的浮雕图像,它使用图像中的边缘显示了不同的效果:

Python Pillow 中的图像浮雕

在本节中,您了解了ImageFilter模块中可应用于图像的几个可用过滤器。您还可以使用其他过滤器来处理图像。ImageFilter您可以在文档中查看所有可用过滤器的列表。

三、图像分割和叠加

3.1 先给出一个例子

   cat.jpg在本部分中,您将使用名为( imagecredit ) 和monastery.jpg( imagecredit )的图像文件,您可以在本教程的图像存储库中找到这些文件:

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

        这是两张图片:

Python Pillow 教程中使用的猫图像

用于 Python Pillow 教程的修道院庭院图像

        您可以使用 Python Pillow 库从第一张图像中提取猫并将其放置在修道院庭院的地板上。您将使用多种图像处理技术来实现此目的。

3.2 图像阈值处理

        您将从工作开始cat.jpg。您需要使用图像分割技术从背景中删除猫的图片。在此示例中,您将使用阈值技术分割图像。

        首先,您可以将图像裁剪为较小的图像以删除一些背景。您可以为此项目启动一个新的 REPL 会话:

>>> from PIL import Image
>>> filename_cat = "cat.jpg"

>>> with Image.open(filename_cat) as img_cat:
...     img_cat.load()
...

>>> img_cat = img_cat.crop((800, 0, 1650, 1281))
>>> img_cat.show()

        裁剪后的图像包含猫和一些距离猫太近而无法裁剪的背景:

裁剪后的猫图像

        彩色图像中的每个像素都由与该像素的红色、绿色和蓝色值相对应的三个数字来数字表示。阈值处理是将所有像素转换为最大值或最小值的过程,具体取决于它们是否高于或低于某个数字。在灰度图像上执行此操作更容易:

>>> img_cat_gray = img_cat.convert("L")
>>> img_cat_gray.show()
>>> threshold = 100
>>> img_cat_threshold = img_cat_gray.point(
...     lambda x: 255 if x > threshold else 0
... )
>>> img_cat_threshold.show()

        您可以通过调用将.point()灰度图像中的每个像素转换为 或 来255实现阈值化0。转换取决于灰度图像中的值是大于还是小于阈值。本例中的阈值是100

        下图显示了灰度图像和阈值处理的结果:

Python Pillow 中的阈值

        在此示例中,灰度图像中像素值大于 的所有点都100转换为白色,所有其他像素都更改为黑色。您可以通过改变阈值来更改阈值处理的灵敏度。

        当要分割的对象与背景不同时,可以使用阈值来分割图像。您可以使用具有更高对比度的原始图像版本获得更好的结果。在此示例中,您可以通过对原始图像的蓝色通道而不是灰度图像进行阈值化来实现更高的对比度,因为背景中的主色是棕色和绿色,其中蓝色成分较弱。

        您可以像之前一样从彩色图像中提取红色、绿色和蓝色通道:

>>> red, green, blue = img_cat.split()
>>> red.show()
>>> green.show()
>>> blue.show()

        下面从左到右显示了红色、绿色和蓝色通道。所有三个都显示为灰度图像:

猫图像的颜色通道

蓝色通道在代表猫的像素和代表背景的像素之间具有更高的对比度。您可以使用蓝色通道图像来阈值:

>>> threshold = 57
>>> img_cat_threshold = blue.point(lambda x: 255 if x > threshold else 0)
>>> img_cat_threshold = img_cat_threshold.convert("1")
>>> img_cat_threshold.show()

  在此示例中,您使用阈值57"1"您还可以使用 的参数将图像转换为二进制模式.convert()。二值图像中的像素只能具有0或的值1

        注意:处理某些依赖有损压缩的图像格式(例如 JPEG)时,图像可能会略有不同,具体取决于您使用的 JPEG 解码器。不同的操作系统通常具有不同的默认 JPEG 解码器。因此,处理图像时获得的结果可能会有所不同,具体取决于您使用的操作系统和 JPEG 解码器。

        如果您的结果与本教程中显示的结果不匹配,您可能需要稍微调整阈值。

        阈值化的结果如下:

改进了 Python Pillow 教程中猫图像的阈值

        您可以在这张黑白图像中识别出这只猫。但是,您希望图像中与猫对应的所有像素都是白色,而所有其他像素都是黑色。在此图像中,与猫相对应的区域仍然有黑色区域,例如眼睛、鼻子和嘴巴所在的位置,并且图像中的其他位置仍然有白色像素。

您可以使用称为腐蚀和膨胀的图像处理技术来创建更好的代表猫的蒙版。您将在下一节中了解这两种技术。

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

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

相关文章

Yakit工具篇:专项漏洞检测的配置和使用

简介(来自官方文档) 专项漏洞检测是针对特定应用程序或系统进行的安全漏洞扫描技术,旨在检测与该应用程序或系统相关的安全漏洞。 Yakit通过对常见的中间件、CMS、框架、组件进行总结、归纳,并针对这些组件对其常见的高危漏洞进…

027-第三代软件开发_ComboBox

第三代软件开发_ComboBox 文章目录 第三代软件开发_ComboBox项目介绍ComboBox实际使用 关键字: Qt、 Qml、 ComboBox、 delegate、 Connections 项目介绍 欢迎来到我们的 QML & C 项目!这个项目结合了 QML(Qt Meta-Object Language&…

试题一 (软件设计师笔记)(15分)

😀前言 现在就是总复习试题一 🏠个人主页:尘觉主页 🧑个人简介:大家好,我是尘觉,希望我的文章可以帮助到大家,您的满意是我的动力😉 在csdn获奖荣誉: 🏆csd…

记录打包部署Springboot项目到Windows环境

Springboot项目开发完成后要做的工作就是部署了,这里记录下打包部署的过程。这个项目是一个SpringBoot多模块项目,包含了一个父工程,一个子模块和一个工具模块。其中子模块里有启动类,而工具模块没有。因此这三者的pom文件不一样。…

SOME/IP, DDS 还是 MQTT

如今,用户希望将他们的汽车根据个人偏好进行定制,通过添加功能并定期进行更新,就像他们对待移动设备一样。实现这些期望属性的一个构建模块是基于 Internet Protocol(IP)的通信;IP为新的设计模式打开了大门…

arcgis js api 4.x加载geoserver发布的地方坐标系(自定义坐标系)的wms服务

问题描述:之前研究过arcgis js api 4.x加载arcgis server 发布的地方坐标系的wms服务,后来研究出来能正常加载了,想了解的可以看我之前的博客。但是一直困于加载geoserver发布的地方坐标系的wms服务,一直都是用的WMSLayer这个调用…

1024渗透OpenVas扫描工具使用(第十四课)

1024渗透扫描工具使用(第十四课) 一 漏洞披露 1 微软安全更新指南(自2017年2月起,替代安全公告) 安全公告都有一个惟一的编号 其命名规则是:MS年份-补丁序号 或 CVE-年份-补丁序号 比如MS17-010就表示2017年发布的编号为010的安…

自然语言处理---Transformer构建语言模型

语言模型概述 以一个符合语言规律的序列为输入,模型将利用序列间关系等特征,输出一个在所有词汇上的概率分布,这样的模型称为语言模型。 # 语言模型的训练语料一般来自于文章,对应的源文本和目标文本形如: src1 "I can do&…

【剑指Offer】34.二叉树中和为某一值的路径(二)

题目 输入一颗二叉树的根节点root和一个整数expectNumber,找出二叉树中结点值的和为expectNumber的所有路径。 1.该题路径定义为从树的根结点开始往下一直到叶子结点所经过的结点 2.叶子节点是指没有子节点的节点 3.路径只能从父节点到子节点,不能从…

运维:mysql常用的服务器状态命令

目录 1、查询当前服务器运行的进程 2、查询最大链接数 3、查询当前链接数 4、展示当前正在执行的sql语句 5、查询当前MySQL当中记录的慢查询条数 6、展示Mysql服务器从启动到现在持续运行的时间 7、查询数据库存储占用情况 8、查询服务器启动以来的执行查询的总次数 9…

算法通关村第十关黄金挑战——归并排序详解

大家好,我是怒码少年小码。 归并排序 就是将一个大的序列分为多个小的序列,对小的序列排序,最后利用归并的思想合并序列。归并排序的思想就是分而治之。 分:将大序列分为很多个小的序列 治:将多个小的序列合并为大序…

用 pytorch 训练端对端验证码识别神经网络并进行 C++ 移植

文章目录 前言安装安装 pytorch安装 libtorch安装 opencv(C) 准备数据集获取训练数据下载标定 编码预分析 数据集封装格式 神经网络搭建神经网络训练神经网络测试神经网络预测C 移植模型转换通过跟踪转换为 Torch Script通过注解转换为 Torch Script 编写…

解决 Element-ui中 表格(Table)使用 v-if 条件控制列显隐时数据展示错乱的问题

本文 Element-ui 版本 2.x 问题 在 el-table-column 上需根据不同 v-if 条件来控制列显隐时&#xff0c;就会出现列数据展示错乱的情况&#xff08;要么 A 列的数据显示在 B 列上&#xff0c;或者后端返回有数据的但是显示的为空&#xff09;&#xff0c;如下所示。 <tem…

Python教程(15)——Python流程控制语句详解

目录 if语句else if语句for循环遍历类型range关键字 while循环break语句continue语句 Python流程控制是Python编程中非常重要的一部分&#xff0c;它用于控制程序的执行流程。Python提供了多种流程控制语句&#xff0c;包括if语句、while循环、for循环、break和continue语句等。…

[翻译]理解Postgres的IOPS:为什么数据即使都在内存,IOPS也非常重要

理解Postgres的IOPS&#xff1a;为什么数据即使都在内存&#xff0c;IOPS也非常重要 磁盘IOPS&#xff08;每秒输入/输出操作数&#xff09;是衡量磁盘系统性能的关键指标。代表每秒可以执行的读写操作数量。对于严重依赖于磁盘访问的PG来说&#xff0c;了解和优化磁盘IOPS对实…

使用QT实现http里面的get和post

#1024程序员节&#xff5c;参与投稿&#xff0c;赢限定勋章和专属大奖# #假如你有一台服务器&#xff0c;你最想做哪些事&#xff1f;# #你被什么样的BUG困扰过一周以上&#xff1f;# 在http里面下面这些方法和服务器的响应代码一起用于HTTP协议中的请求和响应交互。请注意&…

模板再认识

在前面的文章中我写了关于模板的一些简单的认识&#xff0c;现在我们来再次认识模板文章目录 1.非类型模板参数2.模板特化1). 模板特化的写法2). 类模板特化3). 函数模板特化4). 模板全/偏特化 3.模板分离编译 1.非类型模板参数 在模板中还有一种是非类型的模板参数。我们代码…

【数组拷贝+二维数组遍历】

文章目录 前言数组的拷贝第一种方式&#xff1a;第二种方式:利用工具类拷贝 二维数组二维数组的三种定义打印二维数组的某个元素遍历二维数组 二维数组的每个元素是一维数组遍历二维数组&#xff08;优化&#xff09;打印出一个数组&#xff08;不是数组元素&#xff09;的方法…

linux性能分析(三)性能优化导轮

一 别再让Linux性能问题成为你的绊脚石 ① 学习历程 备注&#xff1a; 跟我的学习经历很相像刚工作时遇到的场景跟我现在一样,深深的无力感驱使我继续前行目标: 性能优化成为我的肌肉记忆,写代码的潜意识 ... ② 常见的问题 ③ 性能问题为什么这么难呢 思考&#xff1a…

顺序表ArrayList

作者简介&#xff1a; zoro-1&#xff0c;目前大二&#xff0c;正在学习Java&#xff0c;数据结构等 作者主页&#xff1a; zoro-1的主页 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f496; 顺序表 概念Arraylist构造方法相关方法遍历操作 自…