2

Python 细聊一下可以媲美 PS 的 PIL 图片处理库

 2 years ago
source link: https://blog.51cto.com/u_15541538/5097021
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

PIL 是 Python Image Library 的简称。

PIL 库中提供了诸多用来处理图片的模块,可以对图片做类似于 PS(Photoshop) 的编辑。比如:改变图像大小、旋转图像、图像格式转换,转换颜色通道,图像增强,直方图处理,插值和滤波等等。

PIL 是第三方库,使用之前需要先安装。

pip install pillow

2. 颜色模式

继续之前先解一个重要概念:颜色模式。

所谓颜色模式:指在计算机中如何模拟出现实世界中的各种颜色,或准确讲是一种颜色生成算法。

常用的颜色模式:

  • RGB: 基础理论就是对图片中的每一个像素点,按红 (Red)、绿(Green)、蓝(Blue)三色系的不同分量组合出现实世界中的颜色。也可以说,我们在计算机上中所看到的 RGB 图片的颜色是由三色系分量组合而成。或称其有 3 个颜色通道。

    Tip: 我们在电脑中所看到的图片大多数都是像素图片,像素图片的特点就是整张图片由很多的像素点组成,每一个像素点有自己的颜色。

    在 RGB 颜色模式中,计算机为红色、绿色、蓝色分别分配 8 bit 的空间,也意味着红色、绿色、蓝色各自的分量变化是在 0~255(8bit 二进制换算成十进制度的最大值)之间。

    所以计算机使用 RGB 颜色模式最多可以模拟出 255X255X255 种颜色,这应该足够多了,已经可以让计算机显示出多彩斑斓的现实世界。

    Tip: RGBARGB 颜色模式的增加版。除了可以模拟颜色,还可以摸拟透明度。A 是 Alpha 的缩写,这是可以理解为透过或透明度的意思。

  • CMYK: C:Cyan = 青色,又称为‘天蓝色’或是‘湛蓝’;M:Magenta = 品红色,又称为‘洋红色’;Y:Yellow = 黄色;K:blacK=黑色。CMYK 往往用于模拟印刷制品颜色。多用于广告设计。

可以使用 PIL 库的 ImageColor 模块的 getColor( ) 方法获取一个颜色的不同颜色分量值。

from PIL import ImageColor

red = ImageColor.getrgb("red")
print(red)
'''
输出结果
(255, 0, 0)
'''

Tip: ImageColor 模块内部维护有一个字典。

getColor( ) 方法用使用者提供的颜色名字为键,在字典中查找到对应颜色,再转换成元组后返回。

colormap = {
"aliceblue": "#f0f8ff",
"antiquewhite": "#faebd7",
"aqua": "#00ffff",
"aquamarine": "#7fffd4",
"azure": "#f0ffff",
"beige": "#f5f5dc",
"bisque": "#ffe4c4",
"black": "#000000",
"blanchedalmond": "#ffebcd",
……
}

3. 处理图片

处理图片,主要是使用 PIL 库的 Image 模块(也是核心模块)。在处理图片之前请提前准备 3 张图片(2 张 jpg 格式的图片,1 张 png 格式的图片)。

Tip: 为了方便操作,把图片存放到项目目录中,加载图片时使用相对路径描述。

Python 细聊一下可以媲美  PS  的 PIL 图片处理库_像素点

这是一张名为 back_,jpg 的图片

Python 细聊一下可以媲美  PS  的 PIL 图片处理库_PIL_02

这是一张名为 dog.jpg 的图片

Python 细聊一下可以媲美  PS  的 PIL 图片处理库_Image_03

这是一张名为 guo_ke.png 的图片

3.1 基本操作

  1. 打开图片: 处理图片之前,先要打开图片,可以使用 Image 模块中的 open( ) 方法 打开。此方法返回一个 PIL.Image.Image 类型的对象。

    Tip: 本文不刻意区分函数和方法的概念,统一称为方法。

# 原型
def open(fp, mode="r", formats=None):
    ……

open( ) 方法特点: open( ) 方法不会立即加载图片数据,只有在处理图片或调用图片的 load( ) 方法时才会加载。

from PIL import Image
# open( ) 方法具有懒(延迟)加载的特性
img = Image.open("back_.jpg")
#立即加载图片数据
img.load()

open( ) 方法参数说明:

  • fp: 设置要打开的图片文件。可以是字符串描述的文件名称、也可以是一个文件对象。
