python计算机视觉学习笔记——PIL库的用法

如果需要处理的原图及代码,请移步小编的GitHub地址

传送门:请点击我

如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice

这个是之前的笔记,自己看到了就顺带发出来,也是温习一下,内容可能不太全,算是入门贴吧。

前言:PIL

图像处理是计算机视觉领域中不可或缺的一部分,而PIL(Python Imaging Library)库和OpenCV(Open Source Computer Vision Library)是两个常用的工具。今天这里主要学习以下PIL库,PIL 是一个用于图像处理的 Python 库,提供了丰富的图像处理功能。它包含了处理图像的各种工具和算法,可以进行图像的打开、保存、剪裁、旋转、缩放等操作。

PIL(Python Imaging Library)和 OpenCV 都是用于图像处理的强大库,它们各自有着不同的优势和适用场景。以下是一些导致 PIL 仍然被使用的原因:

1,PIL的优点

  1. 易用性:PIL库的API设计得非常简洁明了,即使是编程新手也能快速上手。例如,你只需要一行代码就可以打开一个图像文件,然后再用一行代码就可以将图像保存到新的文件中。
  2. 功能强大:PIL库提供了丰富的图像处理功能,包括基本的图像操作(如裁剪、旋转、缩放等),图像滤镜,以及更高级的功能(如图像增强、色彩空间转换等)。
  3. 支持多种图像格式:PIL库支持多种常见的图像格式,包括JPEG、PNG、BMP、GIF、PPM、TIFF等。这意味着你可以使用PIL库来处理几乎所有类型的图像文件。
  4. 文字和绘图功能:PIL允许在图像上添加文字、绘制几何图形和绘制曲线,这对于图像注释和标记非常有帮助。
  5. 扩展功能:PIL还支持各种扩展功能,如图像滤波、直方图均衡化和颜色空间转换等。

2,PIL 的缺点

  1. 性能:虽然PIL库的功能强大,但是它的性能并不是最优的。如果你需要处理大量的图像,或者进行复杂的图像处理操作,可能会发现PIL库的速度不尽如人意。
  2. 不支持一些高级功能:虽然PIL库提供了丰富的图像处理功能,但是它并不支持一些高级的图像处理操作,如特征检测、图像分割等。如果你需要进行这些操作,可能需要使用其他的图像处理库,如OpenCV。

3,PIL 库和OpenCV的区别

  1. 编程语言:PIL库是用纯Python编写的,而OpenCV主要是用C++编写的,并提供了Python的接口。如果您更熟悉Python,并且希望使用Python进行图像处理,那么PIL可能更适合您。并且PIL 的接口相对较为简单,特别适合一些简单的图像处理任务。对于一些不需要太多高级功能的应用,PIL 提供了直观的方法和易于使用的 API。
  2. 功能和算法:OpenCV提供了更丰富和先进的图像处理算法和函数,涵盖了从基本操作到高级计算机视觉任务的各个方面。而PIL 在功能上相对轻量,适合一些小型项目或者只需要进行基本图像处理的场景。如果你的需求主要是一些简单的图像操作,PIL 可能是更轻便的选择。
  3. 性能:由于OpenCV是用C++编写的,因此在处理大型图像和复杂计算任务时具有较高的性能优势。PIL库在处理大型图像时可能效率稍低。
  4. 生态系统:OpenCV拥有庞大的社区支持和丰富的文档资源,可以帮助您解决问题和学习。而PIL库的社区活动相对较少,文档资源相对较少。

4,如何使用PIL库

首先是安装,比较简单:

复制代码
pip install pillow

下面是一个简单的示例,演示了如何使用PIL库来打开一个图像文件,然后将图像转换为灰度图,并保存到新的文件中:

复制代码
from PIL import Image

# 打开图像文件
img = Image.open('input.jpg')

# 将图像转换为灰度图
img_gray = img.convert('L')

# 保存图像到新的文件
img_gray.save('output.jpg')

虽然 OpenCV 在计算机视觉和更复杂的图像处理任务中表现得非常强大,但选择使用哪个库通常取决于具体的需求和项目特点。在一些情况下,PIL 可能更为合适,而在其他情况下,特别是涉及到计算机视觉领域的任务,OpenCV 可能更具优势。

