【工程应用接口】多张图片合并(python实现)

如需转载,请注明出处。
更多优质内容,详细测试程序,可点击原文链接进行阅读学习。

功能

合并前景与背景两张图片,可设置图片前景的透明度,缩放因子,位置,可自适应调整背景大小并且输出图片所在边界框位置,用于标注数据

实现

  1. 利用PIL包,将两张图片进行 paste
  2. 通过修改图片 alpha 值,对图片透明度进行修改
  3. 对图片的大小处理,获取最终的图片尺寸
  4. 根据调整后的前景图片尺寸,调整背景的尺寸
  5. 对前景边界框进行处理,得到合理的边界坐标

代码

2022.11.25 修复长宽相反的问题

def xywh2xyxyxyxy(x,y,w,h):
    return [[x,y],[x+w,y],[x+w,y+h],[x,y+h]]

def merge_image(fore_image, back_image, pos=(0,0),alpha=1.0,factor=1.0,padding=False,func=lambda x:x):
    """将两个图片进行合并,支持自定义透明度 alpha, 缩放factor, 背景图缩放开关 padding, 前景图回调函数 func

    Args:
        fore_image (PIL.Image): 前景图
        back_image (PIL.Image): 背景图
        pos (tuple, list): 左上角位置. Defaults to (0,0).
        alpha (float, optional): 前景透明度. Defaults to 1.0.
        factor (float, optional): 前景缩放因子. Defaults to 1.0.
        padding (bool, optional): 背景自适应缩放. Defaults to False.
        func (Functional, optional): 前景处理回调函数. Defaults to lambdax:x.

    Returns:
        PIL.Image: 合并后的图片
    """
    assert alpha <= 1.0, "Alpha must be less or equel than 1.0"
    final_image = back_image.copy() 
    fore_image_temp = fore_image.copy()   
    
    # 设置缩放因子 透明度
    fore_h, fore_w = fore_image_temp.size
    print(fore_w,fore_h)
    fore_new_w = int(fore_w / factor)
    fore_new_h = int(fore_h / factor)
    for i in range(fore_new_w):
        for k in range(fore_new_h):
            color = fore_image_temp.getpixel((i, k))
            color = color[:-1] + (int((color[-1]*alpha)%255), )
            fore_image_temp.putpixel((i, k), color)
    fore_image_temp = fore_image_temp.resize((fore_new_w, fore_new_h), Image.Resampling.LANCZOS)
    fore_image_temp = func(fore_image_temp)

    # 背景图不够大将会被resize
    if padding:
        back_limit_w = fore_new_w + pos[0]
        back_limit_h = fore_new_h + pos[1]
    else:
        back_limit_w = fore_new_w
        back_limit_h = fore_new_h
    
    # 设置背景图片大小
    back_h,back_w = final_image.size
    # 设置背景图大小
    if back_w < back_limit_w:
        back_new_w = back_limit_w
        print(f"背景图宽度过小, {back_w} < {back_limit_w}")
    if back_h < back_limit_h:
        back_new_h = back_limit_h
        print(f"背景图高度过小, {back_h} < {back_limit_h}")
    final_image = final_image.resize((back_new_w,back_new_h),Image.Resampling.LANCZOS)
    
    final_image.paste(fore_image_temp, pos, mask=fore_image_temp)
    fore_final_h, fore_final_w = fore_image_temp.size
    back_final_h, back_final_w =final_image.size
    label_x = pos[0] if pos[0]>0 else 0
    label_y = pos[1] if pos[1]>0 else 0
    label_w = pos[0]+fore_final_w-label_x if pos[0]+fore_final_w < back_final_w else back_final_w-label_x
    label_h = pos[1]+fore_final_h-label_y if pos[1]+fore_final_h < back_final_h else back_final_h-label_y
    
    return final_image, xywh2xyxyxyxy(label_x,label_y,label_w,label_h)

演示

猜你喜欢

转载自blog.csdn.net/liferecords/article/details/128036396