当前位置: 代码网 > it编程>前端脚本>Python > Python使用Pillow库实现图片拼接的方法步骤

Python使用Pillow库实现图片拼接的方法步骤

2026年08月09日 Python 我要评论
引言在图像处理任务中,图片拼接是非常常见的需求:把多张小图拼成一张大图,常用于数据集还原、九宫格图片复原、图像切片后重组、拼图业务等。pillow(pil)通过image.new()创建空白画布 +

引言

在图像处理任务中,图片拼接是非常常见的需求:把多张小图拼成一张大图,常用于数据集还原、九宫格图片复原、图像切片后重组、拼图业务等。pillow(pil)通过image.new()创建空白画布 + paste()粘贴图片实现拼接,支持横向拼接、纵向拼接、n×n矩阵拼接。

环境准备

pip install pillow

核心api说明

  1. image.new(mode, size):创建空白画布
    • mode:图像模式,rgb彩色,rgba带透明通道
    • size:(width, height)画布宽高
  2. canvas.paste(image, (x, y)):把图片粘贴到画布的(x,y)坐标位置
    • x:粘贴起始横坐标
    • y:粘贴起始纵坐标

注意:paste不会自动缩放图片,粘贴的子图尺寸必须和预留位置大小匹配。

场景1:横向拼接(左右排列)

把多张图片从左到右拼在一起,所有图片高度必须一致。

from pil import image
from typing import list


def concat_horizontal(img_list: list[image.image]) -> image.image:
    """横向拼接,图片从左向右排列,要求所有图片高度相同"""
    if not img_list:
        raise valueerror("图片列表不能为空")

    # 总宽度为所有图片宽度之和,高度取第一张图高度
    total_width = sum(img.width for img in img_list)
    height = img_list[0].height

    canvas = image.new("rgb", (total_width, height))

    offset_x = 0
    for img in img_list:
        canvas.paste(img, (offset_x, 0))
        offset_x += img.width
    return canvas


# 示例调用
if __name__ == "__main__":
    im1 = image.open("a.jpg")
    im2 = image.open("b.jpg")
    im3 = image.open("c.jpg")
    result = concat_horizontal([im1, im2, im3])
    result.save("horizontal.jpg")

场景2:纵向拼接(上下排列)

多张图片从上往下拼接,所有图片宽度必须一致。

def concat_vertical(img_list: list[image.image]) -> image.image:
    """纵向拼接,图片从上向下排列,要求所有图片宽度相同"""
    if not img_list:
        raise valueerror("图片列表不能为空")

    total_height = sum(img.height for img in img_list)
    width = img_list[0].width

    canvas = image.new("rgb", (width, total_height))

    offset_y = 0
    for img in img_list:
        canvas.paste(img, (0, offset_y))
        offset_y += img.height
    return canvas


# result = concat_vertical([im1, im2, im3])
# result.save("vertical.jpg")

场景3:n×n矩阵拼接(和之前分割函数配套)

输入子图列表 + 矩阵阶数split_count,输出完整大图。

适用:3×3、4×4九宫格复原,子图尺寸全部相同。

def merge_image_grid(tile_list: list[image.image], split_count: int) -> image.image:
    """
    n × n 矩阵拼接,与split_image分割函数配套
    :param tile_list: split_image返回的子图列表,行优先顺序
    :param split_count: 分割份数,3代表3行3列
    :return: 拼接完成的pil image对象
    """
    if not tile_list:
        raise valueerror("子图列表不能为空")
    if len(tile_list) != split_count * split_count:
        raise valueerror(f"子图数量不匹配,需要{split_count*split_count}张,实际{len(tile_list)}张")

    tile_w, tile_h = tile_list[0].size
    canvas_w = tile_w * split_count
    canvas_h = tile_h * split_count

    canvas = image.new("rgb", (canvas_w, canvas_h))

    index = 0
    for y in range(split_count):
        for x in range(split_count):
            canvas.paste(tile_list[index], (x * tile_w, y * tile_h))
            index += 1
    return canvas


