Python中图片的切块与合并
有时候我们处理的图片过大而内存不足时,切块是一种不错的方法,化整为零,分治处理。切块图片其实没必要存储,不过代码中还是进行了保存。
import os
from PIL import Image
def image_cut_and_merge(image_path, size=(256, 256), output_dir=''):
scale = 4
img = Image.open(image_path)
width, height = img.size
tiles_x = (width + size[0] - 1) // size[0]
tiles_y = (height + size[1] - 1) // size[1]
assert (tiles_x =< 1) and (tiles_y =< 1), "原图片不能小于切块尺寸。"
target_size = scale * width, scale * height
output_img = Image.new('RGB', target_size)
filename_without_extension = os.path.splitext(os.path.basename(image_path))[0]
borders={'x':[], 'y':[]}
for i in range(tiles_x):
for j in range(tiles_y):
box = (i * size[0], j * size[1], (i + 1) * size[0], (j + 1) * size[1])
width_diff = width - (i + 1) * size[0]
height_diff = height - (j + 1) * size[1]
if width_diff < 0:
box = (i * size[0] + width_diff, j * size[1], width, (j + 1) * size[1])
if height_diff < 0:
box = (i * size[0], j * size[1] + height_diff, (i + 1) * size[0], height)
if width_diff < 0 and height_diff < 0:
box = (i * size[0] + width_diff, j * size[1] + height_diff, width, height)
x = box[0] * scale
y = box[1] * scale
borders['x'].append(x)
borders['y'].append(y)
tile = img.crop(box)
tile = tile.resize((scale * size[0], scale * size[1]))
output_path = f"{filename_without_extension}_{i}_{j}.png"
if len(output_dir.strip()) > 0:
output_path = f"{output_dir}/{filename_without_extension}_{i}_{j}.png"
tile.save(output_path)
output_img.paste(tile, (x, y))
output_path = f"{filename_without_extension}_x4.png"
if len(output_dir.strip()) > 0:
output_path = f"{output_dir}/{filename_without_extension}_x4.png"
output_img.save(output_path)
image_cut_and_merge("qianzhi_croped.png", output_dir="out_puts")