第163集:图片批量处理

一、图片批量处理概述

1. 什么是图片批量处理

图片批量处理是指对多张图片同时执行相同或相似的操作,如调整大小、转换格式、添加水印等,以提高工作效率。

2. 应用场景

  • 网站图片优化:统一调整图片尺寸和格式
  • 摄影后期:批量添加水印、调整色彩
  • 文档处理:批量转换图片格式
  • 社交媒体:批量制作符合平台要求的图片

3. 常用Python库

  • Pillow:Python图像处理标准库,提供丰富的图片操作功能
  • OpenCV:主要用于计算机视觉,但也可用于批量图像处理
  • imageio:用于读取和写入多种图像数据格式

二、Pillow库安装与基础

1. 安装Pillow

pip install pillow

2. 基本图像操作

from PIL import Image

# 打开图片
img = Image.open('example.jpg')

# 查看图片信息
print(f"图片尺寸: {img.size}")
print(f"图片格式: {img.format}")
print(f"图片模式: {img.mode}")

# 显示图片
# img.show()

# 保存图片
img.save('output.jpg')

三、图片批量处理核心功能

1. 批量调整图片大小

功能说明:将指定目录下的所有图片调整为统一尺寸

代码实现

import os
from PIL import Image

def batch_resize_images(input_dir, output_dir, size):
    # 创建输出目录
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    
    # 获取所有图片文件
    image_files = [f for f in os.listdir(input_dir) 
                  if f.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp', '.gif'))]
    
    # 批量处理图片
    for i, filename in enumerate(image_files, 1):
        input_path = os.path.join(input_dir, filename)
        output_path = os.path.join(output_dir, filename)
        
        try:
            with Image.open(input_path) as img:
                # 调整大小
                resized_img = img.resize(size, Image.Resampling.LANCZOS)
                # 保存图片
                resized_img.save(output_path)
            print(f"已处理 {i}/{len(image_files)}: {filename}")
        except Exception as e:
            print(f"处理 {filename} 时出错: {e}")

# 使用示例
batch_resize_images('images', 'resized_images', (800, 600))

2. 批量转换图片格式

功能说明:将指定目录下的所有图片转换为另一种格式(如PNG转JPG)

代码实现

import os
from PIL import Image

def batch_convert_format(input_dir, output_dir, output_format):
    # 创建输出目录
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    
    # 获取所有图片文件
    image_files = [f for f in os.listdir(input_dir) 
                  if f.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp', '.gif'))]
    
    # 批量转换格式
    for i, filename in enumerate(image_files, 1):
        input_path = os.path.join(input_dir, filename)
        # 生成新文件名
        name, ext = os.path.splitext(filename)
        output_path = os.path.join(output_dir, f"{name}.{output_format.lower()}")
        
        try:
            with Image.open(input_path) as img:
                # 如果是RGBA模式(透明背景)且要转换为JPG,需要先转换为RGB
                if img.mode == 'RGBA' and output_format.lower() == 'jpg':
                    img = img.convert('RGB')
                img.save(output_path, output_format.upper())
            print(f"已转换 {i}/{len(image_files)}: {filename} → {output_format}")
        except Exception as e:
            print(f"转换 {filename} 时出错: {e}")

# 使用示例
batch_convert_format('images', 'converted_images', 'jpg')

3. 批量添加水印

功能说明:为指定目录下的所有图片添加文字水印

代码实现

import os
from PIL import Image, ImageDraw, ImageFont

def batch_add_watermark(input_dir, output_dir, watermark_text, font_path=None):
    # 创建输出目录
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    
    # 获取所有图片文件
    image_files = [f for f in os.listdir(input_dir) 
                  if f.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp', '.gif'))]
    
    # 批量添加水印
    for i, filename in enumerate(image_files, 1):
        input_path = os.path.join(input_dir, filename)
        output_path = os.path.join(output_dir, filename)
        
        try:
            with Image.open(input_path) as img:
                # 创建绘图对象
                draw = ImageDraw.Draw(img)
                
                # 设置字体
                if font_path:
                    font = ImageFont.truetype(font_path, 36)
                else:
                    font = ImageFont.load_default()
                
                # 获取水印文本大小
                text_width, text_height = draw.textbbox((0, 0), watermark_text, font=font)[2:4]
                
                # 计算水印位置(右下角)
                img_width, img_height = img.size
                x = img_width - text_width - 20
                y = img_height - text_height - 20
                
                # 添加水印
                draw.text((x, y), watermark_text, font=font, fill=(255, 255, 255, 128))
                
                # 保存图片
                img.save(output_path)
            print(f"已添加水印 {i}/{len(image_files)}: {filename}")
        except Exception as e:
            print(f"添加水印到 {filename} 时出错: {e}")

# 使用示例
batch_add_watermark('images', 'watermarked_images', '© Python教程')

4. 批量调整图片质量

功能说明:调整JPEG图片的压缩质量,减小文件大小

代码实现

import os
from PIL import Image

def batch_adjust_quality(input_dir, output_dir, quality):
    # 创建输出目录
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    
    # 获取所有JPEG图片文件
    image_files = [f for f in os.listdir(input_dir) 
                  if f.lower().endswith(('.jpg', '.jpeg'))]
    
    # 批量调整质量
    for i, filename in enumerate(image_files, 1):
        input_path = os.path.join(input_dir, filename)
        output_path = os.path.join(output_dir, filename)
        
        try:
            with Image.open(input_path) as img:
                # 保存图片并设置质量
                img.save(output_path, 'JPEG', quality=quality)
            print(f"已调整质量 {i}/{len(image_files)}: {filename}")
        except Exception as e:
            print(f"调整 {filename} 质量时出错: {e}")

# 使用示例(质量范围:1-100,数字越大质量越高)
batch_adjust_quality('images', 'compressed_images', 85)

5. 批量旋转图片

功能说明:将指定目录下的所有图片旋转指定角度

代码实现

import os
from PIL import Image

def batch_rotate_images(input_dir, output_dir, angle):
    # 创建输出目录
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    
    # 获取所有图片文件
    image_files = [f for f in os.listdir(input_dir) 
                  if f.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp', '.gif'))]
    
    # 批量旋转图片
    for i, filename in enumerate(image_files, 1):
        input_path = os.path.join(input_dir, filename)
        output_path = os.path.join(output_dir, filename)
        
        try:
            with Image.open(input_path) as img:
                # 旋转图片,expand=True保证完整显示
                rotated_img = img.rotate(angle, expand=True)
                rotated_img.save(output_path)
            print(f"已旋转 {i}/{len(image_files)}: {filename}")
        except Exception as e:
            print(f"旋转 {filename} 时出错: {e}")

# 使用示例(角度为正表示顺时针旋转)
batch_rotate_images('images', 'rotated_images', 90)

三、高级批量图像处理

1. 批量裁剪图片

import os
from PIL import Image

def batch_crop_images(input_dir, output_dir, left, top, right, bottom):
    # 创建输出目录
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    
    # 获取所有图片文件
    image_files = [f for f in os.listdir(input_dir) 
                  if f.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp', '.gif'))]
    
    # 批量裁剪图片
    for i, filename in enumerate(image_files, 1):
        input_path = os.path.join(input_dir, filename)
        output_path = os.path.join(output_dir, filename)
        
        try:
            with Image.open(input_path) as img:
                # 裁剪图片
                cropped_img = img.crop((left, top, right, bottom))
                cropped_img.save(output_path)
            print(f"已裁剪 {i}/{len(image_files)}: {filename}")
        except Exception as e:
            print(f"裁剪 {filename} 时出错: {e}")

# 使用示例(裁剪区域:左、上、右、下坐标)
batch_crop_images('images', 'cropped_images', 100, 100, 500, 500)

2. 批量转换为黑白图片

import os
from PIL import Image

def batch_convert_to_bw(input_dir, output_dir):
    # 创建输出目录
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    
    # 获取所有图片文件
    image_files = [f for f in os.listdir(input_dir) 
                  if f.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp', '.gif'))]
    
    # 批量转换为黑白
    for i, filename in enumerate(image_files, 1):
        input_path = os.path.join(input_dir, filename)
        output_path = os.path.join(output_dir, filename)
        
        try:
            with Image.open(input_path) as img:
                # 转换为黑白
                bw_img = img.convert('L')
                bw_img.save(output_path)
            print(f"已转换为黑白 {i}/{len(image_files)}: {filename}")
        except Exception as e:
            print(f"转换 {filename} 为黑白时出错: {e}")

# 使用示例
batch_convert_to_bw('images', 'bw_images')

四、综合案例:图片处理流水线

1. 需求分析

创建一个图片处理流水线,对图片执行以下操作:

  1. 调整大小为800x600
  2. 转换为JPG格式
  3. 添加水印
  4. 降低质量以减小文件大小

2. 实现代码

import os
from PIL import Image, ImageDraw, ImageFont

def image_processing_pipeline(input_dir, output_dir, watermark_text, quality=85):
    # 创建输出目录
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    
    # 获取所有图片文件
    image_files = [f for f in os.listdir(input_dir) 
                  if f.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp', '.gif'))]
    
    # 批量处理图片
    for i, filename in enumerate(image_files, 1):
        input_path = os.path.join(input_dir, filename)
        name, _ = os.path.splitext(filename)
        output_path = os.path.join(output_dir, f"{name}.jpg")
        
        try:
            with Image.open(input_path) as img:
                # 1. 调整大小
                img = img.resize((800, 600), Image.Resampling.LANCZOS)
                
                # 2. 转换为RGB模式(确保可以保存为JPG)
                if img.mode == 'RGBA':
                    img = img.convert('RGB')
                
                # 3. 添加水印
                draw = ImageDraw.Draw(img)
                font = ImageFont.load_default()
                text_width, text_height = draw.textbbox((0, 0), watermark_text, font=font)[2:4]
                img_width, img_height = img.size
                x = img_width - text_width - 20
                y = img_height - text_height - 20
                draw.text((x, y), watermark_text, font=font, fill=(255, 255, 255, 128))
                
                # 4. 降低质量并保存
                img.save(output_path, 'JPEG', quality=quality)
            print(f"已处理 {i}/{len(image_files)}: {filename}")
        except Exception as e:
            print(f"处理 {filename} 时出错: {e}")

# 使用示例
image_processing_pipeline('raw_images', 'processed_images', '© Python自动化教程')

五、注意事项与最佳实践

1. 注意事项

  • 处理前备份原始图片,避免不可逆操作
  • 注意图片格式兼容性,如PNG转JPG会丢失透明通道
  • 大图片批量处理可能消耗较多内存,可考虑分批处理

2. 最佳实践

  • 使用上下文管理器(with语句)确保图片文件正确关闭
  • 添加适当的错误处理,提高脚本的健壮性
  • 根据实际需求选择合适的图像处理方法和参数
  • 对于大量图片,考虑使用多进程或多线程提高处理速度

六、扩展学习

  1. 多进程处理:使用multiprocessing库加速批量处理
  2. 图像增强:使用Pillow或OpenCV进行批量图像增强
  3. 人脸识别:结合人脸识别技术进行批量人像处理
  4. 视频帧处理:将视频拆分为帧进行批量处理,再合成视频

通过本集的学习,你已经掌握了使用Python进行图片批量处理的基本方法和高级技巧。在实际应用中,可以根据具体需求组合这些操作,创建更复杂的图像处理流程。

« 上一篇 文件批量处理 下一篇 » 办公文档自动化