from PIL import Image
# mode 必须是 "rb"
file = open("dog.png", mode="rb")
#文件对象作为参数
img = Image.open(file)
  • mode: 对图片文件操作的模式,默认是 “r” 。如果设置,也只能是 “r”。
  • formats: 列表或元组类型,指定文件的打开格式,默认由方法自己判断。
  1. 图片的常规属性: 图片对象有几个常用的属性。
  • mode: 图片的颜色模式(RGB,CMYK,RGBA,L……)。不同颜色模式的图片其通道数量会有差异。

  • format: 图片的格式(PNG,JPEG,GIF……)。JPEG格式的图片没有 A 通道,所以 JPEG 图片是没有透明度信息的。PNG 图片有 A 通道,具有透明性。GIF 图片格式有帧的概念,一张 GIF 图片其实是由多张图片组成的,每一张图片为一帧。

  • size: 图片大小。在处理图片时,图片大小用 2 元组表示。

from PIL import Image
img = Image.open("dog.jpg", mode="r")
print("图片颜色模式:", img.mode)
print("图片的格式:", img.format)
print("图片的大小:", img.size)
'''
输出结果
图片颜色模式: RGB
图片的格式: JPEG
图片的大小: (852, 639)
'''
  1. 修改图片的属性

PIL.Image.Image 对象提供有方法用来修改图片的的属性,如改变大小、改变模式、改变格式。

修改图片的大小: 可使用图片对象的 resize( ) 方法修改图片的大小。此方法的参数必须是 2元组类型。*,返回一个图片副本。

Tip: 不是直接修改原图片的大小(原图片是以 r 模式打开的)。类似于按给定的大小在原图片做插值运算后重新生成一张图片。

# 返回一个新的 PIL.Image.Image 对象
img=img.resize((300,300))

修改的图片的颜色模式: 可以使用图片对象的 conver( ) 方法修改图片模式 。可以取值范围: 1、L、P、RGB、RGBA、CMYK、YCbCr、I、F。返回的也是一个图片副本。

1 模式: 黑白图片模式,每一个像素只有黑或白两个颜色。

from PIL import Image
img = Image.open("dog.jpg", mode="r")
img1 = img.convert('1')
img.show()

Python 细聊一下可以媲美  PS  的 PIL 图片处理库_PIL_04

L 模式: 生成灰度图片,每一个像素的颜色会重新按 L = R * 299/1000 + G * 587/1000 + B * 114/1000 进行换算。

Tip: 当像素点的 RGB 颜色分量相同时,组合出来的就是灰色。灰色系有 256 阶梯,从 0~255。0 表示黑色,255 表示白色,从0到255 颜色由黑逐渐转向白。

#000 黑色,#111、 # 222、 #333 ……逐渐到 #FFF 白色。灰度图片要比黑白图片的颜色层次丰富。

from PIL import Image
img = Image.open("dog.jpg", mode="r")
img = img.convert('L')
img.show()

Python 细聊一下可以媲美  PS  的 PIL 图片处理库_PIL_05

当把 RGBA 模式转换成 RGB 模式时,只会获取其中的 RGB 颜色通道(舍弃透明信息)。当由 RGB 模式转换成 RGBA 模式时。会自动添加 A 通道,补值为 255。

from PIL import Image

img = Image.open("dog.jpg", mode="r")
print(img.mode)
print(img.getpixel((1, 1)))
img = img.convert("RGBA")
# 使用 getpixel( ) 方法获取任意一点的颜色模式
print(img.getpixel((1, 1)))
print(img.mode)
'''
输出结果
RGB
(207, 209, 222)
(207, 209, 222, 255)
RGBA
'''
  1. 保存图片。图片修改后可以使用 save( ) 方法对其保存。
def save(self, fp, format=None, **params):

save( ) 方法的参数说明:

  • fp: 字符串描述的文件名或一个文件对象。

  • format: 保存时指定图片的格式(JPG、PNG……)。如果省略此参数,则由文件的扩展名确定。如果 fp 是一个文件对象,此参数不能省略。

  • params: 扩展参数。

保存图片的副本:除了文件名不一样,其它数据信息都是相同。

from PIL import Image
img = Image.open("dog.jpg")
img.save("dog_01.jpg")

保存时修改图片格式:

from PIL import Image

# 原图片格式为 jpg
img = Image.open("dog.jpg")
print("dog.jpg图片的颜色模式:", img.mode)
# 保存后图片的格式为 png
img.save("dog_02.png")
img = Image.open("dog_02.png")
print("dog_02.png的颜色模式:", img.mode)
'''
输出结果
dog.jpg图片的颜色模式: RGB
dog_02.png的颜色模式: RGB
'''

Tip: dog.jpg 图片是 RGB 模式,虽然在保存时指定 PNG 扩展名,但系统不会添加 A 通道, dog_02.png 图片的颜色模式还是 RGB 模式。