总体来说,网上开源的一些计算机视觉中也使用PIL加载图像,所以有不得不学习的理由,话不多说,开干:

一:pillow模块的基本概念

Pillow的官网地址:https://pillow.readthedocs.io/en/stable/,其实打开后,什么都有,只是都是英文,对于部分同学不方面而已。

PIL:Python Imaging Library,已经是Python平台上的图像处理标准库了。由于PIL仅支持到Python2.7 ,加上年久失修,于是一群志愿者在PIL的基础上创建了兼容的版本,名字叫Pillow,支持最新版本的Python3.X,又加了许多新特性。因此,我们可以直接安装使用Pillow。

PIL中所涉及的基本概念有如下几个:通道(bands)、模式(mode)、尺寸(size)、坐标系统(coordinate system)、调色板(palette)、信息(info)和滤波器(filters)。

1.1 通道------Image.getbands

每张图片都是由一个或者多个数据通道构成。PIL允许在单张图片中合成相同维数和深度的多个通道。

以RGB图像为例,每张图片都是由三个数据通道构成,分别为R、G和B通道。而对于灰度图像,则只有一个通道。

对于一张图片的通道数量和名称,可以通过方法getbands()来获取。方法getbands()是Image模块的方法,它会返回一个字符串元组(tuple)。该元组将包括每一个通道的名称。

Python的元组与列表类似,不同之处在于元组的元素不能修改,元组使用小括号,列表使用方括号,元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可。

方法getbands()的使用如下:

复制代码
from PIL import Image
im = Image.open("test.png")
print(im.getbands())
输出:
('R', 'G', 'B')

1.2 模式------Image.mode

图像的模式定义了图像的类型和像素的位宽。当前支持如下模式:

复制代码
1:1位像素,表示黑和白,但是存储的时候每个像素存储为8bit。

L:8位像素,表示黑和白。

P:8位像素,使用调色板映射到其他模式。

RGB:3x8位像素,为真彩色。

RGBA:4x8位像素,有透明通道的真彩色。

CMYK:4x8位像素,颜色分离。

YCbCr:3x8位像素,彩色视频格式。

I:32位整型像素。

F:32位浮点型像素。

PIL也支持一些特殊的模式,包括RGBX(有padding的真彩色)和RGBa(有自左乘alpha的真彩色)。

可以通过mode属性读取图像的模式。其返回值是包括上述模式的字符串。

属性mode的使用如下:

复制代码
from PIL import Image
im = Image.open("test.png")
print(im.mode)
输出:
'RGB'

1.3 尺寸------Image.size

通过size属性可以获取图片的尺寸。这是一个二元组,包含水平和垂直方向上的像素数。

属性mode的使用如下:

复制代码
from PIL import Image
im = Image.open("test.png")
print(im.size)
输出:
(670, 502)

1.4 坐标系统

在PIL(或Pillow)中,图像的坐标系统遵循常见的数学坐标系,其中左上角是原点(0, 0),x轴向右增长,y轴向下增长。这意味着图像的左上角具有坐标 (0, 0),而右下角的坐标是 (width-1, height-1)

以下是一个简单的示例说明PIL的坐标系统:

复制代码
from PIL import Image, ImageDraw


# 创建一个白色背景的图像
width, height = 200, 100
image = Image.new("RGB", (width, height), "yellow")

# 创建一个ImageDraw对象,即获取图像的绘制对象
draw = ImageDraw.Draw(image)

# 在图像中心绘制一个红色矩形
rect_width, rect_height = 50, 30
left = 0
top = (height - rect_height) // 2
right = left + rect_width
bottom = top + rect_height

draw.rectangle([left, top, right, bottom], fill="red")

# 保存图像
# image.save("coordinate_example.png")

# 显示图像
image.show()


# 显示坐标系
print(f"左上角坐标:(0, 0)")
print(f"右下角坐标:({width-1}, {height-1})")


# 输出结果
# 左上角坐标: (0, 0)
# 右下角坐标:( 199, 99)

输出图像:

