Python图片缩放案例实操?

wen python案例 1

本文目录导读:

  1. 基础缩放(使用PIL/Pillow)
  2. 批量缩放处理
  3. 智能裁剪缩放
  4. OpenCV方式缩放
  5. 多线程批量处理
  6. Web应用中的图片缩放
  7. 实用工具类
  8. 安装依赖

我来为您介绍几个实用的Python图片缩放案例,从基础到进阶。

基础缩放(使用PIL/Pillow)

from PIL import Image
import os
def basic_resize():
    """基础图片缩放"""
    # 打开图片
    img = Image.open('input.jpg')
    # 方法1:指定宽高
    resized_img = img.resize((800, 600))
    resized_img.save('resized_800x600.jpg')
    # 方法2:按比例缩放
    width, height = img.size
    new_width = 400
    new_height = int(height * new_width / width)
    resized_img = img.resize((new_width, new_height))
    resized_img.save('resized_by_ratio.jpg')
    # 方法3:使用thumbnail(保持比例,不会放大)
    img.thumbnail((300, 300))
    img.save('thumbnail_300.jpg')
basic_resize()

批量缩放处理

import os
from PIL import Image
from pathlib import Path
def batch_resize(input_dir, output_dir, target_size=(800, 600)):
    """批量缩放图片"""
    # 创建输出目录
    Path(output_dir).mkdir(exist_ok=True)
    # 支持的图片格式
    valid_extensions = {'.jpg', '.jpeg', '.png', '.bmp', '.gif'}
    for filename in os.listdir(input_dir):
        ext = os.path.splitext(filename)[1].lower()
        if ext in valid_extensions:
            input_path = os.path.join(input_dir, filename)
            output_path = os.path.join(output_dir, f"resized_{filename}")
            try:
                # 打开并缩放图片
                with Image.open(input_path) as img:
                    # 保持宽高比的缩放
                    img.thumbnail(target_size, Image.Resampling.LANCZOS)
                    # 如果是RGBA模式,转换为RGB
                    if img.mode == 'RGBA':
                        img = img.convert('RGB')
                    img.save(output_path, quality=85)
                    print(f"已处理: {filename}")
            except Exception as e:
                print(f"处理失败 {filename}: {e}")
# 使用示例
batch_resize('./images/', './resized/', (800, 600))

智能裁剪缩放

from PIL import Image
def smart_crop_resize(image_path, target_size=(800, 600)):
    """智能裁剪缩放 - 保持关键区域"""
    img = Image.open(image_path)
    target_ratio = target_size[0] / target_size[1]
    img_ratio = img.width / img.height
    if img_ratio > target_ratio:
        # 图片更宽,裁剪左右
        new_width = int(img.height * target_ratio)
        left = (img.width - new_width) // 2
        img = img.crop((left, 0, left + new_width, img.height))
    else:
        # 图片更高,裁剪上下
        new_height = int(img.width / target_ratio)
        top = (img.height - new_height) // 2
        img = img.crop((0, top, img.width, top + new_height))
    # 缩放到目标尺寸
    img = img.resize(target_size, Image.Resampling.LANCZOS)
    return img
# 使用示例
result = smart_crop_resize('wide_image.jpg', (800, 600))
result.save('smart_cropped.jpg')

OpenCV方式缩放

import cv2
import numpy as np
def opencv_resize_examples():
    """使用OpenCV进行图片缩放"""
    # 读取图片
    img = cv2.imread('input.jpg')
    if img is None:
        print("无法读取图片")
        return
    # 1. 直接缩放
    resized = cv2.resize(img, (800, 600))
    # 2. 按比例缩放
    scale_percent = 50  # 缩放50%
    width = int(img.shape[1] * scale_percent / 100)
    height = int(img.shape[0] * scale_percent / 100)
    resized_by_percent = cv2.resize(img, (width, height))
    # 3. 不同插值方法
    methods = {
        'nearest': cv2.INTER_NEAREST,    # 最近邻(速度快)
        'linear': cv2.INTER_LINEAR,      # 双线性(一般)
        'cubic': cv2.INTER_CUBIC,        # 双三次(质量好)
        'lanczos': cv2.INTER_LANCZOS4    # Lanczos(质量最好)
    }
    for name, method in methods.items():
        resized = cv2.resize(img, (400, 300), interpolation=method)
        cv2.imwrite(f'resized_{name}.jpg', resized)
    # 4. 自适应缩放(保持宽高比)
    def resize_with_aspect_ratio(image, width=None, height=None):
        dim = None
        (h, w) = image.shape[:2]
        if width is None and height is None:
            return image
        if width is None:
            r = height / float(h)
            dim = (int(w * r), height)
        else:
            r = width / float(w)
            dim = (width, int(h * r))
        return cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
    result = resize_with_aspect_ratio(img, width=500)
    cv2.imwrite('aspect_ratio_resized.jpg', result)
    print("OpenCV缩放完成")
opencv_resize_examples()

多线程批量处理

from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
import os
from PIL import Image
def process_single_image(args):
    """处理单张图片"""
    input_path, output_path, size = args
    try:
        with Image.open(input_path) as img:
            # 获取原始尺寸
            original_size = img.size
            # 智能缩放保持比例
            img.thumbnail(size, Image.Resampling.LANCZOS)
            # 保存图片
            img.save(output_path, quality=85)
            return {
                'success': True,
                'input': input_path,
                'original': original_size,
                'new': img.size
            }
    except Exception as e:
        return {
            'success': False,
            'input': input_path,
            'error': str(e)
        }