如下代码会抛异常:因为无法将 RGBA 模式的图片以 JPEG 格式保存

from PIL import Image
# png 格式的图片有透明通道,其颜色模式是 RGBA.
img = Image.open("guo_ke.png")
print(img.mode)
# jpg 格式的图片没有透明通道
img.save("guo_ke.jpg")
'''
输出结果
OSError: cannot write mode RGBA as JPEG
'''

3.2 变形操作

变形操作包括对图片的旋转、裁剪、复制和粘贴一系列操作。

rotate( )方法: 此方法使用一个角度值旋转图片,返回图片副本

角度为正值时以逆时针方向旋转,负值向顺时针方向旋转.可以通过调整角度,让图片水平或垂直方向翻转。

from PIL import Image
img = Image.open("dog.jpg")
img=img.rotate(30)
img.show()

Python 细聊一下可以媲美  PS  的 PIL 图片处理库_PIL_06

默认情况下,图片旋转后的空白处填充黑色。可以使用 rotate( )方法 的 fillcolor 参数为图片旋转后留下的空白处指定填充颜色。

from PIL import Image
img = Image.open("dog.jpg")
img=img.rotate(-45,fillcolor="blue")
img.show()

Python 细聊一下可以媲美  PS  的 PIL 图片处理库_元组_07

可以使用 rotate( )方法 的 center 参数调整图片的中心点的位置。

from PIL import Image
img = Image.open("dog.jpg")
img = img.rotate(45, fillcolor="blue", center=(20, 20))
img.show()

Python 细聊一下可以媲美  PS  的 PIL 图片处理库_PIL_08

crop( ) 方法: 裁剪图片,裁剪时需要在原图片中确定一个需要保留的矩形区域**。此方法返回一个图片副本。**

from PIL import Image
img = Image.open("dog.jpg")
# 4 元组,前 2 个数字 表示矩形的左上角,后 2 个数字 表示矩形的右下角
img = img.crop((0, 0, 400, 400))
img.show()

图片的坐标系,图片的最左上角为原点,水平向右为 X 正轴,垂直向下为 正轴.

Python 细聊一下可以媲美  PS  的 PIL 图片处理库_Image_09

<img src=“D:\红泥巴\我的文章\image\dogC.png” alt=“dogC” style=“zoom:33%;” />

​ 裁剪后的图片
Python 细聊一下可以媲美  PS  的 PIL 图片处理库_python_10

copy( )方法: 复制图片,返回和原图片完全一样的图片副本。图片副本和原图片之间是完全独立的,修改其中的一张图片不会影响另一张图片。

paste( )方法: 粘贴图片,可以把一张图片粘贴到另一张图片上。如把小狗的图片粘贴到背景图片上。

def paste(self, im, box=None, mask=None):

参数说明:

  • im: 需要被粘贴的图片(这里是小狗图片)。
  • box: 图片被粘贴的位置。box 可以是一个 2 元组,这 2 个表示小狗图片的左上角在背景图片上的位置。如果是 4 元组,则被粘贴的图片(小狗图片)必须和 4 元组所描述的矩形区域的大小一样。
  • **mask:**遮罩图片,遮罩图片最好有透明性,如 PNG 图片。
from PIL import Image
# 打开背景图片
back_img = Image.open("back_.jpg")
# 打开小狗图片
dog_img = Image.open("dog.jpg")
# 修改小狗的大小
dog_img = dog_img.resize((180, 120))
# 复制图片
back_copy_img = back_img.copy()
# (300,200) 或(300,200,480,320)
back_copy_img.paste(dog_img, (300, 200))
back_copy_img.show()

Python 细聊一下可以媲美  PS  的 PIL 图片处理库_python_11

遮罩图片的使用,遮罩图片只能是 “1”, “L” or “RGBA” 模式的图片,且遮罩图片和被粘贴的图片大小必须一样。

from PIL import Image
# 打开背景图片
back_img = Image.open("back_.jpg")
# 打开小狗图片
dog_img = Image.open("dog.jpg")
# 修改小狗的大小
dog_img = dog_img.resize((180, 120))
# 复制图片
back_copy_img = back_img.copy()
# 遮罩图片 需要有透明度信息
mask_img = Image.open("js.png")
# 修改 遮罩图片 和 小狗图片一样大小
mask_img = mask_img.resize((180, 120))
# 粘贴
back_copy_img.paste(dog_img, box=(300, 200, 480, 320), mask=mask_img)
back_copy_img.show()

Python 细聊一下可以媲美  PS  的 PIL 图片处理库_像素点_12

3.3 合并颜色通道