1.5 调色板------Image.palette

在PIL(Python Imaging Library)中,调色板(Palette)是一种用于存储和管理颜色映射的机制。调色板通常与图像的索引颜色模式一起使用,这意味着图像的每个像素值不直接表示颜色,而是作为索引来查找调色板中的实际颜色。

以下是有关调色板的一些重要概念和说明:

  1. 索引颜色模式:

    • 在索引颜色模式中,图像的每个像素值都是一个索引,该索引对应于调色板中的颜色。
    • 通常,索引颜色模式用于节省存储空间,特别是对于包含有限颜色集的图像。
  2. 调色板的组成:

    • 调色板是一个包含颜色信息的数据结构,通常由颜色元组组成。颜色元组可以是RGB(红、绿、蓝)格式,也可以是其他颜色表示格式。
    • 对于每个索引,调色板中都有一个与之对应的颜色。
  3. 使用调色板的图像格式:

    • 一些常见的使用调色板的图像格式包括GIF和PNG-8。这些格式在保存图像时使用调色板,而不是直接存储每个像素的完整颜色信息。
  4. 图像的调色板属性:

    • PIL中的图像对象具有调色板属性,通过该属性可以获取和设置图像的调色板。
    • 使用 image.getpalette() 方法可以获取图像的调色板,而 image.putpalette() 方法可以设置调色板。

以下是一个简单的示例,演示如何使用PIL中的调色板:

复制代码
from PIL import Image

# 创建一个调色板
palette = [255, 0, 0,  # Red
           0, 255, 0,  # Green
           0, 0, 255]  # Blue

# 创建一个8x8的图像,使用调色板和索引颜色模式
image = Image.new("P", (8, 8))
image.putpalette(palette)

# 设置图像的像素值(索引)
pixels = [0, 1, 2, 0, 1, 2, 0, 1,
          1, 2, 0, 1, 2, 0, 1, 2,
          2, 0, 1, 2, 0, 1, 2, 0,
          0, 1, 2, 0, 1, 2, 0, 1,
          1, 2, 0, 1, 2, 0, 1, 2,
          2, 0, 1, 2, 0, 1, 2, 0,
          0, 1, 2, 0, 1, 2, 0, 1,
          1, 2, 0, 1, 2, 0, 1, 2]

image.putdata(pixels)

# 显示图像
image.show()

这个例子创建了一个调色板,然后使用索引颜色模式创建了一个8x8的图像,并通过设置像素值(索引)来使用调色板中的颜色。

1.6 信息------Image.info

使用info属性可以为一张图片添加一些辅助信息。这个是字典对象。加载和保存图像文件时,多少信息需要处理取决于文件格式。

属性info的使用如下:

复制代码
from PIL import Image
im = Image.open("test.jpg")
print(im.info)
输出:
{'jfif': 257, 'jfif_version': (1, 1), 'jfif_unit': 0, 'jfif_density': (1, 1)}

1.7 滤波器

对于将多个输入像素映射为一个输出像素的几何操作,PIL提供了四个不同的采样滤波器。

复制代码
NEAREST:最近滤波。从输入图像中选取最近的像素作为输出像素。它忽略了所有其他的像素。

BILINEAR:双线性滤波。在输入图像的2x2矩阵上进行线性插值。
注意:PIL的当前版本,做下采样时该滤波器使用了固定输入模板。

BICUBIC:双立方滤波。在输入图像的4x4矩阵上进行立方插值。
注意:PIL的当前版本,做下采样时该滤波器使用了固定输入模板。

ANTIALIAS:平滑滤波。这是PIL 1.1.3版本中新的滤波器。对所有可以影响输出像素
的输入像素进行高质量的重采样滤波,以计算输出像素值。在当前的PIL版本中,这个滤
波器只用于改变尺寸和缩略图方法。
注意:在当前的PIL版本中,ANTIALIAS滤波器是下采样(例如,将一个大的图像转换为
小图)时唯一正确的滤波器。BILIEAR和BICUBIC滤波器使用固定的输入模板,用于固
定比例的几何变换和上采样是最好的。

Image模块中的方法 resize() 和 thumbnail()用到了滤波器。