def parallel_batch_resize(input_dir, output_dir, target_size=(800, 600), max_workers=4):
    """并行批量处理图片缩放"""
    import glob
    os.makedirs(output_dir, exist_ok=True)
    # 准备任务列表
    tasks = []
    image_extensions = ('*.jpg', '*.jpeg', '*.png', '*.bmp')
    for ext in image_extensions:
        for filepath in glob.glob(os.path.join(input_dir, ext)):
            filename = os.path.basename(filepath)
            output_path = os.path.join(output_dir, filename)
            tasks.append((filepath, output_path, target_size))
    print(f"找到 {len(tasks)} 张图片需要处理")
    # 使用线程池并行处理
    results = []
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        for result in executor.map(process_single_image, tasks):
            results.append(result)
            if result['success']:
                print(f"✓ {result['input']}: {result['original']} -> {result['new']}")
            else:
                print(f"✗ {result['input']}: {result['error']}")
    # 统计结果
    success_count = sum(1 for r in results if r['success'])
    print(f"\n处理完成: 成功 {success_count}, 失败 {len(results) - success_count}")
# 使用示例
parallel_batch_resize('./images/', './resized/', (800, 600), max_workers=8)

Web应用中的图片缩放

from flask import Flask, request, send_file
from PIL import Image
import io
import base64
app = Flask(__name__)
@app.route('/resize', methods=['POST'])
def resize_image():
    """图片缩放API"""
    if 'image' not in request.files:
        return {'error': '没有上传图片'}, 400
    file = request.files['image']
    width = request.form.get('width', 800, type=int)
    height = request.form.get('height', 600, type=int)
    # 读取图片
    img = Image.open(file.stream)
    # 缩放图片
    img.thumbnail((width, height), Image.Resampling.LANCZOS)
    # 保存到内存
    img_byte_arr = io.BytesIO()
    img.save(img_byte_arr, format='JPEG')
    img_byte_arr.seek(0)
    # 返回base64编码的图片
    img_base64 = base64.b64encode(img_byte_arr.getvalue()).decode()
    return {
        'success': True,
        'original_size': file.content_length,
        'new_size': len(img_base64),
        'image': f'data:image/jpeg;base64,{img_base64}'
    }
@app.route('/resize/download', methods=['POST'])
def resize_and_download():
    """缩放并下载图片"""
    if 'image' not in request.files:
        return {'error': '没有上传图片'}, 400
    file = request.files['image']
    width = request.form.get('width', 800, type=int)
    height = request.form.get('height', 600, type=int)
    # 处理图片
    img = Image.open(file.stream)
    img.thumbnail((width, height), Image.Resampling.LANCZOS)
    # 保存到内存
    img_byte_arr = io.BytesIO()
    img.save(img_byte_arr, format='JPEG')
    img_byte_arr.seek(0)
    return send_file(
        img_byte_arr,
        mimetype='image/jpeg',
        as_attachment=True,
        download_name=f'resized_{file.filename}'
    )
if __name__ == '__main__':
    app.run(debug=True, port=5000)

实用工具类

from PIL import Image, ImageFilter
import os
import hashlib
class ImageResizer:
    """图片缩放工具类"""
    def __init__(self, quality=85):
        self.quality = quality
    def resize_with_constraints(self, image_path, max_size=(1200, 1200), 
                               min_size=(100, 100), output_format='JPEG'):
        """带约束的缩放"""
        img = Image.open(image_path)
        # 检查最小尺寸
        if img.width < min_size[0] or img.height < min_size[1]:
            raise ValueError("图片太小")
        # 缩放到最大尺寸
        img.thumbnail(max_size, Image.Resampling.LANCZOS)
        # 缓存文件名(基于内容哈希)
        content = open(image_path, 'rb').read()
        hash_id = hashlib.md5(content).hexdigest()[:10]
        output_name = f"resized_{hash_id}.{output_format.lower()}"
        # 保存
        img.save(output_name, output_format, quality=self.quality)
        return output_name
    def create_fit_size(self, image_path, target_width, target_height):
        """创建适合指定尺寸的图片(智能填充)"""
        img = Image.open(image_path)
        # 计算缩放比例
        ratio = min(target_width / img.width, target_height / img.height)
        new_size = (int(img.width * ratio), int(img.height * ratio))
        img = img.resize(new_size, Image.Resampling.LANCZOS)
        # 创建背景并居中
        background = Image.new('RGB', (target_width, target_height), (255, 255, 255))
        x = (target_width - new_size[0]) // 2
        y = (target_height - new_size[1]) // 2
        background.paste(img, (x, y))
        return background
    def multi_size_resize(self, image_path, sizes):
        """生成多种尺寸的缩略图"""
        img = Image.open(image_path)
        results = []
        for size_name, size in sizes.items():
            copy_img = img.copy()
            if size[0] and size[1]:
                # 指定宽高
                copy_img.thumbnail(size, Image.Resampling.LANCZOS)
            else:
                # 只指定宽(保持比例)
                if size[0]:
                    ratio = size[0] / img.width
                    copy_img = copy_img.resize((
                        size[0],
                        int(img.height * ratio)
                    ))
            output_name = f"{size_name}_{os.path.basename(image_path)}"
            copy_img.save(output_name, quality=self.quality)
            results.append((size_name, output_name))
        return results
# 使用示例
resizer = ImageResizer()
resizer.multi_size_resize('input.jpg', {
    'small': (150, 150),
    'medium': (400, 300),
    'large': (800, 600)
})

安装依赖

pip install pillow opencv-python flask

这些案例涵盖了日常开发中大部分的图片缩放需求,从简单的单张处理到复杂的批量处理、API接口开发等场景,根据您的具体需求选择合适的方案即可。

标签: Python 图像缩放

抱歉,评论功能暂时关闭!