python pillow 库简单使用

简介

Pillow 是 Python 中最常用的图像处理库,它是 PIL(Python Imaging Library)的分支和继任者,提供了丰富的图像处理功能。

  • 功能:支持图像打开、保存、裁剪、缩放、旋转、滤镜、颜色处理等多种操作,支持主流图像格式(JPG、PNG、GIF、BMP 等)。
  • 优势:API 简洁易用,兼容性好,是 Python 图像处理的基础库。
  • 核心模块:PIL.Image 是最核心的模块,用于表示和处理图像。

安装

pip install pillow

常用操作

图像的基本操作

open

from PIL import Image

# 打开图像
img = Image.open("image.jpg")  # 返回 Image 对象



# 显示图像(调用系统默认图像查看器)
img.show()

# 查看图像信息
print(f"格式:{img.format}")    # 输出图像格式(如 JPEG)
print(f"尺寸:{img.size}")      # 输出宽×高(元组)
print(f"模式:{img.mode}")      # 输出颜色模式(如 RGB、L 灰度)

# 保存图像(可转换格式)
img.save("output.png")  # 保存为 PNG 格式

new

Image.new(mode,size,color)
  • mode: 图像模式,str,如 RGB(真彩图像)、L(灰度图像)、CMYK(色彩图打印模式)等;
  • size: 元组参数(width, height)
  • color: 图片颜色,默认值为 0,
    • (r,g,b)三元组,
    • 16进制的颜色
    • 颜色字符串
