Python 图像处理库之PIL & Pillow

PIL(Python Image Library),Python 平台事实上的图像处理标准库。PIL 仅支持到 Python 2.7,故python3用的是PIL的兼容版本Pillow。以下统称PIL。

一、功能与模块组成

PIL库包括21个与图片相关的类,支持多种图像存储、显示和处理功能。具体包括:
——图像存储(Image Archives)。PIL非常适合于图像归档以及图像的批处理任务,如创建缩略图、转换图像格式、打印图像等等。
——图像显示(Image Display)。PIL支持众多的GUI框架接口,可以用于图像展示,包括Tk PhotoImage,BitmapImage还有Windows DIB等接口。
——图像处理(Image Processing)。PIL支持图像剪切、粘贴、镜像、缩放、旋转、增强,水印、颜色块、滤镜,图像格式转换、色场空间转换,验证码、直方图处理、插值和滤波等支持对点的处理,使用众多的卷积核(convolution kernels)做过滤(filter),还有颜色空间转换。PIL直方图方法能够展示图像统计特性,可以用来实现图像的自动对比度增强,还有全局的统计分析等。

主要模块包括:Image模块、ImageChops模块、ImageCrackCode模块、ImageDraw模块、ImageEnhance模块、ImageFile模块、ImageFileIO模块、ImageFilter模块、ImageFont模块、ImageGrab模块、ImageOps模块、ImagePath模块、ImageSequence模块、ImageStat模块、ImageTk模块、ImageWin模块、PSDraw模块

最常用的模块:Image模块

二、基本操作

使用

在日常应用过程中,使用最多的是 Pillow 提供的 Image 模块,其提供了包括图像存储、变换以及一系列的相关处理功能。Pillow 使用 Image 对象来表示图像对象并基于其定义图像的属性信息以及可针对其进行的操作,后续即主要介绍通过 Image 对象可进行的图像操作。在 Python 中使用时,用户首先需从 PIL 中导入对应的 Image 模块。

1

from PIL import Image #通过 Image 进行图像处理相关的操作

图像读取与存储

通过 Image 提供的 open 方法读取图像,其以指定的文件名为参数,返回值为对应图像的 Image 对象,后续即可针对图像对应的 Image 对象进行操作。

1

