本文目录导读:
我来为您介绍几个实用的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接口开发等场景,根据您的具体需求选择合适的方案即可。