方法resize() 的使用如下:

复制代码
方法resize()的定义为:resize(size, filter=None)=> image
from PIL import Image
im = Image.open("test.png")
print(im.size)
im_resize = im.resize((256,256))
print(im_resize.size)
输出:
(670, 502)
(256,256)

对参数filter不赋值的话,方法resize()默认使用NEAREST滤波器。如果要使用其他滤波器可以通过下面的方法来实现:

复制代码
from PIL import Image
im = Image.open("test.png")
print(im.size)
im_resize0 = im.resize((256,256), Image.BILINEAR)
print(im_resize0.size)
im_resize1 = im.resize((256,256), Image.BICUBIC)
print(im_resize1.size)
im_resize2 = im.resize((256,256), Image.ANTIALIAS)
print(im_resize2.size)

输出:
(670, 502)
(256,256)
(256,256)
(256,256)

2,Image对象

2.1 实例化对象

直接读取图片

复制代码
from PIL import Image

# 导入图像
img_path = r"book.png"
img = Image.open(img_path)

# 展示图像
im.show()

2.2 格式转换------save方法

save方法用于保存图像,当不指定文件格式时,它会以默认的图片格式来存储;如果指定图片格式,则会以指定的格式存储图片,语法如下:

复制代码
im = PIL.Image.open(r"book.jpg")

# 保存图片
# fp: 图片的存储路径,包含图片的名称,字符串格式
fp = "book_save.jpg"  
# format:可选参数,可以指定图片的格式
im.save(fp, format=None)  

2.3 格式转换------Convert方法

**注意:**并非所有的图片格式都可以用 save() 方法转换完成,比如将 PNG 格式的图片保存为 JPG 格式,如果直接使用 save() 方法就会出现错误,引发错误的原因是由于 PNG 和 JPG 图像模式不一致导致的。其中 PNG 是四通道 RGBA 模式,即红色、绿色、蓝色、Alpha 透明色;JPG 是三通道 RGB 模式。因此要想实现图片格式的转换,就要将 PNG 转变为三通道 RGB 模式。

Image 类提供的 convert() 方法可以实现图像模式的转换。该函数提供了多个参数,比如 mode、matrix、dither 等,其中最关键的参数是 mode,其余参数无须关心

语法:

复制代码
im.convert(mode, params)  # 转换模式
im.save(fp)  # 保存图片

2.4 图像缩放

在图像处理过程中经常会遇到缩小或放大图像的情况,Image 类提供的 resize() 方法能够实现任意缩小和放大图像

语法:

复制代码
im_new = im.resize(size, resample=image.BICUBIC, box=None, reducing_gap=None)  
 
# 缩放后的图片
im_new.show() 

2.5 图像的分离和合并

图像(指数字图像)由许多像素点组成,像素是组成图像的基本单位,而每一个像素点又可以使用不同的颜色,最终呈现出了绚丽多彩的图像 ,而图像的分离与合并,指的就是图像颜色的分离和合并

图像分离:split方法

示例:

复制代码
im = PIL.Image.open(r"magic_h03.jpg")

# split 方法使用较简单,分离通道
r, g, b = im.split()  
r.show()
g.show()
b.show()

图像合并:merge方法

Image 类提供的 merge() 方法可以实现图像的合并操作。注意,图像合并,可以是单个图像合并,也可以合并两个以上的图像

示例:

复制代码
im_merge = PIL.Image.merge(mode, bands)
im_merge.show()

图像合并:blend方法

Image 类也提供了 blend() 方法来混合 RGBA 模式的图片(PNG 格式)

语法:

复制代码
PIL.Image.blend(image1,image2, alpha)

2.6 图像裁剪

Image 类提供的 crop() 函数允许我们以矩形区域的方式对原图像进行裁剪

语法:

复制代码
im_crop = im.crop(box=None)  # box 代表裁剪区域
im_crop.show()

box 是一个有四个数字的元组参数 (x_左上,y_左下,x1_右上,y1_右下),分别表示被裁剪矩形区域的左上角 x、y 坐标和右下角 x,y 坐标。默认 (0,0) 表示坐标原点,宽度的方向为 x 轴,高度的方向为 y 轴,每个像素点代表一个单位

