PIL(Python Imaging Library)是Python早期常用的图像处理库,目前已停止维护,实际开发中一般改用它的分支Pillow。Pillow支持更多图像格式,并对原有接口做了改进。安装命令如下:
安装完成后,导入时仍然使用PIL这个包名:
下面围绕Pillow的常用函数,按“打开与查看—保存—色彩模式—滤镜—增强—综合应用”的顺序整理一套可直接落地的写法。
一、打开图片、查看格式并显示
Image.open()用于读取图片,参数是图片路径;show()会调用系统默认看图工具把图片展示出来。
- from PIL import Image
- a = Image.open("F:\\Pictures\\wallhaven-3klw69.jpg")
- a.show()
复制代码
打开后可以通过format属性读取图像格式信息,例如JPEG:
- from PIL import Image
- a = Image.open("F:\\Pictures\\wallhaven-3klw69.jpg")
- print(a.format)
- a.show()
复制代码
在Windows路径中,反斜杠容易被当成转义符,建议写成双反斜杠,或者使用原始字符串r"F:\Pictures\..."。路径写错或文件不存在时,open()会直接抛出异常,这是排查图片读取失败时首先要确认的地方。
二、save()保存图片及常用参数
save()把图片写到指定路径,最基本的用法是传入目标文件名,格式通常由扩展名推断:
- from PIL import Image
- a = Image.open(ImgFile)
- a.save("D:\\1.jpg")
复制代码
save()还支持一组与格式相关的参数,实际使用时按目标格式选择:
format:指定保存格式,如JPEG、PNG、GIF;不指定时根据文件扩展名自动推断。
quality:用于JPEG,指定图像质量,取值范围为1-95。
optimize:对GIF等格式设置为True,可优化保存后的文件大小。
progressive:用于JPEG,设置为True时生成渐进式JPEG。
compress_level:用于PNG等格式,指定压缩级别,取值0-9,0表示不压缩,9表示最高压缩。
subsampling:用于JPEG,指定色度子采样方式,0表示4:4:4无子采样,1表示4:2:2水平子采样,2表示4:2:0水平和垂直子采样。
dpi:设置图像的DPI,可以传单个整数,也可以传表示水平和垂直DPI的元组。
icc_profile:指定ICC配置文件的路径。
append_images:用于GIF,传入一个图像列表,附加到原始图像之后。
save_all:用于GIF,指定是否保存所有图像帧,默认为False。
loop:用于GIF,指定循环播放次数,传0表示无限循环。
duration:用于GIF,指定每帧之间的显示时间,单位为毫秒。
如果保存时既没有写扩展名,也没有显式传format,就容易出现无法推断格式的问题。压缩级别、quality、optimize这些参数会同时影响文件体积和保存耗时,批量处理时可以先在小样本上确认参数,再应用到全量图片。
三、convert()切换色彩模式
convert()用于把图像转换成指定色彩模式,常见模式如下:
- image.convert('1') # 一位像素,黑白
- image.convert('L') # 8位像素,黑白
- image.convert('P') # 使用调色板的像素模式
- image.convert('RGB') # 3*8位像素,真彩色
- image.convert('RGBA') # 4*8位像素,带透明度掩膜的真彩色
- image.convert('YCbCr') # 3*8位像素,彩色视频格式
- image.convert('I') # 32位有符号整数像素
- image.convert('F') # 32位浮点像素
复制代码
不同模式会影响后续处理和保存结果。例如做视频相关的颜色空间转换时可用YCbCr,需要透明通道时用RGBA,只做黑白处理时用L或1。
四、filter()调用ImageFilter滤镜
ImageFilter模块提供了多种内置滤镜,直接传给filter()即可:
- from PIL import Image, ImageFilter
- im = Image.open("F:\\Pictures\\wallhaven-3klw69.jpg")
- im = im.filter(ImageFilter.GaussianBlur) # 高斯模糊
- im = im.filter(ImageFilter.BLUR) # 普通模糊
- im = im.filter(ImageFilter.EDGE_ENHANCE) # 边缘增强
- im = im.filter(ImageFilter.FIND_EDGES) # 找到边缘
- im = im.filter(ImageFilter.CONTOUR) # 轮廓
- im = im.filter(ImageFilter.DETAIL) # 细节
复制代码
这类滤镜适合做轮廓提取、边缘检测、模糊降噪等预处理。注意每次filter()都会返回新的图像对象,需要重新赋值才能保留处理结果。
五、查看直方图
histogram()返回图像的像素分布统计结果,打印出来是一长串整数,可以用于分析图像各灰度级或通道的像素数量:
六、转换图像文件格式
下面这段脚本先判断文件路径是否为字符串、后缀是否属于bmp、gif、png,然后打开图片,转成YCbCr并另存为jpg。文件名通过切片去掉原后缀,再拼接“00.jpg”:
- from PIL import Image, ImageFilter
- imgFile = "test.gif"
- if type(imgFile) == str and imgFile.endswith(('.bmp', '.gif', '.png')):
- im = Image.open(imgFile)
- im.convert('YCbCr').save(imgFile[0:-4] + '00.jpg')
复制代码
这里的后缀判断决定了脚本的适用范围,如果要处理jpg等格式,需要把对应后缀加入判断条件,否则代码不会进入转换分支。
七、屏幕截图
ImageGrab.grab()可以截取屏幕。传入四元组时截取指定区域,不传参数时截取全屏:
- from PIL import ImageGrab
- im = ImageGrab.grab((0, 0, 800, 200)) # 截取区域:横向0-800,纵向0-200
- tm = ImageGrab.grab() # 截取全屏
- im.show()
- tm.show()
复制代码
八、图像缩放
resize()接收目标宽高组成的元组,返回缩放后的新图像:
- a = a.resize((2560, 1440))
复制代码
缩放会改变图像尺寸,大图处理时要注意内存占用;如果需要保持比例,应在调用前自行计算目标宽高。
九、ImageEnhance做亮度、色度、对比度和锐度增强
ImageEnhance中的Brightness、Color、Contrast、Sharpness分别对应亮度、色度、对比度和锐度增强。enhance()的参数是增强因子:
- from PIL import Image, ImageEnhance
- image = Image.open("F:\\Pictures\\won.jpg")
- image.show()
- # 增强亮度
- enh = ImageEnhance.Brightness(image)
- brightness = 2
- image1 = enh.enhance(brightness)
- image1.show()
- # 色度增强
- enh = ImageEnhance.Color(image)
- col = 2
- image1 = enh.enhance(col)
- image1.show()
- # 对比度增强
- enh = ImageEnhance.Contrast(image)
- con = 2
- image1 = enh.enhance(con)
- image1.show()
- # 锐度增强
- enh = ImageEnhance.Sharpness(image)
- sha = 2
- image1 = enh.enhance(sha)
- image1.show()
复制代码
增强因子为2表示在原有基础上加强,实际调参时可以从较小值开始逐步调整,避免图像过曝或失真。
十、综合应用:轮廓处理、纯色图与随机验证码图
轮廓处理可以直接复用CONTOUR滤镜:
- from PIL import Image, ImageFilter
- image = Image.open("F:\\Pictures\\won.jpg")
- image = image.filter(ImageFilter.CONTOUR)
- image.show()
复制代码
生成固定尺寸、固定颜色的图片,使用Image.new()新建RGB图像,颜色由随机函数生成:
- from PIL import Image
- import random
- def GetColo():
- a = random.randint(0, 255)
- b = random.randint(0, 255)
- c = random.randint(0, 255)
- return (a, b, c)
- image = Image.new('RGB', (150, 50), GetColo())
- image = image.save(open("test.png", 'wb'), 'png')
复制代码
生成随机字符串、随机颜色的验证码图片,需要组合ImageDraw和ImageFont:
- from PIL import Image, ImageDraw, ImageFont
- import random
- def GetColor():
- a = random.randint(0, 255)
- b = random.randint(0, 255)
- c = random.randint(0, 255)
- return (a, b, c)
- def GetRandom():
- random_num = str(random.randint(0, 9))
- random_low = chr(random.randint(97, 122)) # 小写字母
- random_upp = chr(random.randint(65, 90)) # 大写字母
- random_chr = random.choice([random_upp, random_low, random_num])
- return random_chr
- image = Image.new('RGB', (150, 30), GetColor())
- draw = ImageDraw.Draw(image)
- font = ImageFont.truetype('Sophia Script Free Demo.ttf', 26)
- for i in range(5):
- random_char = GetRandom()
- draw.text((10 + i * 30, 0), random_char, GetColor(), font)
- image = image.save(open("test.png", 'wb'), 'png')
复制代码
验证码示例中,chr()把ASCII码转换成字符,random.choice()从大小写字母和数字组成的列表中随机取一个;draw.text()按坐标、字符、颜色、字体四个参数把内容画到图上。ImageFont.truetype()依赖本地字体文件,如果指定的ttf文件不存在,字体加载会失败,所以部署脚本时要把字体文件和脚本一起放到可访问的路径。
适用场景与注意点
Pillow适合批量图片格式转换、缩略图生成、滤镜预处理、截图、简单验证码生成和亮度对比度调节等脚本化任务。实际使用时重点确认三件事:图片路径和字体路径是否正确;save()的格式由扩展名还是format参数决定;批量处理时quality、compress_level、optimize等参数对输出体积和耗时的取舍。按照上述函数组合,就能把常见的图像读取、处理、增强和保存流程串成可复用的Python脚本。 |