img = Image.new(mode='RGB', (100, 100), color='red'
img.show()

属性

  • size, return (height, width)
  • width
  • height
  • format: 查看图片的格式
  • readonly
  • info: 查看图片相关信息
  • mode: 图像模式

常用的图片模式

  1. 1 模式:1 位像素,黑白图像,每个像素用 0 或 1 表示,占 1bit 存储空间。
  2. L 模式:8 位像素,灰度图像,像素值范围 0-255,0 表示黑色,255 表示白色。
  3. P 模式:8 位像素,使用调色板映射到其他模式,适用于颜色数量有限的图像。
  4. RGB 模式:24 位像素(3×8 位),真彩色图像,分别表示红、绿、蓝三个通道。
  5. RGBA 模式:32 位像素(4×8 位),在 RGB 基础上增加了 Alpha 通道(透明度)。
  6. CMYK 模式:32 位像素(4×8 位),用于印刷的青色、品红色、黄色和黑色四通道模式。
  7. YCbCr 模式:24 位像素,用于视频和数字摄影的亮度(Y)和色度(Cb、Cr)模式。
  8. I 模式:32 位整数像素,用于灰度图像的更高精度表示。
  9. F 模式:32 位浮点像素,用于科学计算等需要更高精度的场景。

可以使用 Image.mode 属性查看图像当前模式,也可以通过Image.convert(mode)方法转换图像模式。

# 转为灰度图(L 模式)
gray_img = img.convert("L")
gray_img.save("gray.jpg")

# 转为黑白图(1 模式,二值化)
bw_img = img.convert("1")  # 自动阈值处理
bw_img.save("black_white.jpg")

# 转为 RGBA 模式(增加透明通道)
rgba_img = img.convert("RGBA")
rgba_img.save("with_alpha.png")  # PNG 支持透明

图片格式转换

在 Pillow 中进行图片格式转换非常简单,核心是使用 Image.save() 方法,通过指定不同的文件名后缀来实现格式转换。

save

from PIL import Image

def convert_image_format(input_path, output_path):
    """
    转换图片格式
    :param input_path: 输入图片路径
    :param output_path: 输出图片路径(含目标格式后缀)
    """
    try:
        # 打开图片
        with Image.open(input_path) as img:
            # 保存为目标格式
            img.save(output_path)
        print(f"图片已成功转换为: {output_path}")
    except Exception as e:
        print(f"转换失败: {e}")

# 示例:将PNG转换为JPG
convert_image_format("input.png", "output.jpg")

# 示例:将JPG转换为WebP
convert_image_format("photo.jpg", "photo.webp")

# 示例:将BMP转换为PNG
convert_image_format("image.bmp", "image.png")

png->jpg

PG 不支持透明通道,转换时需要指定背景色

with Image.open("transparent.png") as img:
    # 转换为RGB模式(去除Alpha通道)
    if img.mode in ('RGBA', 'LA'):
        background = Image.new(img.mode[:-1], img.size, (255, 255, 255))
        background.paste(img, img.split()[-1])
        background.save("output.jpg")
    else:
        img.convert("RGB").save("output.jpg")

webp

img.save("output.webp", quality=80)  # 80%质量

TIFF

pip install pillow tifffile

Pillow 支持的主要格式包括:JPG、PNG、GIF、BMP、TIFF、WebP、PPM、PGM 等。转换时只需确保输出文件名的后缀正确即可。

图像缩放

resize

from PIL import Image

def resize_image(input_path, output_path, width, height):
    """
    精确缩放图像到指定尺寸
    :param input_path: 输入图像路径
    :param output_path: 输出图像路径
    :param width: 目标宽度
    :param height: 目标高度
    """
    try:
        with Image.open(input_path) as img:
            # 使用高质量插值算法进行缩放
            resized_img = img.resize((width, height), Image.Resampling.LANCZOS)
            resized_img.save(output_path)
        print(f"图像已缩放到 {width}x{height},保存为: {output_path}")
    except Exception as e:
        print(f"缩放失败: {e}")

# 示例:将图像缩放到 800x600
resize_image("input.jpg", "resized.jpg", 800, 600)

使用 thumbnail() 方法(生成缩略图)

thumbnail() 方法会保持图像的宽高比,将图像缩放到不超过指定的最大尺寸。

from PIL import Image

def create_thumbnail(input_path, output_path, max_size):
    """
    创建缩略图(保持宽高比)
    :param input_path: 输入图像路径
    :param output_path: 输出图像路径
    :param max_size: 元组 (max_width, max_height)
    """
    try:
        with Image.open(input_path) as img:
            # 生成缩略图(会直接修改原图对象)
            img.thumbnail(max_size, Image.Resampling.LANCZOS)
            img.save(output_path)
        print(f"缩略图已生成,最大尺寸 {max_size},保存为: {output_path}")
    except Exception as e:
        print(f"生成缩略图失败: {e}")

# 示例:生成最大尺寸为 200x200 的缩略图
create_thumbnail("input.jpg", "thumbnail.jpg", (200, 200))

按比例缩放(保持宽高比)

from PIL import Image

def scale_image_by_ratio(input_path, output_path, scale_ratio):
    """
    按比例缩放图像
    :param input_path: 输入图像路径
    :param output_path: 输出图像路径
    :param scale_ratio: 缩放比例(例如 0.5 表示缩小到50%)
    """
    try:
        with Image.open(input_path) as img:
            # 计算新尺寸
            width, height = img.size
            new_width = int(width * scale_ratio)
            new_height = int(height * scale_ratio)
            
            # 缩放并保存
            resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
            resized_img.save(output_path)
        print(f"图像已按比例 {scale_ratio} 缩放,新尺寸 {new_width}x{new_height}")
    except Exception as e:
        print(f"缩放失败: {e}")

# 示例:将图像缩小到原来的 30%
scale_image_by_ratio("input.jpg", "scaled.jpg", 0.3)

插值算法

  • Image.Resampling.NEAREST:最近邻插值(速度快,质量低)
  • Image.Resampling.BILINEAR:双线性插值
  • Image.Resampling.BICUBIC:双三次插值
  • Image.Resampling.LANCZOS: Lanczos 插值(高质量,适合缩小图像)

图像旋转与翻转


#旋转图像(角度为正顺时针,负为逆时针)
rotated_90 = img.rotate(90)    # 旋转 90 度
rotated_45 = img.rotate(45)    # 旋转 45 度(默认黑边填充)
rotated_expand = img.rotate(45, expand=True)  # 自动调整画布大小避免裁剪

#翻转图像
flipped_left_right = img.transpose(Image.Transpose.FLIP_LEFT_RIGHT)   # 左右翻转
flipped_top_bottom = img.transpose(Image.Transpose.FLIP_TOP_BOTTOM)  # 上下翻转

图像滤镜与增强

from PIL import ImageFilter

# 模糊效果
blurred = img.filter(ImageFilter.BLUR)  # 普通模糊
gaussian_blur = img.filter(ImageFilter.GaussianBlur(radius=5))  # 高斯模糊(radius 控制程度)

# 锐化效果
sharpened = img.filter(ImageFilter.SHARPEN)  # 普通锐化
more_sharp = img.filter(ImageFilter.DETAIL)  # 增强细节

# 边缘检测
edge_enhance = img.filter(ImageFilter.EDGE_ENHANCE)
edge_detected = img.filter(ImageFilter.FIND_EDGES)  # 边缘检测

sharpened.save("sharpened.jpg")

绘制图形与添加文字

from PIL import ImageDraw, ImageFont

# 创建可绘制对象
draw = ImageDraw.Draw(img)

# 绘制矩形(左上角、右下角坐标,边框颜色,填充色)
draw.rectangle((100, 50, 300, 200), outline="red", fill="yellow", width=2)

# 绘制圆形(用椭圆模拟,外接矩形)
draw.ellipse((200, 150, 400, 350), outline="blue", width=3)

# 添加文字(位置、内容、字体、颜色)
try:
    # 加载系统字体(需指定字体路径或名称,Windows 示例)
    font = ImageFont.truetype("C:/Windows/Fonts/simhei.ttf", size=30)  # 黑体,30号
    draw.text((50, 50), "Hello Pillow", font=font, fill="green")
except IOError:
    # 若无指定字体,使用默认字体
    draw.text((50, 50), "Hello Pillow", fill="green")

img.save("drawn.jpg")

处理透明图像

# 创建带透明通道的图像(宽 400,高 300,RGBA 模式)
rgba_img = Image.new("RGBA", (400, 300), (255, 255, 255, 0))  # 全透明背景

# 绘制半透明矩形(最后一个值为透明度 0-255)
draw = ImageDraw.Draw(rgba_img)
draw.rectangle((100, 100, 300, 200), fill=(255, 0, 0, 128))  # 半透明红色

rgba_img.save("transparent.png")

split & merge

在 Pillow 中,图像的分离(split)与合并(merge)是处理图像通道的重要操作,尤其适用于 RGB、RGBA 等多通道图像。

split

split() 方法可以将多通道图像分离为单个通道的图像。对于 RGB 图像,会分离为 R、G、B 三个单通道;对于 RGBA 图像,会分离为 R、G、B、A 四个单通道。

from PIL import Image

def split_image_channels(input_path):
    """分离图像通道并保存单个通道"""
    try:
        with Image.open(input_path) as img:
            # 确保图像是多通道模式(如RGB、RGBA)
            if img.mode in ('RGB', 'RGBA'):
                # 分离通道
                channels = img.split()
                
                # 保存每个通道(单通道图像会以灰度显示)
                for i, channel in enumerate(channels):
                    # 通道名称(R=0, G=1, B=2, A=3)
                    channel_name = img.mode[i]
                    channel.save(f"{channel_name}_channel.jpg")
                    print(f"已保存 {channel_name} 通道图像")
            else:
                print("图像不是多通道模式,无法分离")
    except Exception as e:
        print(f"分离通道失败: {e}")

# 示例:分离RGB图像的三个通道
split_image_channels("input_rgb.jpg")

merge

Image.merge() 函数可以将多个单通道图像合并为一个多通道图像,需要保证所有通道的尺寸相同。

from PIL import Image

def merge_image_channels(mode, channel_paths, output_path):
    """
    合并多个单通道图像
    :param mode: 目标图像模式(如"RGB"、"RGBA")
    :param channel_paths: 通道图像路径列表(顺序需与模式对应)
    :param output_path: 合并后图像保存路径
    """
    try:
        # 打开所有通道图像
        channels = [Image.open(path) for path in channel_paths]
        
        # 检查通道数量是否与模式匹配
        if len(channels) != len(mode):
            raise ValueError(f"通道数量与模式不匹配:需要 {len(mode)} 个通道,提供了 {len(channels)} 个")
        
        # 合并通道
        merged_img = Image.merge(mode, channels)
        merged_img.save(output_path)
        print(f"通道已合并为 {mode} 模式,保存为: {output_path}")
    except Exception as e:
        print(f"合并通道失败: {e}")

# 示例:合并R、G、B三个通道为RGB图像
merge_image_channels(
    "RGB", 
    ["R_channel.jpg", "G_channel.jpg", "B_channel.jpg"], 
    "merged_rgb.jpg"
)

示例

from PIL import Image

def replace_channel(input_path, channel_index, new_channel_path, output_path):
    """
    替换图像中的指定通道
    :param input_path: 原始图像路径
    :param channel_index: 要替换的通道索引(如RGB中0=R,1=G,2=B)
    :param new_channel_path: 新通道图像路径
    :param output_path: 结果保存路径
    """
    try:
        with Image.open(input_path) as img:
            # 分离原始通道
            channels = list(img.split())
            
            # 打开新通道图像并调整尺寸
            new_channel = Image.open(new_channel_path).resize(img.size)
            
            # 替换指定通道
            channels[channel_index] = new_channel
            
            # 合并通道并保存
            merged_img = Image.merge(img.mode, channels)
            merged_img.save(output_path)
            print(f"已替换第 {channel_index} 个通道,保存为: {output_path}")
    except Exception as e:
        print(f"替换通道失败: {e}")

# 示例:替换RGB图像中的红色通道(索引0)
replace_channel("original_rgb.jpg", 0, "new_red_channel.jpg", "modified_rgb.jpg")

transpose

transpose(method)

method:

  • mage.FLIP_LEFT_RIGHT:左右水平翻转;
  • Image.FLIP_TOP_BOTTOM:上下垂直翻转;
  • Image.ROTATE_90:图像旋转 90 度;
  • Image.ROTATE_180:图像旋转 180 度;
  • Image.ROTATE_270:图像旋转 270 度;
  • Image.TRANSPOSE:图像转置;
  • Image.TRANSVERSE:图像横向翻转。
img = Image.open('test.png')
img1 = img.transpose(Image.FLIP_LEFT_RIGHT)

rotate

Image.rotate() 方法用于对图像进行旋转操作,其核心参数决定了旋转角度、填充方式、扩展边界等效果。以下是该方法的参数详解和使用示例:
rotate(

Image.rotate(angle, resample=Resampling.NEAREST, expand=0, center=None, translate=None, fillcolor=None)
  1. angle(必选)

    • 旋转角度,单位为度(°)
    • 正值表示逆时针旋转,负值表示顺时针旋转
    • 示例:angle=90 表示逆时针旋转 90°,angle=-45 表示顺时针旋转 45°
  2. resample(可选)

    • 旋转时使用的插值算法,影响图像质量
    • 可选值(Pillow 9.1.0+ 使用 Image.Resampling 枚举):
      • Resampling.NEAREST:最近邻插值(速度快,质量低,默认值)
      • Resampling.BILINEAR:双线性插值(平衡速度和质量)
      • Resampling.BICUBIC / Resampling.LANCZOS:高质量插值(适合细节保留,速度较慢)
    • 建议:对照片等需要保留细节的图像使用 LANCZOS
  3. expand(可选)

    • 布尔值或整数(0/1),控制是否扩展图像尺寸以容纳旋转后的全部内容
    • expand=False(默认):保持原图像尺寸,旋转后超出部分会被裁剪
    • expand=True:自动计算并扩展画布,确保旋转后的图像完整显示
    • 示例:正方形旋转 45° 时,expand=True 会生成更大的菱形画布
  4. center(可选)

    • 旋转中心点坐标,格式为 (x, y),默认以图像中心为旋转点
    • 坐标原点在图像左上角,(0, 0) 表示左上角,(width, height) 表示右下角
    • 示例:center=(100, 100) 表示以图像中 (100,100) 位置为中心旋转
  5. translate(可选)

    • 旋转后图像的平移偏移量,格式为 (dx, dy)
    • 正值表示向右 / 向下平移,负值表示向左 / 向上平移
    • 通常用于微调旋转后的图像位置
  6. fillcolor(可选)

  • 旋转后空白区域的填充色,默认使用黑色
  • 支持颜色名称(如 “red”)、RGB 元组(如 (255, 255, 255))或十六进制值
  • 透明图像(RGBA 模式)可使用带 alpha 通道的元组(如 (255, 255, 255, 128))
from PIL import Image, ImageResampling

# 打开图像
with Image.open("input.jpg") as img:
    # 1. 逆时针旋转90°,使用高质量插值,扩展画布
    rotated1 = img.rotate(
        angle=90,
        resample=ImageResampling.LANCZOS,
        expand=True
    )
    rotated1.save("rotated_90.jpg")
    
    # 2. 顺时针旋转45°,填充白色背景,不扩展画布(超出部分裁剪)
    rotated2 = img.rotate(
        angle=-45,
        resample=ImageResampling.BICUBIC,
        expand=False,
        fillcolor=(255, 255, 255)  # 白色填充
    )
    rotated2.save("rotated_45_cropped.jpg")
    
    # 3. 以左上角为中心旋转30°,并向右下方平移
    rotated3 = img.rotate(
        angle=30,
        center=(0, 0),  # 左上角为旋转中心
        translate=(50, 50),  # 向右平移50px,向下平移50px
        fillcolor="lightblue"
    )
    rotated3.save("rotated_custom_center.jpg")

transform

Image.transform() 方法用于对图像进行更复杂的几何变换(如缩放、旋转、扭曲等),相比 resize() 或 rotate() 具有更高的灵活性。其核心是通过自定义变换矩阵或预设变换模式实现复杂效果。

  1. size:变换后图像的目标尺寸,格式为 (width, height)

  2. method: 变换方式,决定了使用哪种几何变换算法,常用取值

    • Image.EXTENT:通过指定源区域和目标区域进行平移 / 缩放(类似裁剪 + 拉伸)
    • Image.AFFINE:仿射变换(支持平移、旋转、缩放、剪切)
    • Image.PERSPECTIVE:透视变换(适合 3D 效果,如倾斜视角)
    • Image.QUAD:四点映射变换(将四边形区域映射到矩形)
    • Image.MESH:网格变换(高级用法,通过多个网格点控制变换)
  3. data(可选): 变换的具体参数,格式因 method 而异:

    • EXTENT:(x0, y0, x1, y1),表示源图像中要截取的矩形区域(左上角和右下角坐标),会被拉伸 / 压缩到 size 尺寸
    • AFFINE:(a, b, c, d, e, f),仿射变换矩阵参数,对应公式:
    x' = a*x + b*y + c
    y' = d*x + e*y + f
    
    • PERSPECTIVE:(a, b, c, d, e, f, g, h),透视变换矩阵参数,对应公式
    x' = (a*x + b*y + c) / (g*x + h*y + 1)
    y' = (d*x + e*y + f) / (g*x + h*y + 1)
    
  4. resample(可选): 插值算法,同 rotate() 方法:

    • Resampling.NEAREST(默认)、BILINEAR、BICUBIC、LANCZOS
    • 高质量图像建议用 LANCZOS
  5. fill(可选): 变换后空白区域的填充色

    • fill 是整数形式的颜色值(如 0 表示黑色),fillcolor 支持颜色名称或 RGB 元组(如 (255,255,255))
    • fillcolor 优先级高于 fill,建议直接使用 fillcolor

EXTENT 变换(区域截取 + 拉伸)

from PIL import Image

with Image.open("input.jpg") as img:
    # 截取源图像中 (100, 50) 到 (300, 250) 的区域,拉伸到 400x300
    transformed = img.transform(
        size=(400, 300),
        method=Image.EXTENT,
        data=(100, 50, 300, 250),  # 源区域坐标
        fillcolor="white"
    )
    transformed.save("extent_transform.jpg")

AFFINE 变换(旋转 + 缩放)

from PIL import Image, ImageResampling
import math

with Image.open("input.jpg") as img:
    w, h = img.size
    angle = 30  # 旋转角度
    scale = 0.8  # 缩放比例
    
    # 计算仿射变换矩阵(含旋转和缩放)
    rad = math.radians(angle)
    a = math.cos(rad) * scale
    b = -math.sin(rad) * scale
    d = math.sin(rad) * scale
    e = math.cos(rad) * scale
    # 平移参数(使图像居中)
    c = w * (1 - a) / 2
    f = h * (1 - e) / 2
    
    transformed = img.transform(
        size=(w, h),
        method=Image.AFFINE,
        data=(a, b, c, d, e, f),
        resample=ImageResampling.LANCZOS,
        fillcolor="lightgray"
    )
    transformed.save("affine_transform.jpg")

PERSPECTIVE 变换(透视效果)

from PIL import Image

with Image.open("input.jpg") as img:
    # 透视变换参数(模拟倾斜视角)
    perspective_data = (1, 0.2, 0, 0.1, 1, 0, 0.001, 0.002)
    
    transformed = img.transform(
        size=(img.width, img.height),
        method=Image.PERSPECTIVE,
        data=perspective_data,
        resample=ImageResampling.BICUBIC,
        fillcolor=(255, 255, 255)
    )
    transformed.save("perspective_transform.jpg")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值