3,代码实战

3.1 图像的属性的打印示例

注意:源文件的文件格式。如果是由PIL创建的空图像,则其文件格式为None,即 im.format ⇒ string or None

示例代码如下:

复制代码
import PIL.Image

im = PIL.Image.open(r"harden.png")

print(im.size)  # 查看图片大小, 按照像素数计算。它的返回值为宽度和高度的二元组(width, height)
print(im.readonly) # 查看是否为只读,1为是,0为否 print(im.format) # 查看图片的格式, 输出为 'png'
print(im.info) # 查看图片的相关信息 print(im.mode) # 查看图片的模式

print(im.mode)  # 表明图像所使用像素格式, 属性典型的取值为“1”,“L”,“RGB”或“CMYK”
print(im.palette)  # 颜色调色板表格。如果图像的模式是“P”,则返回ImagePalette类的实例;否则,将为None。

3.2 使用PIL进行灰度化+二值化

代码如下:

复制代码
from PIL import Image

#  load a color image
im = Image.open('durant.jpg' )

#  convert to grey level image
Lim = im.convert('L' )
Lim.save('grey.jpg' )

#  setup a converting table with constant threshold
threshold = 185
table = []
for i in range(256):
    if i < threshold:
        table.append(0)
    else:
        table.append(1)

# convert to binary image by the table
bim = Lim.point(table, '1' )

bim.save('durant_grey.jpg' )

原图图片效果展示:

灰度化图片效果展示:

二值化图片效果展示:

3.2 图像转换示例

代码如下:

复制代码
例子1:
from PIL import Image
im1 = Image.open("jing.jpg")
print(im1.mode)
im_c = im1.convert("1")
im_c.save("he.jpg")
print(im_c.mode)
输出:
注:将“RGB”模式的im01图像,转换为“1”模式的im_c图像。

 
定义3:im.convert(mode,matrix) ⇒ image
含义3:使用转换矩阵将一个“RGB”图像转换为“L”或者“RGB”图像。变量matrix为4或者16元组。
例子3:下面的例子将一个RGB图像(根据ITU-R709线性校准,使用D65亮度)转换到CIE XYZ颜色空间:
from PIL import Image
im1 = Image.open("jing.jpg")
im1.mode
rgb2xyz = (
    0.412453, 0.357580, 0.180423, 0,
    0.212671, 0.715160, 0.072169, 0,
    0.019334, 0.119193, 0.950227, 0 )
im_c3 = im1.convert("L", rgb2xyz)
im_c3.save("he.jpg")
print(im_c3.mode)
输出:
L

相关推荐
菜鸟‍4 小时前
【论文学习】2025年图像处理顶会论文
图像处理·人工智能·学习
七芒星20232 天前
多目标识别YOLO :YOLOV3 原理
图像处理·人工智能·yolo·计算机视觉·目标跟踪·分类·聚类
2401_841495644 天前
【计算机视觉】分水岭实现医学诊断
图像处理·人工智能·python·算法·计算机视觉·分水岭算法·医学ct图像分割
格林威4 天前
常规可见光相机在工业视觉检测中的应用
图像处理·人工智能·数码相机·计算机视觉·视觉检测
扶尔魔ocy4 天前
【QT常用技术讲解】multimedia实现指定分辨率打开摄像头
图像处理·qt
格林威4 天前
工业视觉检测里的 “柔性” 是什么?
图像处理·人工智能·深度学习·yolo·计算机视觉·视觉检测
格林威4 天前
不同光谱的工业相机有哪些?能做什么?
图像处理·人工智能·深度学习·数码相机·计算机视觉·视觉检测
CiLerLinux4 天前
第三十八章 ESP32S3 SPIFFS 实验
图像处理·人工智能·单片机·嵌入式硬件
要做朋鱼燕4 天前
【OpenCV】图像处理入门:从基础到实战技巧
图像处理·人工智能·opencv
不枯石4 天前
Matlab通过GUI实现点云的随机一致性(RANSAC)配准
开发语言·图像处理·算法·计算机视觉·matlab