- 教程
- 文档
【免费下载链接】Python-100-Days
Python - 100天从新手到大师
本篇技术指南以 Python-100-Days 项目 Day21-30/28.Python处理图像.md 为核心,系统讲解使用 Python 标准三方库Pillow完成图像读取、剪裁、缩放、旋转、像素操作、滤镜处理与图像绘制的完整方法论。读完本文,你将掌握Image类与ImageDraw模块的全部核心 API 用法,并能独立完成缩略图批量生成、图像合成、加滤镜、加文字等常见实战任务。
入门知识:先理解"图像"是什么
在用代码处理图像之前,需要先建立两个基础概念:颜色与像素。它们是理解 Pillow 所有 API 的前提。
颜色:RGB 与 RGBA 色彩模型
如果你有用颜料画画的经历,一定知道混合红、黄、蓝三种颜料可以得到其他颜色——这三种颜色是美术中的三原色(减色模型)。而在计算机系统中恰恰相反,我们将红、绿、蓝三种色光以不同的比例叠加来组合成其他颜色,因此这三种颜色是色光三原色(加色模型)。
在计算机系统中,一个颜色通常被表示为一个RGB 值或RGBA 值,其中:
- R(Red):红色通道,取值范围 0~255;
- G(Green):绿色通道,取值范围 0~255;
- B(Blue):蓝色通道,取值范围 0~255;
- A(Alpha):Alpha 通道,决定透过该图像像素的程度,也就是透明度。
下表给出了几种常见颜色的 RGB 值,可以作为手工操作像素时的参考:
| 名称 | RGB 值 | 名称 | RGB 值 |
|---|---|---|---|
| White(白) | (255, 255, 255) | Red(红) | (255, 0, 0) |
| Green(绿) | (0, 255, 0) | Blue(蓝) | (0, 0, 255) |
| Gray(灰) | (128, 128, 128) | Yellow(黄) | (255, 255, 0) |
| Black(黑) | (0, 0, 0) | Purple(紫) | (128, 0, 128) |
像素:图像的最小不可分割单位
对于一个由数字序列表示的图像来说,最小的单位是图像上单一颜色的小方格。这些小方格都有明确的位置和被分配的色彩数值,其颜色和位置共同决定了图像最终呈现的样子,它们是不可分割的单位,通常被称为像素(pixel)。
每一个图像都包含了一定量的像素,这些像素决定图像在屏幕上所呈现的大小。数码照片中常说的"XX 万像素",指的就是图像包含的像素总量。
用 Pillow 处理图像
Pillow是从著名的 Python 图像处理库PIL(Python Imaging Library)发展出来的一个分支。PIL 曾是 Python 平台事实上的图像处理标准库,但仅支持到 Python 2.7 且多年无人维护,一群志愿者在 PIL 的基础上创建了兼容版本,即 Pillow——它支持 Python 3.x,并加入了许多有用且有趣的新特性。
通过 Pillow 可以实现图像压缩和图像处理等各种操作。安装只需要一条命令:
pip install pillow说明:若你的环境存在多个 Python 版本,也可以使用
pip3 install pillow。在 Jupyter Notebook 环境中则可以使用%pip install pillow魔法指令安装,例如仓库中的 Day66-80/code/day02.ipynb 就给出了这样的安装方式。
Pillow 中最为重要的是Image类,可以通过Image模块的open函数来读取图像并获得Image类型的对象。下面逐一演示基于Image对象的七类核心操作。
1. 读取和显示图像
from PIL import Image # 读取图像获得Image对象 image = Image.open('guido.jpg') # 通过Image对象的format属性获得图像的格式 print(image.format) # JPEG # 通过Image对象的size属性获得图像的尺寸 print(image.size) # (500, 750) # 通过Image对象的mode属性获取图像的模式 print(image.mode) # RGB # 通过Image对象的show方法显示图像 image.show()format属性:图像的原始格式,常见取值如JPEG、PNG、GIF、BMP等;size属性:返回(width, height)元组,即图像宽高(单位是像素);mode属性:图像的颜色模式,常见取值包括RGB、RGBA、L(灰度)、CMYK、P(调色板模式)等;show()方法:调用操作系统默认的图片查看器显示图像,适合快速预览调试。
实战提示:在服务器或无图形界面的环境中
show()无法弹出窗口,此时应改用image.save('output.jpg')将结果写入文件后查看。
2. 剪裁图像
使用Image对象的crop方法,传入一个四元组(left, top, right, bottom)指定剪裁区域的边界坐标(左、上、右、下),即可从原图中切出矩形区域:
# 通过Image对象的crop方法指定剪裁区域剪裁图像 image.crop((80, 20, 310, 360)).show()注意:right和bottom是开区间边界,即剪裁区域实际包含的像素横坐标范围是left <= x < right。
3. 生成缩略图
使用Image对象的thumbnail方法,传入目标尺寸元组(width, height),会保持原始宽高比将图像缩小到不超过该尺寸的缩略图,并直接修改原Image对象:
# 通过Image对象的thumbnail方法生成指定尺寸的缩略图 image.thumbnail((128, 128)) image.show()thumbnail与resize的关键区别在于:thumbnail是等比例缩放且就地修改,不会变形;而resize是严格按给定尺寸拉伸,可能产生比例失真。
批量缩略图与并发实战(仓库源码印证):缩略图生成是典型的 I/O 密集任务,非常适合配合多线程/线程池加速。在 Python-100-Days 的进阶章节 Day31-35/31.Python语言进阶.md 中,给出了使用threading.Thread为每个图片文件生成(32, 32)、(64, 64)、(128, 128)三种尺寸缩略图的示例;在 Day31-35/code/example19.py 中,进一步展示了用ThreadPoolExecutor(max_workers=30)并发处理images/*目录下所有图片的完整实现,其核心处理函数如下:
def gen_thumbnail(infile): file, ext = os.path.splitext(infile) filename = file[file.rfind('/') + 1:] for size in (32, 64, 128): outfile = f'thumbnails/{filename}_{size}_{size}.png' image = Image.open(infile) image.thumbnail((size, size)) image.save(outfile, format='PNG')可以看到,实际项目中thumbnail通常与save(outfile, format='PNG')组合使用,将缩略图批量落盘——这正是thumbnail最典型的应用场景(如电商商品图、头像裁剪)。
4. 缩放和黏贴图像
综合使用resize(修改图像尺寸)和paste(将一张图粘贴到另一张图上),可以实现图像合成:
# 读取骆昊的照片获得Image对象 luohao_image = Image.open('luohao.png') # 读取吉多的照片获得Image对象 guido_image = Image.open('guido.jpg') # 从吉多的照片上剪裁出吉多的头 guido_head = guido_image.crop((80, 20, 310, 360)) width, height = guido_head.size # 使用Image对象的resize方法修改图像的尺寸 # 使用Image对象的paste方法将吉多的头粘贴到骆昊的照片上 luohao_image.paste(guido_head.resize((int(width / 1.5), int(height / 1.5))), (172, 40)) luohao_image.show()resize(new_size):返回一个按新尺寸(宽、高)重新采样后的新图像,不改动原图;paste(im, box):将图像im粘贴到目标图像的指定位置box(可传入左上角坐标二元组,也可传入四元组区域)。如果im带有 Alpha 通道,paste会进行透明混合。
5. 旋转和翻转
image = Image.open('guido.jpg') # 使用Image对象的rotate方法实现图像的旋转 image.rotate(45).show() # 使用Image对象的transpose方法实现图像翻转 # Image.FLIP_LEFT_RIGHT - 水平翻转 # Image.FLIP_TOP_BOTTOM - 垂直翻转 image.transpose(Image.FLIP_TOP_BOTTOM).show()rotate(angle):按给定角度(度)逆时针旋转图像,expand=True时可以扩展画布避免边缘被裁剪;transpose(method):支持两种内置翻转模式——Image.FLIP_LEFT_RIGHT(水平翻转,即左右镜像)和Image.FLIP_TOP_BOTTOM(垂直翻转,即上下倒置)。
水平翻转(镜像)在公开课 公开课/第04次公开课-好玩的Python/code/example01.py 中也有应用,用于生成图片的镜像副本:
chiling.transpose(Image.FLIP_LEFT_RIGHT).show()6. 操作像素
putpixel方法可以直接修改图像指定坐标点的颜色,是 Pillow 中粒度最细的操作。下面的代码把x在 80~309、y在 20~359 范围内的所有像素统一改成灰色(128, 128, 128):
for x in range(80, 310): for y in range(20, 360): # 通过Image对象的putpixel方法修改图像指定像素点 image.putpixel((x, y), (128, 128, 128)) image.show()与之配套的还有getpixel((x, y))方法,用于读取指定像素的颜色值。逐像素遍历虽然直观,但由于 Python 循环开销较大,不适合对超大图像做全图遍历——当需要高性能批量像素处理时,更推荐结合 NumPy 数组(见 Day66-80/code/day02.ipynb 中通过Image.fromarray在 NumPy 数组与Image对象之间转换的做法)或使用下面的滤镜方案。
7. 滤镜效果
filter方法配合PIL.ImageFilter模块,可以一键为图像套用各种预设滤镜:
from PIL import ImageFilter # 使用Image对象的filter方法对图像进行滤镜处理 # ImageFilter模块包含了诸多预设的滤镜也可以自定义滤镜 image.filter(ImageFilter.CONTOUR).show()ImageFilter模块内置了多种预设滤镜,除示例中的CONTOUR(轮廓描边)外,常用的还有:
BLUR/GaussianBlur(radius):模糊 / 高斯模糊(可指定半径);EMBOSS:浮雕效果;EDGE_ENHANCE:边缘增强;SHARPEN:锐化;SMOOTH:平滑。
公开课 公开课/第04次公开课-好玩的Python/code/example01.py 给出了更丰富的滤镜组合示例:
from PIL import Image, ImageFilter chiling.filter(ImageFilter.GaussianBlur(4)).show() chiling.filter(ImageFilter.EMBOSS).show()filter也支持传入自定义滤镜(基于ImageFilter.BuiltinFilter或卷积核),从而在预设滤镜之外实现定制化的图像增强效果。
使用 Pillow 绘图
处理现有图像之外,Pillow 还能从零创建图像并绘制图形和文字。Pillow 中名为ImageDraw的模块,其Draw函数会返回一个ImageDraw对象,通过该对象的arc、line、rectangle、ellipse、polygon等方法,可以在图像上绘制出圆弧、线条、矩形、椭圆、多边形等形状,也可以通过text方法在图像上添加文字。
要绘制如上图所示的图像,完整代码如下:
import random from PIL import Image, ImageDraw, ImageFont def random_color(): """生成随机颜色""" red = random.randint(0, 255) green = random.randint(0, 255) blue = random.randint(0, 255) return red, green, blue width, height = 800, 600 # 创建一个800*600的图像,背景色为白色 image = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255)) # 创建一个ImageDraw对象 drawer = ImageDraw.Draw(image) # 通过指定字体和大小获得ImageFont对象 font = ImageFont.truetype('Kongxin.ttf', 32) # 通过ImageDraw对象的text方法绘制文字 drawer.text((300, 50), 'Hello, world!', fill=(255, 0, 0), font=font) # 通过ImageDraw对象的line方法绘制两条对角直线 drawer.line((0, 0, width, height), fill=(0, 0, 255), width=2) drawer.line((width, 0, 0, height), fill=(0, 0, 255), width=2) xy = width // 2 - 60, height // 2 - 60, width // 2 + 60, height // 2 + 60 # 通过ImageDraw对象的rectangle方法绘制矩形 drawer.rectangle(xy, outline=(255, 0, 0), width=2) # 通过ImageDraw对象的ellipse方法绘制椭圆 for i in range(4): left, top, right, bottom = 150 + i * 120, 220, 310 + i * 120, 380 drawer.ellipse((left, top, right, bottom), outline=random_color(), width=8) # 显示图像 image.show() # 保存图像 image.save('result.png')这段示例代码覆盖了 Pillow 绘图的完整流程,逐步拆解如下:
- 创建画布:
Image.new(mode='RGB', size=(800, 600), color=(255, 255, 255))创建一个 800×600、白色背景的新图像。mode参数决定画布的色彩模式,color为背景色; - 获取画笔:
ImageDraw.Draw(image)基于图像对象创建ImageDraw画笔; - 设置字体:
ImageFont.truetype('Kongxin.ttf', 32)从字体文件加载 TrueType 字体并指定字号; - 绘制文字:
drawer.text((300, 50), 'Hello, world!', fill=(255, 0, 0), font=font),fill指定文字颜色; - 绘制线条:
drawer.line((x1, y1, x2, y2), fill=color, width=w),这里用两条对角直线构成"X"形交叉; - 绘制矩形:
drawer.rectangle((left, top, right, bottom), outline=color, width=w),outline指定描边颜色; - 绘制椭圆:
drawer.ellipse((left, top, right, bottom), outline=random_color(), width=8),传入的是外接矩形区域,配合循环和random_color()生成四个不同颜色的椭圆; - 输出结果:
image.show()预览、image.save('result.png')保存到文件。save方法会根据扩展名自动推断输出格式。
注意:上面代码中使用的字体文件(
Kongxin.ttf)需要根据自己的环境准备,可以选择自己喜欢的字体文件并放置在代码目录下。若系统字体目录中不存在该文件,可改用系统自带字体路径(如 Linux 下的/usr/share/fonts/...或 Windows 下的C:/Windows/Fonts/...),ImageFont.truetype支持直接传入字体文件的绝对路径。
从 Pillow 到 OpenCV:图像处理能力的下一步
使用 Python 语言做开发,除了可以用 Pillow 来处理图像外,还可以使用更为强大的OpenCV库来完成图形图像的处理。OpenCV(OpenSourceComputerVision Library,开放源代码计算机视觉库)是一个跨平台的计算机视觉库,可以用来开发实时图像处理、计算机视觉和模式识别程序。
选择建议:
- 轻量、快速上手的日常图像操作(缩放、剪裁、格式转换、加水印、批量缩略图、简单绘图)优先使用 Pillow——API 简单、文档友好、无需编译;
- 实时图像处理、人脸检测、特征提取、视频流分析等计算机视觉任务则更适合 OpenCV——它提供大量内置算法与高性能实现。
总结
本篇文章完整梳理了 Python-100-Days 项目 Day28 图像处理 的核心内容:从颜色与像素的底层概念出发,掌握了Image.open读取图像、crop剪裁、thumbnail缩略图、resize/paste缩放合成、rotate/transpose旋转翻转、putpixel像素操作、filter滤镜这七类图像处理手段,以及基于Image.new+ImageDraw+ImageFont从零绘图的完整流程。
在 Python-100-Days 仓库中,你还可以进一步看到 Pillow 的实际工程化用法:在 Day31-35/code/example19.py 中它被用来配合线程池批量生成缩略图;在 Day31-35/31.Python语言进阶.md 中缩略图生成被用作多线程编程的教学案例;在 公开课/第04次公开课-好玩的Python/code/example01.py 中它与滤镜、翻转组合实现"用代码 P 图"的趣味玩法。
在我们的日常工作中,有很多繁琐乏味的任务(批量改名、批量加滤镜、批量生成缩略图、自动添加水印等)其实都可以通过 Python 程序来处理。编程的目的就是让计算机帮助我们解决问题,减少重复乏味的劳动。通过本章节的学习,相信大家已经感受到了使用 Python 程序绘图改图的乐趣——而 Python 能做的事情还远不止这些,继续你的学习吧。
- 教程
- 文档
【免费下载链接】Python-100-Days
Python - 100天从新手到大师
相关推荐
Pillow图像处理库完全指南:Python图像处理的终极解决方案
Pillow图像处理库完全指南:Python图像处理的终极解决方案 Pillow是Python生态中最强大的图像处理库,为开发者提供了简单易用的图像操作接口。无
图像处理计算机视觉Python Imaging Library (Pillow) 图像处理教程
Python Imaging Library Pillow 图像处理教程 核心概念:Image类 Python Imaging Library Pillow 中
图像处理计算机视觉Python-Pillow图像处理库全平台支持指南
Python Pillow图像处理库全平台支持指南 前言 Python Pillow(简称Pillow)作为Python生态中最流行的图像处理库之一,其跨平台兼
图像处理计算机视觉
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考