im = Image.open( "test.png" # open 方法以图像名(或图像对象)为参数,返回一个 Image 对象

通过 Image 对象的 save 方法存储图像对象,其使用存储目标文件名为参数,也可通过 format 参数指定存储文件的格式。

1

2

im.save( "test.png" )          # im 为 Image 对象,其被保存至 test.png,不指定 format 参数时,该方法通过文件后缀推测文件类型

im.save( "test.jpg" , format="JPEG"# 以 JPEG 格式保存 Image 对象 im 至文件 test.jpg 中

基本属性

图像对应的 Image 对象具备基本属性。用户可以通过这些属性获得图像最基本的信息,Image 对象的完整属性信息可以查看这里。

1

2

3

im.filename    # Image 对象 im 对应的文件/路径名

im.mode      # Image 对象图像数据的解释方式,如灰度图为 “L”,彩色图为 “RGB”等

im.size      # 返回图像的尺寸信息,为( width , height ) 格式的元祖

图像类型转换

不同的图像数据具有不同的图像格式,进而拥有不同的组织数据的方式。对于 RGB 图像而言,图像拥有 R、G、B 三个通道,像素数据由三个对应三通道的 8 bit 数据组成;对于黑白图像而言,其每个像素由一个 8 bit 字节表示等等。在打开图像时,open 方法会自动解析图像的格式,用户可通过 Image 对象的 mode 属性获得图像的状态。

Image 对象可通过 convert 方法进行图像类型间的转换,其使用转换的目标类型的字符串为参数,返回转换后的 Image 对象,常见的类型包括 RGB(真彩)、L(黑白)、YCbCr(视频图像)、HSV(色调饱和度亮度彩色空间)。

1

data = im.convert( "L" )    #获得 RGB 图像 im 的灰度图

与 numpy 数组的转换

在程序中,一般使用图像对应的 Image 对象进行图像相关的操作,针对图像数据本身的计算处理一般将 Image 对象的数据转换为 numpy 数据后进行,处理完成之后的 numpy 数据再被转换为 Image 对象进行保存。

a. 将 Image 对象转换为 numpy 数组

使用 numpy.asarray 方法( 不唯一,可参见 Array creation routines )将 Image 对象的数据转换为 numpy 数组,进而可以对其进行计算处理。转换后 numpy 数组的数据类型根据 Image 数据对象本身的数据类型推断获得,使用时也可使用 numpy.asarray 的 dtype 参数指定转换后的数据类型。  

1

2

3

im = Image.open( "test.png" )         #打开图像 test.png ,并获得其对应的 Image 对象

data = numpy.asarray( im )           #将 Image 对象 im 的数据转换为 numpy 数组的形式,data 即为可供运算的 numpy 数组

data = numpy.asarray( im, dtype=np.uint8 )   #转换图像数据为 numpy 数组,并指定其类型为 np.uint8

b.将 numpy 数组转换为 Image 对象

对于 numpy 数据形式的图像数据( 通过数据处理或其他途径获得 ),可通过 Image.fromarray 方法将已有的 numpy 图像数据转换为 Image 对象。

1

im = Image.fromarray( data ) # data 为 numpy 数组,im 为转换获得的 Image 对象

注意,在使用 Image.fromarray 方法时可能会出现报错 raise TypeError("Cannot handle this data type") , 这是由于待转换的 numpy 数据类型可能并不符合 Image 对象所需的数据类型( 一般为 8 bit 无符号值 ),解决方法是在转换前先将 numpy 数组的数据类型转换为 np.uint8 .

1

im = Image.fromarray( data.astype( np.uint8 ) )  #将 numpy 数组的数据类型转换为 np.uint8 后再转换为 Image 对象

常用操作

裁剪图像——crop

可以使用 crop 方法获得图像的指定部分。crop 方法以指定 ( 左,上,右,下 ) 切割位置的元祖来定义待分割的图像部分,可以理解为定义的是切割获得的矩形的左上角和右下角位置的坐标。在 PIL 所支持的坐标系统中,坐标的( 0 , 0 ) 为图像的左上角,注意 ( 0 , 0 ) 指向的不是左上角的第一个像素,而是该像素位置前的位置,后续所有的坐标均为像素间的空隙位置,而不是指向像素。也就是说,第一个像素被 ( 0 , 0 ) 和 ( 0 , 1 ) 两个坐标左右包围。  

1

part = im.crop( ( 0 , 0 , 100 , 100 ) ) #截取获得图像 im 左上角大小为 100 × 100 像素的矩形图像

通道处理——split / getchannel

split 方法将图像数据按通道分离,其返回值为包含各个通道分离数据的元组tuple,如对于 RGB 图像而言,其被分成 R、G、B 三个通道的数据。

1

R, G, B = im.split() # im 为真彩色 Image 对象,其被分为独立的 R、G、B 通道信息

getchannel 方法以图像的通道的索引或字符名字为参数,返回包含有对应通道数据的 L 类型的图像( 即为黑白模式 )。  

1

2

R = im.getchannel( 0 )  # 获得 RGB 图像的第一个通道的数据,即 R 通道信息

R = im.getchannel( "R" ) #同上

缩放图像——resize

resize 方法以缩放目标图像大小的元祖( Width, Heigth ) 为参数,通过指定的采样方法将图像缩放为指定的图像大小。其支持采样的方法包括 PIL.Image.NEAREST、PIL.Image.BILINEAR、PIL.Image.BICUBIC 等,resize 支持的全部采样方式见文档。注意,以上采样方法的全名为 PIL.Image.xxxx,但实际上由于之前已经使用 from PIL import Image 导入了 Image 这个模块名,故而后续可以直接使用 Image.xxxx 的形式调用上述方法,反之,在未导入模块名时需使用完整的名称来使用上述方法,下同。

1

2

data = im.resize( ( 100, 100 ) )             #将 im 对应的 Image 对象缩放为 100×100 的大小,默认采用 PIL.Image.NEAREST 方法

data = im.resize( ( 100, 100 ), Image.BICUBIC )     #使用 PIL.Image.BICUBIC 方法进行采样

翻转图像——rotate/transpose

通过 rotate 方法旋转图像,rotate 方法以旋转的角度为参数,将图像顺时针中心旋转对应的度数,并返回对应的 Image 对象。注意,通过 rotate 方法进行旋转时,结果图像是中心旋转后图像在源图像大小范围内被截取的部分,其他部分为填充。如大小为宽×高 200 * 100 的图像,经过 90 度旋转后,其大小仍为 200 * 100 ,图像内容为旋转后的理论为 100 * 200 的图像与原 200 * 100 区域的重合部分,其余部分为填充。

rotate 方法可以指定 expand 参数为 1 ,此时生成的新图像为完整包含有旋转后图像内容的最小矩形大小( 空白处为填充),如上例中,图像经过 90 度旋转后,获得的新图像的大小即为 100 * 200。更多介绍见 Image.rotate.

1

2

data = im.rotate( 90 ) #将图像顺时针旋转 90 度

data = im.rotate( 90 , expand=1 ) #将图像顺时针旋转 90 度,同时保留图像的完整内容

在某些图像训练的数据生成中,将图像进行 90 度为单位的旋转、上下或左右翻转是更为常见的操作。此时可以使用 transpose 方法,transpose 以翻转方式为参数,返回经过翻转后的图像,其支持的参数如下所示。

1

2

3

4

5

6

7

PIL.Image.FLIP_LEFT_RIGHT  #左右翻转图像

  PIL.Image.FLIP_TOP_BOTTOM  #上下翻转图像

  PIL.Image.ROTATE_90

  PIL.Image.ROTATE_180

  PIL.Image.ROTATE_270     #顺时针旋转对应度数

  PIL.Image.TRANSPOSE     #类似于左右翻转后再逆时针旋转图像 90 度

  PIL.Image.TRANSVERSE     #类似与左右翻转后再顺时针旋转图像 90 度

可以直接使用上述参数对图像进行变换,transpose 方法返回变换后的完整图像( 由于是 90 度倍数的变换,也不存在空白区域 )。

1

data = im.transpose( Image.FLIP_LEFT_RIGHT ) #获得 im 图像经过左右旋转后的数据 

format

format属性定义了图像的格式,如果图像不是从文件打开的,那么该属性值为None;size属性是一个tuple,表示图像的宽和高(单位为像素);mode属性为表示图像的模式,常用的模式为:L为灰度图,RGB为真彩色,CMYK为pre-press图像。如果文件不能打开,则抛出IOError异常。

1

print(im.format, im.size, im.mode)

save

1

im.save("c:\\")

convert()

convert() 是图像实例对象的一个方法,接受一个 mode 参数,用以指定一种色彩模式,mode 的取值可以是如下几种:
· 1 (1-bit pixels, black and white, stored with one pixel per byte)
· L (8-bit pixels, black and white)
· P (8-bit pixels, mapped to any other mode using a colour palette)
· RGB (3x8-bit pixels, true colour)
· RGBA (4x8-bit pixels, true colour with transparency mask)
· CMYK (4x8-bit pixels, colour separation)
· YCbCr (3x8-bit pixels, colour video format)
· I (32-bit signed integer pixels)
· F (32-bit floating point pixels)

1

im = Image.open('1.png').convert('L')

Filter

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

from PIL import Image, ImageFilter

im = Image.open(‘1.png')

# 高斯模糊

im.filter(ImageFilter.GaussianBlur)

# 普通模糊

im.filter(ImageFilter.BLUR)

# 边缘增强

im.filter(ImageFilter.EDGE_ENHANCE)

# 找到边缘

im.filter(ImageFilter.FIND_EDGES)

# 浮雕

im.filter(ImageFilter.EMBOSS)

# 轮廓

im.filter(ImageFilter.CONTOUR)

# 锐化

im.filter(ImageFilter.SHARPEN)

# 平滑

im.filter(ImageFilter.SMOOTH)

# 细节

im.filter(ImageFilter.DETAIL)

查看图像直方图

1

im.histogram()

转换图像文件格式

1

2

3

4

5

6

7

def img2jpg(imgFile): 

   if type(imgFile)==str and imgFile.endswith(('.bmp', '.gif', '.png')):

     with Image.open(imgFile) as im:

       im.convert('RGB').save(imgFile[:-3]+'jpg'

 img2jpg('1.gif')

 img2jpg('1.bmp')

 img2jpg('1.png')

屏幕截图

1

2

3

from PIL import ImageGrab

im = ImageGrab.grab((0,0,800,200)) #截取屏幕指定区域的图像

im = ImageGrab.grab() #不带参数表示全屏幕截图

图像裁剪与粘贴

Python 图像处理库之PIL & Pillow_第1张图片

1

2

3

4

box = (120, 194, 220, 294) #定义裁剪区域

region = im.crop(box) #裁剪

region = region.transpose(Image.ROTATE_180)

im.paste(region,box) #粘贴

图像缩放

1

im = im.resize((100,100)) #参数表示图像的新尺寸,分别表示宽度和高度

图像对比度增强

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

from PIL import Image

from PIL import ImageEnhance

#原始图像

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

image.show()

#亮度增强

enh_bri = ImageEnhance.Brightness(image)

brightness = 1.5

image_brightened = enh_bri.enhance(brightness)

image_brightened.show()

#色度增强

enh_col = ImageEnhance.Color(image)

color = 1.5

image_colored = enh_col.enhance(color)

image_colored.show()

#对比度增强

enh_con = ImageEnhance.Contrast(image)

contrast = 1.5

image_contrasted = enh_con.enhance(contrast)

image_contrasted.show()

#锐度增强

enh_sha = ImageEnhance.Sharpness(image)

sharpness = 3.0

image_sharped = enh_sha.enhance(sharpness)

image_sharped.show()

Image模块用法介绍

1. 简介。

图像处理是一门应用非常广的技术,而拥有非常丰富第三方扩展库的 Python 当然不会错过这一门盛宴。PIL (Python Imaging Library)是 Python 中最常用的图像处理库,目前版本为 1.1.7,我们可以 在这里 下载学习和查找资料。

Image 类是 PIL 库中一个非常重要的类,通过这个类来创建实例可以有直接载入图像文件,读取处理过的图像和通过抓取的方法得到的图像这三种方法。

2. 使用。

导入 Image 模块。然后通过 Image 类中的 open 方法即可载入一个图像文件。如果载入文件失败,则会引起一个 IOError ;若无返回错误,则 open 函数返回一个 Image 对象。现在,我们可以通过一些对象属性来检查文件内容,即:

1

2

3

4

>>> import Image

>>> im = Image.open("j.jpg")>>> im.show()

>>> print im.format, im.size, im.mode

JPEG (440, 330) RGB

这里有三个属性,我们逐一了解。

format : 识别图像的源格式,如果该文件不是从文件中读取的,则被置为 None 值。

size : 返回的一个元组,有两个元素,其值为象素意义上的宽和高。

mode : RGB(true color image),此外还有,L(luminance),CMTK(pre-press image)。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

from PIL import Image

from PIL import ImageEnhance

import pytesseract

import re

pytesseract.pytesseract.tesseract_cmd = 'D:\\Program Files\\Tesseract-OCR\\tesseract.exe'

tessdata_dir_config = '--tessdata-dir "D:\\Program Files\\Tesseract-OCR\\tessdata"'

im=Image.open("./img/10.jpg")

im=im.convert('L')

im.show()

im=ImageEnhance.Contrast(im)

im=im.enhance(1)

#im = im.resize((300, 90))

ltext = pytesseract.image_to_string(im)

ltext = re.sub("\W", "", ltext)

im.show()

print(ltext)

#print(pytesseract.image_to_string(im))

#print(pytesseract.image_to_boxes(im))

#print(im.format, im.size, im.mode)

convert() : 该函数可以用来将图像转换为不同色彩模式。

ImageEnhance.Contrast(im):使用ImageEnhance可以增强图片的识别率

其他

简单的几何变换。

1

2

3

4

5

6

7

>>>out = im.resize((128, 128))           #调整图片大小

>>>out = im.rotate(45)               #逆时针旋转 45 度角。

>>>out = im.transpose(Image.FLIP_LEFT_RIGHT)    #左右对换。

>>>out = im.transpose(Image.FLIP_TOP_BOTTOM)    #上下对换。

>>>out = im.transpose(Image.ROTATE_90)       #旋转 90 度角。

>>>out = im.transpose(Image.ROTATE_180)      #旋转 180 度角。

>>>out = im.transpose(Image.ROTATE_270)      #旋转 270 度角。

序列图像。

即我们常见到的动态图,最常见的后缀为 .gif ,另外还有 FLI / FLC 。PIL 库对这种动画格式图也提供了一些基本的支持。当我们打开这类图像文件时,PIL 自动载入图像的第一帧。我们可以使用 seek 和 tell 方法在各帧之间移动。

1

2

3

4

5

6

7

8

import Image

im.seek(1)    # skip to the second frame

try:

  while 1:

    im.seek( im.tell() + 1)

    # do something to im

except EOFError:

  pass

三、代码实例

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

from PIL import Image,ImageFilter,ImageGrab,ImageDraw,ImageFont

imNew = Image.new('RGB',(800,600),(255,0,0))   # 创建图片:宽800*高600,红色

imNew.show()                                   # 显示图片

imGrab = ImageGrab.grab()                      # 抓取屏幕

imGrab.save('grab.jpg', 'jpeg')

im = Image.open('1.jpg')                       # 打开图片

im1 = im.copy()                                # 复制图片

im2 = im.copy()

im3 = im.copy()

im4 = im.copy()

im5 = im.copy()

im6 = im.copy()

im7 = im.copy()

w, h = im.size                                # 获得图片宽高:

print('图片宽高:{} * {}'.format(w, h))

im.thumbnail((w//2, h//2))                    # 缩略图(图片不会被拉伸,只能缩小)

im.save('1_thumbnail.jpg', 'jpeg')

im1 = im1.resize((w//2, h//2))                # 缩放(图片可能会被拉伸,可缩小也可放大)

im1.save('1_resize.jpg', 'jpeg')

im2 = im2.filter(ImageFilter.BLUR)            # 模糊图片

im2.save('1_blur.jpg', 'jpeg')

im3 = im3.rotate(45)                          # 旋转图片,逆时钟旋转45度

im3.save('1_rotate.jpg', 'jpeg')

# 图片转换:左右转换 FLIP_LEFT_RIGHT,上下转换 FLIP_TOP_BOTTOM

im4 = im4.transpose(Image.FLIP_LEFT_RIGHT)

im4.save('1_transpose.jpg', 'jpeg')

# 图片裁剪

box = (200,200,400,400) #左上角(0,0),4元组表示坐标位置:左、上、右、下

im5 = im5.crop(box)

im5.save('1_crop.jpg', 'jpeg')

# 图片上添加文字

draw = ImageDraw.Draw(im6)

#truetype设置字体、文字大小

#stxingka.ttf华文行楷 simkai.ttf 楷体 simli.ttf 隶书

font = ImageFont.truetype("C:\\WINDOWS\\Fonts\\stxingka.ttf", 20)

draw.text((100,100), ('hello word \n你好,世界'), fill='#0000ff', font=font)

im6.save('1_drawText.jpg', 'jpeg')

imTmp = Image.new('RGB',(30,30),'blue')        # 图片上添加图片(粘贴图片)

im7.paste(imTmp, (50,50))                      # 第2个参数为坐标

im7.save('1_paste.jpg','jpeg')

im6Width, im6Height = im6.size        # 图片横向拼接:拼接上面im6、im7(两张图片大小一样)

imHorizontal = Image.new('RGB', (im6Width * 2, im6Height))

imHorizontal.paste(im6, (0,0))

imHorizontal.paste(im7, (im6Width,0))

imHorizontal.save('1_horizontal.jpg', 'jpeg')

imVertical = Image.new('RGB', (im6Width, im6Height*2))    # 图片竖向拼接:拼接上面im6、im7

imVertical.paste(im6, (0,0))

imVertical.paste(im7, (0,im6Height))

imVertical.save('1_vertical.jpg', 'jpeg')

参考博客:

python之pil的使用详解_python_脚本之家  https://www.jb51.net/article/225452.htm

最全的PythonPIL详解可能你找不到比这个更详细的了  https://baijiahao.baidu.com/s?id=1595108270577043146&wfr=spider&for=pc

Python图像处理PIL各模块详细介绍_章子雎Kevin的博客-CSDN博客_pil https://blog.csdn.net/zhangziju/article/details/79123275

你可能感兴趣的:(python,图像处理)