python+pillow不规则图片合成合并

需求

在这里插入图片描述

大部分查到的图片合成,都是将矩形图片贴到模板上,或者通过权重的方式,将几张图片合成到一张图片上。对于上图这种不规则的图片合成,尝试了两种方法:

  • 方法1:生成一个和模板图同等大小的空图,将目标图片裁切、旋转后贴到空图上,再进行图片的位运算合成。
  • 方法2:利用透视变换,将目标图片裁切后,变换到指定图形,再进行贴图。

从最终实现的结果来看,方法1只适合用于合成区域垂直于视线的场景,效果等同于方法2。方法2则适用面更广一些,可以处理一些复杂的场景。

摘要

技术栈如下:

代码演示:python
图像处理:pillow

演示

在进行处理前,需要先把图片中,将要贴图进去的位置扣掉,保存为png图片,用于后续的贴图。

在这里插入图片描述
这里将贴入空白区域的图片称为目标图片,大图称为模板图片。

import numpy as np
from PIL import Image

def find_coeffs(source_coords, target_coords):
    """
    PIL透视变换转换
    :param source_coords: 源区域点数组,类型数组
    :param target_coords: 目标区域点数组,类型数组
    :return:
    """
    matrix = []
    for s, t in zip(source_coords, target_coords):
        matrix.append([t[0], t[1], 1, 0, 0, 0, -s[0]*t[0], -s[0]*t[1]])
        matrix.append([0, 0, 0, t[0], t[1], 1, -s[1]*t[0], -s[1]*t[1]])
    A = np.matrix(matrix, dtype=np.float)
    B = np.array(source_coords).reshape(8)
    res = np.dot(np.linalg.inv(A.T * A) * A.T, B)
    return np.array(res).reshape(8)

def img_square_pil(img, position='middle'):
    # 将图像规整为正方形(pil版)  lt:top或left  rb:right或bottom
    if position not in ['middle', 'lt', 'rb']:
        raise Exception('position入参不合法')
    w, h = img.size
    if h >= w:
        # 纵向图
        t_y = ()
        if position == 'middle':
            t_y = (int((h-w)/2), int((h-w)/2 + w))
        elif position == 'lt':
            t_y = (0, w)
        elif position == 'rb':
            t_y = ((h - w), h)

        img = img.crop((0, t_y[0], w, t_y[1]))
    else:
        # 横向图
        t_x = ()
        if position == 'middle':
            t_x = (int((w-h)/2), int((w-h)/2 + h))
        elif position == 'lt':
            t_x = (0, h)
        elif position == 'rb':
            t_x = ((w - h), w)
        img = img.crop((t_x[0], 0, t_x[1], h))
    return img

img = Image.open('目标图片')
dec1 = Image.open(‘模板图片’)
dec1 = dec1.convert('RGBA')
img = img_square_pil(img)
iw, ih = img.size
dw, dh = dec1.size
tgt_w, tgt_h = 560, 650    # 目标图片裁切后的宽高。空白区域为矩形,需要裁切图片。
p1, p2, p3, p4 = (357, 395), (804, 510), (708, 1135), (138, 996)  # 空白区域四个点的坐标
img = img.resize((int(iw / (ih / tgt_h)), tgt_h), Image.ANTIALIAS)
iw, ih = img.size
img = img.crop((int((iw - tgt_w) / 2), 0, int((iw - tgt_w) / 2 + tgt_w), tgt_h))
iw, ih = img.size
coeffs = find_coeffs(
    [(0, 0), (iw, 0), (iw, ih), (0, ih)],  # 四个点顺序和下面四个点顺序相同,比如都是顺时针
    [p1, p2, p3, p4]
)
img = img.transform(dec1.size, Image.PERSPECTIVE, coeffs, Image.BICUBIC)
img.paste(dec1, (0, 0, dw, dh), mask=dec1.split()[-1])

效果展示

在这里插入图片描述

在这里插入图片描述




更多功能,或者想体验一下,可以扫下方二维码”:


在这里插入图片描述
主业前端程序猿一枚。图片处理方面,作为业余爱好。如有错误,请各位大佬轻喷,谢谢!!😂

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晴天晒小麦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值