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

第二部分

一、说明

        该文是《在 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.rhkb.cn/news/169726.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

26. 通过 cilium pwru了解网络包的来龙去脉

pwru是一种基于eBPF的工具,可跟踪Linux内核中的网络数据包,并具有先进的过滤功能。它允许对内核状态进行细粒度检查,以便通过调试网络连接问题来解决传统工具(如iptables TRACE或tcpdump)难以解决甚至无法解决的问题。在本文中,我将介绍pwru如何在不必事先了解所有内容的…

【java】【重构二】分模块开发版本锁定以及耦合(打包)实战

目录 一、创建dependencyManagement标签 二、 将需要版本控制的依赖版本进行标签设置 三、将需要版本控制的依赖从各子模块迁移到此处 四、将父模块的依赖版本控制 五、删除子模块的全部版本 1、bocai-web-management模块 2、bocai-utils模块 六、打包 1、确定代码都…

shein面试:nacos无入侵配置,做过吗,怎么做?

说在前面 在40岁老架构师 尼恩的读者社区(50)中,最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、shein 希音、百度、网易的面试资格,遇到很多很重要的面试题: 无入侵配置,做过吗,怎么做的?Na…

学习package.json

package.json 文件,它是项目的配置文件,常见的配置有配置项目启动、打包命令,声明依赖包等。package.json 文件是一个 JSON 对象,该对象的每一个成员就是当前项目的一项设置。 {"name": "monorepo_frame",&q…

Go 实现选择排序算法及优化

选择排序 选择排序是一种简单的比较排序算法,它的算法思路是首先从数组中寻找最小(大)的元素,然后放到数组中的第一位,接下来继续从未排序的元素中寻找最小(大)元素,然后放到已排序…

Zabbix告警与飞书集成

一、配置媒介 1、下载飞书的Zabbix媒介类型如下: zbx_export_mediatype_feishu.xml 2、Zabbix中导入媒介类型 Zabbix Web中选择管理 > 报警媒介,然后导入该媒介类型。导入规则选择“更新现有的”和“创建新的”。 3、配置飞书媒介类型用户 Zabbi…

【MyBatis进阶】mybatis-config.xml分析以及try-catch新用法

目录 尝试在mybatis项目中书写增删改查 遇见问题:使用mybaties向数据库中插入数据,idea显示插入成功,但是数据库中并没有数据变化? MyBatis核心配置文件剖析 细节剖析: try-catch新用法 截至目前我的项目存在的问题&#xf…

AD20~PCB的板层设计和布线

1、打开51单片机最小系统的工程文件。 2、完成原理图后续工作:打开原理图文件,双击元件“CH340X”窗口右边弹出元件内部属性设置界面,在窗口下方点击“Footprint ->Add…”按钮进入添加元件类型界面,进入元件封装选择界面&…

红日靶场复现1

红日靶场复现1🎈🎈🎈🎈🎉🎉🎉🎉🎉🎉🎈🎈🎉🎈🎈🎉 一、主机发现🎈&#x1…

Http长连接同一个socket多个请求和响应如何保证一一对应?

HTTP/2引入二进制数据帧和流的概念,其中帧对数据进行顺序标识,如下图所示,这样浏览器收到数据之后,就可以按照序列对数据进行合并,而不会出现合并后数据错乱的情况。同样是因为有了序列,服务器就可以并行的…

【MySQL-->数据操作】

文章目录 前言一、insert1.单行插入2.多行插入3.插入更新/替换 二、select1.全列查询2.指定列插入3.列别名4. 表达式计算5.去重6.where条件查询7.排序8.limit分页显示 三、update四、delete五、插入查询结果六、聚合函数六、聚合分组1.格式2.where和having的区别 前言 一、inse…

深入理解Redis集群模式、协议、元数据维护方式

文章目录 🍊 集群模式🍊 集群协议🍊 元数据维护方式🎉 集中式🎉 gossip 协议 📕我是廖志伟,一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出…

nginx中gzip推荐配置

#开启gzip压缩功能 gzip on; #设置允许压缩的页面最小字节数; 这里表示如果文件小于10个字节,就不用压缩,因为没有意义,本来就很小. gzip_min_length 10k; #设置压缩缓冲区大小,此处设置为4个16K内存作为压缩结果流缓存 gzip_buffers 4 16k;#压缩版本 gzip_http_version 1…

零基础Linux_19(进程信号)产生信号+Core_Dump+保存信号

目录 1. 信号前期知识 1.1 生活中的信号 1.2 Linux中的信号 1.3 信号概念 1.4 信号处理方法的注册 2. 产生信号 2.1 通过终端按键产生信号 2.2 调用系统调用向进程发信号 2.3 软件条件产生信号 2.4 硬件异常产生信号 3. 核心转储Core Dump 4. 保存信号 4.1 信号在…

尚硅谷kafka3.0.0

目录 💃概述 ⛹定义 ​编辑⛹消息队列 🤸‍♂️消息队列应用场景 ​编辑🤸‍♂️两种模式:点对点、发布订阅 ​编辑⛹基本概念 💃Kafka安装 ⛹ zookeeper安装 ⛹集群规划 ​编辑⛹流程 ⛹原神启动 🤸‍♂️…

Windows网络监视工具

对于任何规模的企业来说,网络管理在信息技术中都起着至关重要的作用。管理、监控和密切关注网络基础设施对任何组织都至关重要。在Windows网络中,桌面,服务器,虚拟服务器和虚拟机(如Hyper-V)在Windows操作系…

C算法:写一个用于找出数组的最大值和最小值的函数

需求&#xff1a; 写一个用于找出数组的最大值和最小值的函数。 示例&#xff1a;int array[9] {5, 9, 3, 1, 2, 8, 4, 7, 6}; 该数组最大值的下标为1&#xff0c;最小值的小标为3。 代码实现&#xff1a; #include <stdio.h>int getNum(int *array,int len,int (*…

【C++面向对象】6. 指向类的指针

文章目录 【 1. 基本原理 】【 2. 实例 】 【 1. 基本原理 】 一个指向 C 类的指针与指向结构体的指针类似&#xff0c;访问指向类的指针的成员&#xff0c;需要使用 成员访问运算符 ->&#xff0c;就像访问指向结构的指针一样。 【 2. 实例 】 // 使用指向类的指针&…

PX4-Autopilot下载与编译

文章目录 1 Git clone 代码2 下载子模块3 编译4 可能遇到的问题参考 1 Git clone 代码 Github Repository 链接&#xff1a;PX4-Autopilot 查看现有版本&#xff1a; 在终端用命令下载&#xff0c;-b表示branch git clone -b v1.14.0 https://github.com/PX4/PX4-Autopilot.…

win10下u2net tensorrt模型部署

TensorRT系列之 Win10下yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov8 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov7 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov6 tensorrt模型加速部署 TensorRT系列之 Linux下 yolov5 tensorrt模型加速部署…