RGB颜色模式的图片有 3 个颜色通道,RGBA 颜色模式的图片有 3 个颜色通道另加 1 个透明度通道。可以使用 split( ) 方法 分离出图片的颜色通道,然后根据自己的需要再重新排列颜色通道得到不同效果的图片。

分离小狗图片的颜色通道,并重组颜色通道 。merge( ) 方法能通过指定的颜色通道创建一张新图片。

from PIL import Image
dog_img = Image.open("dog.jpg")
# 分离颜色通道
r, g, b = dog_img.split()
# 打乱颜色通道得到新图片 蓝色通道和红色通道互换
dog_img = Image.merge(dog_img.mode, (b, g, r))
dog_img.show()

Python 细聊一下可以媲美  PS  的 PIL 图片处理库_python_13

可以对分离出来的颜色通道进行单独修改修改,修改后再重组出新的图片。

from PIL import Image

dog_img = Image.open("dog.jpg")
# 分离颜色通道
r, g, b = dog_img.split()
# 修改每一个颜色通道中的像素点的值
r = r.point(lambda i: i + 10)
g = r.point(lambda i: i * 0.6)
b = b.point(lambda i: i + 100)
dog_img = Image.merge(dog_img.mode, (r, g, b))
dog_img.show()

Python 细聊一下可以媲美  PS  的 PIL 图片处理库_像素点_14

下面的代码使用 getpixel( ) 方法通过给定的坐标值找到每一点的颜色模式。然后对每一个像素点的颜色模式进行重构。

from PIL import Image
dog_img = Image.open("dog.jpg")
w, h = dog_img.size
for i in range(w):
    for j in range(h):
        # 获取每一个像素点的颜色模式
        c = dog_img.getpixel((i, j))
        # 修改每一个像素点的颜色模式 红色加重,绿色减少。
        dog_img.putpixel((i, j), (c[0] + 100, c[1] - 20, c[2] + 30))
dog_img.show()

Python 细聊一下可以媲美  PS  的 PIL 图片处理库_PIL_15

重组不同图片中的颜色通道,要求所有图片的大小都一样。

from PIL import Image
dog_img = Image.open("dog.jpg")
# 分离颜色通道
r, g, b = dog_img.split()
img1 = Image.open("guo_ke.png")
#两张图片的大小一样
img1=img1.resize(dog_img.size)
# js.png 颜色模式是 rgba
r1,g1,b1,a=img1.split()
# 混合 两张图片的不同通道
img=Image.merge("RGBA",(r1,g,b1,a))
img.show()

Python 细聊一下可以媲美  PS  的 PIL 图片处理库_元组_16

3.4 滤镜和增加

可以像 PS 一样给图片添加滤镜,并且可以调整图片的对比度,色调……等信息。

ImageFilter 模块提供有各种滤镜对象,图片使用滤镜后会返回一个图片副本。

  • BLUR:模糊效果

  • CONTOUR:轮廓效果

  • DETAIL:细节效果

  • EDGR_ENHANCE:边界增强效果

  • EDGE_ENHANCE_MODE:阈值边界增强效果

  • EMBOSS:浮雕效果

  • FIND_EDGES:边界效果

  • SMOOTH:平滑效果

  • SMOOTH_MODE:阈值平滑效果

  • SHARPEN:锐化效果

给小狗图片添加滤镜效果:

from PIL import ImageFilter
from PIL import Image
dog_img = Image.open("dog.jpg")
# 浮雕效果
dog_img = dog_img.filter(ImageFilter.EMBOSS)
dog_img.show()

Python 细聊一下可以媲美  PS  的 PIL 图片处理库_PIL_17

其它的效果大家可以自己试一试。

ImageEnhance 类提供有修改图片对比度,色调等信息的对象。这些对象都有一个 enhance(factor) 方法用来设置增强的强度。

  • Color(im):调整颜色平衡

  • Contrast(im):调整对比度

  • Brightness(im):调整亮度

  • Sharpness(im):调整锐度

增强图片的高度:

from PIL import ImageFilter
from PIL import Image
from PIL import ImageEnhance

dog_img = Image.open("dog.jpg")
dog_img = dog_img.filter(ImageFilter.SHARPEN)
# 构建 Brightness 对象
dog_img=ImageEnhance.Brightness(dog_img)
# 调用 Brightness 对象的enhance()设置增加的数值
dog_img.enhance(2).show()

Python 细聊一下可以媲美  PS  的 PIL 图片处理库_python_18

本文介绍了 PIL 库的 ImageColor、Image、ImageFilter、ImageEnchance 模块。除此之外,PIL 中还有很多与图片处理相关的模块。使用这些模块,几乎可以完成 PS 中能完成的任务。

对于图片处理还有些高级应用,有时间再另开辟新文。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK