paddlehub人像抠图+PIL图像处理

完整代码见:https://aistudio.baidu.com/aistudio/projectdetail/444078

文章目录

  • 一、环境配置
  • 二、定义函数
    • 1、人像抠图
    • 2、图像旋转
    • 3、上下/左右镜像
    • 4、图像剪切
    • 5、图像缩放
    • 6、添加文字
    • 7、背景合成
  • 三、调用函数

先看看最终效果图

paddlehub人像抠图+PIL图像处理_第1张图片

一、环境配置

首先要确保已经安装好了paddlepaddle。没有安装的需要先安装一下。paddlepaddle快速安装
然后将需要用到的库进行导入。

!pip install paddlehub==1.6.0 -i https://pypi.tuna.tsinghua.edu.cn/simple

import matplotlib.pyplot as plt 
import matplotlib.image as mpimg 
import paddlehub as hub
from PIL import Image
from PIL import ImageFilter 
from PIL import ImageEnhance 
from PIL import ImageDraw 
from PIL import ImageFont 
import numpy as np
import cv2

二、定义函数

1、人像抠图

我使用的是paddlehub中的deeplabv3p_xception65_humanseg。
需要注意的是这个模型对版本有一定的要求。 paddlepaddle >= 1.5.0 paddlehub >=
1.0.0

一切准备好后开始导入图片。

# 待预测图片的路径
test_img_path = ['test_img_path/1.jpg','test_img_path/2.jpg']
#预览一下原图片
for i in range(len(test_img_path)):
    img = mpimg.imread(test_img_path[i])
    plt.figure(figsize=(10,10))#决定显示的图片长宽
    plt.imshow(img)
    plt.axis('off')#图片坐标,off关闭坐标
    plt.show()

paddlehub人像抠图+PIL图像处理_第2张图片
paddlehub人像抠图+PIL图像处理_第3张图片
加载模型。

module = hub.Module(name="deeplabv3p_xception65_humanseg")

input_dict = {"image": test_img_path}

results = module.segmentation(data=input_dict)
for result in results:
    print(result)

# 结果展示,图片已经保存在文件夹humanseg_output中
for i in results:
    test_img_path = i['processed']
    img = mpimg.imread(test_img_path)
    plt.imshow(img) 
    plt.axis('on') 
    plt.show()

paddlehub人像抠图+PIL图像处理_第4张图片
抠得比较干净,但是人像抠图真的是仅仅人像抠图,如果人物手上有什么棒棒糖之类的也会被抠掉,有些细节确实没有直接用PS来的好,但是这个方便啊。

接下来几个函数都是简单的PIL库的使用。详细使用请见

2、图像旋转

original_rotate_img:输入需要旋转的图片的地址
rotate_img:输入旋转后图片保存的地址
angle:旋转角度,负顺正逆

def rotate_images(original_rotate_img,rotate_img,angle):
    
    #读取图片
    original_rotate_img = Image.open(original_rotate_img) 

    #将图片旋转
    rotate_image = original_rotate_img.rotate(angle) 

    #保存图片
    rotate_image.save(rotate_img)
   
    #显示旋转后的图片
    plt.imshow(rotate_image)  
    plt.show(rotate_image)  

3、上下/左右镜像

original_mirror_img:输入需要镜像的图片地址
lr_mirror_img:输入左右镜像后图片保存地址
bt_mirror_img:输入上下镜像后图片保存地址

def bt_inversion_image(original_mirror_img,bt_mirror_img):
    #打开图片
    original_mirror_img = Image.open(original_mirror_img) 

    #上下镜像
    mirror_image = original_mirror_img.transpose(Image.FLIP_TOP_BOTTOM)

    #保存图片
    mirror_image.save(bt_mirror_img)

    #展示上下镜像图片
    plt.imshow(mirror_image)  
    plt.show(mirror_image)
def lr_inversion_image(original_mirror_img,lr_mirror_img):
    #读取图片
    original_mirror_img = Image.open(original_mirror_img) 

    #左右镜像
    mirror_image = original_mirror_img.transpose(Image.FLIP_LEFT_RIGHT)

    #保存图片
    mirror_image.save(lr_mirror_img)

    #展示左右镜像图片
    plt.imshow(mirror_image)  
    plt.show(mirror_image)   

4、图像剪切

这个函数只能剪切长方形,如果要切割不规则形状,需要使用opencv,有兴趣的同学可以看看这篇文章。

original_shear_img:输入需要剪切的图片的地址
shear_img:输入剪切后图片保存地址
crop:剪切坐标

def shear_image(original_shear_img,shear_img,crop):
    #打开图片
    original_shear_img = Image.open(original_shear_img) 

    #剪切
    crop_result = original_shear_img.crop(crop)
    print(crop_result.size)

    #保存图片
    crop_result.save(shear_img)

    #展示图片
    plt.imshow(crop_result)  
    plt.show(crop_result)   

5、图像缩放

original_scaling_img:输入需要缩放的图片的地址
scaling_img:输入缩放后图片保存地址

#缩放
def scaling_image(original_scaling_img,scaling_img,w,h):
    #打开图片
    original_scaling_img = Image.open(original_scaling_img) 
    width,height = original_scaling_img.size

    #缩放
    scaling_image = original_scaling_img.resize((int(width*w),int(height*h)),Image.ANTIALIAS)
    print(scaling_image.size)

    #保存图片
    scaling_image.save(scaling_img)

    #展示图片
    plt.imshow(scaling_image)  
    plt.show(scaling_image) 

6、添加文字

如果没有之前下载好的字体需要先下载一下。
下载字体可以参考一下这段代码,有些时候会报错,表示已经存在fonts文件夹,但是表面上看不到,只是隐藏了,可以直接将创建文件路径的那句注释掉。

# 下载中文字体
!wget https://mydueros.cdn.bcebos.com/font/simhei.ttf
# 将字体文件复制到matplotlib字体路径
!cp simhei.ttf /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/mpl-data/fonts/ttf/
# 一般只需要将字体文件复制到系统字体目录下即可,但是在aistudio上该路径没有写权限,所以此方法不能用
# !cp simhei.ttf /usr/share/fonts/

# 创建系统字体文件路径
!mkdir .fonts
# 复制文件到该路径
!cp simhei.ttf .fonts/
!rm -rf .cache/matplotlib

我是直接将提前下载好的字体上传上去的,所以上面这段代码没有加上。

#添加文字
im = Image.open('scaling_img/2.png')
draw = ImageDraw.Draw(im)
fnt = ImageFont.truetype('simhei.ttf',250)#选择字体和字号
draw.text((70, 70), u'易烊千玺', fill='white', font=fnt)#选择左右上下的位置,内容,以及字体颜色
im.show()
im.save('background_img/2_font.jpg')

7、背景合成

需要注意的是前景照片与后景照片大小需一致,否则电脑会自动匹配成大小一致的状态,可以先在没有合成之前利用剪切和缩放功能,将前景与后景两张图片处理成差不多大小,然后进行拼合。

fore_image:前景图片,抠出的人物图片地址
base_image:背景图片地址
output_path:合成后的照片保存地址

def blend_images(fore_image, base_image,output_path):
    # 读入图片
    base_image = Image.open(base_image).convert('RGB')
    fore_image = Image.open(fore_image).resize(base_image.size)

    # 图片加权合成
    scope_map = np.array(fore_image)[:,:,-1] / 255
    scope_map = scope_map[:,:,np.newaxis]
    scope_map = np.repeat(scope_map, repeats=3, axis=2)
    res_image = np.multiply(scope_map, np.array(fore_image)[:,:,:3]) + np.multiply((1-scope_map), np.array(base_image))
    
    #保存图片
    res_image = Image.fromarray(np.uint8(res_image))
    res_image.save(output_path)

    #展示图片
    plt.imshow(res_image)  
    plt.show(res_image) 

三、调用函数

这里就是简单的调用之前定义好的函数。为了不那么单调以及将所有函数都尝试一下,我将图片做成了手幅和便签的样子,有兴趣的也可以试一下。(1厘米=25像素)先前说到的将前景与后景剪切缩放成一样大,有几点需要注意一下:
1.因为前景图片的背景是透明的,所以可以超过图片本身的大小剪切,甚至可以输入负值。例如我在剪切第二张图片时输入的值为(-120,-320,530,330)。
2.缩放是以丢失或增加像素为前提的,并不是对矢量图进行操作,所以缩太小或放太大对图片都有一定的影响。

你可能感兴趣的:(paddlehub人像抠图+PIL图像处理)