if __name__ == "__main__":
    # 和分割代码完整联调示例
    from pil import image
    from your_module import split_image

    big_img = image.open("300x300.jpg")
    tiles = split_image(big_img, split_count=3)
    merged_img = merge_image_grid(tiles, split_count=3)
    merged_img.save("merge_output.jpg")

场景4:自定义行列拼接(m行n列,非正方形)

如果你想要 2行3列,不是n×n正方形矩阵:

def merge_custom_grid(tile_list: list[image.image], rows: int, cols: int) -> image.image:
    """自定义行列矩阵拼接 rows行 cols列"""
    tile_w, tile_h = tile_list[0].size
    canvas = image.new("rgb", (tile_w * cols, tile_h * rows))
    idx = 0
    for y in range(rows):
        for x in range(cols):
            canvas.paste(tile_list[idx], (x * tile_w, y * tile_h))
            idx += 1
    return canvas

# 示例:2行3列,共6张图片
# out = merge_custom_grid(tiles, rows=2, cols=3)

处理透明通道 rgba

如果你的图片是png带透明,创建画布时把模式改为rgba

canvas = image.new("rgba", (canvas_w, canvas_h))

常见踩坑点

  1. 子图尺寸不一致:paste不会自动缩放,子图大小不一样会出现错位、溢出。需要先统一尺寸。
  2. 图片模式不匹配:rgb图片粘贴到rgba画布可以;rgba粘贴到rgb画布会丢失透明通道,建议统一模式。
  3. 列表顺序错误:矩阵拼接严格依赖列表顺序,必须和分割时遍历顺序(行优先)保持一致。
  4. 索引越界:子图数量不等于 rows×cols,直接抛出异常,避免生成错误图片。

完整闭环:分割 + 拼接完整示例

from pil import image
import os
from typing import list


def split_image(
    img: image.image,
    split_count: int,
    save_dir: str = none
) -> list[image.image]:
    w, h = img.size
    tile_w = w // split_count
    tile_h = h // split_count
    tile_list: list[image.image] = []
    for y in range(split_count):
        for x in range(split_count):
            left = x * tile_w
            upper = y * tile_h
            right = left + tile_w
            lower = upper + tile_h
            tile = img.crop((left, upper, right, lower))
            tile_list.append(tile)
            if save_dir is not none:
                os.makedirs(save_dir, exist_ok=true)
                tile.save(os.path.join(save_dir, f"tile_x{x}_y{y}.png"))
    return tile_list


def merge_image_grid(tile_list: list[image.image], split_count: int) -> image.image:
    if not tile_list:
        raise valueerror("子图列表不能为空")
    if len(tile_list) != split_count * split_count:
        raise valueerror(f"子图数量不匹配,需要{split_count*split_count}张,实际{len(tile_list)}张")
    tile_w, tile_h = tile_list[0].size
    canvas_w = tile_w * split_count
    canvas_h = tile_h * split_count
    canvas = image.new("rgb", (canvas_w, canvas_h))
    index = 0
    for y in range(split_count):
        for x in range(split_count):
            canvas.paste(tile_list[index], (x * tile_w, y * tile_h))
            index += 1
    return canvas


if __name__ == "__main__":
    src_img = image.open("test.jpg")
    tile_list = split_image(src_img, split_count=3)
    print(f"分割得到 {len(tile_list)} 张图片")
    restore_img = merge_image_grid(tile_list, split_count=3)
    restore_img.save("restore.jpg")
    print("完成分割复原,输出 restore.jpg")

总结

  1. image.new()创建空白画布,paste()实现图片粘贴,是pillow拼接的底层核心。
  2. 分为横向、纵向、矩阵n×n三种常用场景;矩阵拼接可以完美复原之前分割出来的图片。
  3. 注意图片尺寸、图像模式、列表顺序,这三个是拼接出错最高的地方。
  4. 分割与拼接组合,完成图片切片、复原完整流程,适合数据集预处理、九宫格业务。

拓展方向:可以增加边框、间隙,在子图之间添加空白间隔;也可以增加缩放逻辑自动适配子图大小。

以上就是python使用pillow库实现图片拼接的方法步骤的详细内容,更多关于python pillow库图片拼接的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com