应用体验:证件照一键生成
应用体验:证件照一键生成
本项目主要是为了方便大家照不那么严格的证件照,纯自助,只要拿手机一拍,在“应用体验”页面上传,项目自动抠图和排版,再下载下来的就是符合背景色要求的证件照了。本项目只为方便大家,一些要求非常严格的证件照,还是建议在专业招照相馆或者自助机上进行。
整个项目使用步骤很简单:
- 在“应用体验”页面拍照上传,要求露双肩。并根据证件照其它要求提前做好构图取景等。因为可以抠图换背景,所以不需要专业照相馆里的背景布
- 选择合适的背景色,有红色、蓝色和白色三种颜色可选。然后点“提交图片”,系统就自动进行抠图换背景。
- 选择合适的照片下载。处理后的照片显示出来,根据需求,点击合适的照片下载即可。
一、应用体验项目的问题分解
为了较快实现功能,选择了FastDeploy。就AIStudio的应用中心实现来推测,不太合适使用飞桨Serving,因此选型就剩下了FastDeploy、Hub以及Inference。其中前两个都封装的较好,属于开箱能用的。
1、实现基本功能,在notebook下跑通
- 拍照上传,使用AIStudio的上传功能
- 抠像,系统后台使用飞桨AI框架进行自动扣图。本项目最内核的部分就是这里了
- 后处理,主要是填背景色和证件照排版输出
生成的图片,可以在AIStudio notebook下右键下载。
2、在本地应用中心调试跑通
BML CodeLab提供用户创建应用、调试应用和部署应用等功能。相关功能以Streamlit作为底层技术,为用户提供快速搭建交互式图形化界面的能力,只需要几行代码即可搭建一个炫酷的图形化界面。
文档参考:https://ai.baidu.com/ai-doc/AISTUDIO/Gktuwqf1x#应用
- 按照应用中心例子,写应用代码。主要是页面展示
- 将前面测试好的抠图和后处理代码,嵌入。
- 本地“运行”调试,调试成功后部署即可。
在本项目中,为了更好的展示,也为了加快调试,使用了“默认图片”的设置,“运行”后直接点击“提交照片”即可测试。
会自动输出1寸照片和5寸6寸混排照片,选中合适的照片下载即可。
3、在服务端应用部署调试成功
可以使用“在浏览器打开”进行调试,但最终在部署后还需要调试,以免有任何遗漏,影响应用的体验。
二、在notebook下跑通
在学习FastDeploy、PaddleDet等多种套件模型后,选择FastDeploy里面的PP-Matting模型。具体文档见:https://gitee.com/paddlepaddle/FastDeploy/tree/develop/examples/vision/matting/ppmatting/python
1、安装FastDeploy
因最终“应用体验”使用的是cpu版本,所以这里最终安装cpu版本。
测试中发现cpu版本安装的时候较慢,尽管gpu版本文件1.68G,有时候反而安装速度要快于cpu版本。所以在调试的时候,大部分时候都是选择AIStudio高端版GPU版,FastDeploy也是安装的GPU版。因为飞桨面向用户的代码是不需要区分GPU和cpu,所以不管使用GPU还是cpu,除了处理速度不同外,开发者不会有任何不同的感受。
# !pip install fastdeploy-gpu-python -f https://www.paddlepaddle.org.cn/whl/fastdeploy.html
!pip install fastdeploy-python -f https://www.paddlepaddle.org.cn/whl/fastdeploy.html
2、准备PP-Matting模型
FastDeploy需要手动下载模型文件,从上面的文档中,可以看到下载语句。文档中是512 * 512大小模型,我这里选了1024* 1024图片的小的模型。
# 下面这句大约是PaddleSeg库里的抠图模型
# !cd ~/work/ && wget https://paddleseg.bj.bcebos.com/matting/models/deploy/pp-matting-hrnet_w18-human_1024.zip && unzip pp-matting-hrnet_w18-human_1024.zip
# fastdeploy库的模型
# !wget https://bj.bcebos.com/paddlehub/fastdeploy/PP-Matting-512.tgz && tar -xvf PP-Matting-512.tgz
!wget https://bj.bcebos.com/paddlehub/fastdeploy/PP-Matting-1024.tgz && tar -xvf PP-Matting-1024.tgz
3、抠图核心代码实现
PP-Matting API https://www.paddlepaddle.org.cn/fastdeploy-api-doc/python/html/matting.html
fastdeploy.vision.matting.PPMatting
class fastdeploy.vision.matting.PPMatting(model_file, params_file, config_file, runtime_option=None, model_format=<ModelFormat.PADDLE: 1>)[source]
Load a PPMatting model exported by PaddleSeg.
以下为手册中的例子,先跑通。然后学习和拆分核心代码,以移植到notebook下,并为最终“应用体验”部署做准备。
跑通PP-Matting例子
# #下载部署示例代码
!git clone https://github.com/PaddlePaddle/FastDeploy.git
%cd ~/FastDeploy/examples/vision/matting/ppmatting/python
# # 下载PP-Matting模型文件和测试图片
!wget https://bj.bcebos.com/paddlehub/fastdeploy/PP-Matting-512.tgz
!tar -xvf PP-Matting-512.tgz
!wget https://bj.bcebos.com/paddlehub/fastdeploy/matting_input.jpg
!wget https://bj.bcebos.com/paddlehub/fastdeploy/matting_bgr.jpg
# # CPU推理
!python infer.py --model PP-Matting-512 --image matting_input.jpg --bg matting_bgr.jpg --device cpu
# # GPU推理
# !python infer.py --model PP-Matting-512 --image matting_input.jpg --bg matting_bgr.jpg --device gpu
# # GPU上使用TensorRT推理 (注意:TensorRT推理第一次运行,有序列化模型的操作,有一定耗时,需要耐心等待)
# !python infer.py --model PP-Matting-512 --image matting_input.jpg --bg matting_bgr.jpg --device gpu --use_trt True
%cd ~/
将PP-Matting例子代码移植到notebook下
使用PP-Matting-1024模型进行抠图
https://gitee.com/paddlepaddle/FastDeploy/tree/develop/examples/vision/matting/ppmatting/python
# 下载1024模型
!wget https://bj.bcebos.com/paddlehub/fastdeploy/PP-Matting-1024.tgz
!tar -xvf PP-Matting-1024.tgz
# 将infer.py代码移植到notebook下执行
import fastdeploy as fd
import cv2
import os
# 配置runtime,加载模型
# runtime_option = build_option(args)
runtime_option = None
argsmodel = "/home/aistudio/PP-Matting-1024/"
model_file = os.path.join(argsmodel, "model.pdmodel")
params_file = os.path.join(argsmodel, "model.pdiparams")
config_file = os.path.join(argsmodel, "deploy.yaml")
# model = fd.vision.matting.PPMatting(
# model_file, params_file, config_file, runtime_option=runtime_option)
model = fd.vision.matting.PPMatting(
model_file, params_file, config_file)
抠图结束后,将其存为visualized_result_fg文件。
为了换背景色,先代码生成红、蓝和白三色图片。
# 写三张颜色背景图
import numpy as np
x = np.ndarray([800, 600, 3])
x[:, :, :] = 0
x[:, :, 0] = 255
cv2.imwrite("blue.jpg", x)
x[:, :, :] = 0
x[:, :, 1] = 255
cv2.imwrite("green.jpg", x)
x[:, :, :] = 0
x[:, :, 2] = 255
cv2.imwrite("red.jpg", x)
x[:, :, :] = 255
cv2.imwrite("white.jpg", x)
# 预测图片抠图结果
%cd ~/
argsimage = "work/beautysmall.jpg"
argsbg = "beautysmall.jpg"
im = cv2.imread(argsimage)
# bg = cv2.imread(argsbg)
bgrgb = "red"
if bgrgb == "red":
bgrgb = cv2.imread("red.jpg")
elif bgrgb == "blue":
bgrgb = cv2.imread("blue.jpg")
else :
bgrgb = cv2.imread("white.jpg")
bg = bgrgb
result = model.predict(im.copy())
# print(result)
# 可视化结果
vis_im = fd.vision.vis_matting(im, result)
vis_im_with_bg = fd.vision.swap_background_matting(im, bg, result)
# vis_im_with_red = fd.vision.swap_background_matting(im, bgrgb, result)
cv2.imwrite("visualized_result_fg.png", vis_im)
cv2.imwrite("visualized_result_replaced_bg.jpg", vis_im_with_bg)
print(
"Visualized result save in ./visualized_result_replaced_bg.jpg and ./visualized_result_fg.jpg"
)
# vis_im_with_red.show()
可以点击生成的图片:visualized_result_replaced_bg.jpg,观察是否达到了预计的目标。
4、后处理
证件照的大小要求:
1、一寸照片尺寸大小为:2.5*3.5cm(厘米)。一寸照片用的太普遍了,我们常见的有学生证、健康证、工作证、中小学生教师资格证、驾驶证等。2、二寸照片尺寸大小为:3.5*4.5cm(厘米)。二寸主要用在部分公务员和部分国家的签证。中国护照、港澳通行证、台湾通行证、韩国以及澳大利亚签证、雅思考试、全国计算机等级考试、英语四六级考试等。
作者:兰花草
链接:https://www.zhihu.com/question/330460193/answer/723674520
zhege gengxiangxi
这个更详细
https://zhuanlan.zhihu.com/p/549253320
1寸 295px × 413px 25* 35
2寸 413px × 579px
5寸生活照片 89mm × 127mm 1050px × 1500px
针对1寸照片需求,我们需要把大小调整为295*413 。使用F.resize函数即可。
import numpy as np
from PIL import Image
from paddle.vision.transforms import functional as F
fake_img = (np.random.rand(256, 300, 3) * 255.).astype('uint8')
fake_img = Image.fromarray(fake_img)
converted_img = F.resize(fake_img, 224)
testim = F.tran
testimg = F.resize(vis_im, (295, 413, 3))
print(converted_img.size)
print(testimg.size)
加白框
思路,可以把图片调整为290 * 408 ,然后再叠加到295 * 413
也可以采用在295 * 413照片上画白线来解决。倾向于第二个方法。
弄明白了,单照片不用放边框。
平铺以便打印
5寸 8.9* 12.7 0.7
6寸 10.2* 15.2 0.67
大6寸 114* 15.2 0.75
这样5寸可以打9张 ,3列3排
295* 3 = 885 2.5* 3 = 7.5
413* 3 = 1239 3.5* 3=10.5
这样可以有足够的位置放白框。纵横间隔为40像素,这样打印照片的大小为:
295* 3+40* 4= 1045
413* 3 +40* 4 =1399 约等于1400 ,这样打印的时候有一定的盈余。
5、后处理实践
因为比较复杂,所以单独列一项出来。
几个技术,经过比较,后来决定使用csnd上现成的代码。
以下是中间走过的弯路
Pad增加边界
class paddle.vision.transforms.Pad(padding, fill=0, padding_mode=‘constant’, keys=None)
img (PIL.Image|np.ndarray|Paddle.Tensor) - 输入的图像数据,数据格式为’HWC’。
output (PIL.Image|np.ndarray|Paddle.Tensor) - 返回填充后的图像数据。
padding (int|list|tuple) - 在图像边界上进行填充的范围。如果提供的是单个 int 值,则该值用于填充图像所有边;如果提供的是长度为 2 的元组/列表,则分别为图像左/右和顶部/底部进行填充;如果提供的是长度为 4 的元组/列表,则按照左,上,右和下的顺序为图像填充。
fill (int|list|tuple,可选) - 用于填充的像素值。仅当 padding_mode 为 constant 时参数值有效。 默认值:0。 如果参数值是一个长度为 3 的元组,则会分别用于填充 R,G,B 通道。
Resize调整大小
class paddle.vision.transforms.Resize(size, interpolation=‘bilinear’, keys=None)[源代码]
将输入数据调整为指定大小。
需要调整称2.5:3.5 也就是5:7的比例,这样原图cai bu bi
CenterCrop
class paddle.vision.transforms.CenterCrop(size, keys=None)[源代码]
对输入图像进行裁剪,保持图片中心点不变。
主要是调整成5:7的比例
csdn学到的代码
这段代码不错。 拿来用了,来源于csdn论坛:http://t.csdn.cn/8UhHo
# Author:ZM
# http://t.csdn.cn/8UhHo
"""
照片尺寸,宽*高(单位:像素)
1寸照片:295*413
2寸照片:413*626
5寸照片(横版):1500*1050
6寸照片(横版):1800*1200
"""
from PIL import Image,ImageDraw
WIDTH_1IN = 295
HEIGHT_1IN = 413
WIDTH_2IN = 413
HEIGHT_2IN = 626
WIDTH_5IN = 1500
HEIGHT_5IN = 1050
# 非全景6寸照片
WIDTH_6IN = 1950
HEIGHT_6IN = 1300
def cut_photo(photo,choice):
"""
将照片按照比例进行裁剪成1寸、2寸
:param photo: 待处理的照片
:param choice: <int> 1代表1寸,2代表2寸
:return: 处理后的照片
"""
width = photo.size[0] # 宽
height = photo.size[1] #高
rate = height / width
if choice == 1:
if rate < (HEIGHT_1IN/WIDTH_1IN):
x = (width - int(height / HEIGHT_1IN * WIDTH_1IN)) / 2
y = 0
cutted_photo = photo.crop((x, y, x + (int(height / HEIGHT_1IN * WIDTH_1IN)), y + height))
else:
x = 0
y = (height - int(width / WIDTH_1IN * HEIGHT_1IN)) / 2
cutted_photo = photo.crop((x, y, x + width, y + (int(width / WIDTH_1IN * HEIGHT_1IN))))
return cutted_photo
if choice == 2:
if rate < (HEIGHT_2IN/WIDTH_2IN):
x = (width - int(height / HEIGHT_2IN * WIDTH_2IN)) / 2
y = 0
cutted_photo = im.crop((x, y, x + (int(height / HEIGHT_2IN * WIDTH_2IN)), y + height))
else:
x = 0
y = (height - int(width / WIDTH_2IN * HEIGHT_2IN)) / 2
cutted_photo = im.crop((x, y, x + width, y + (int(width / WIDTH_2IN * HEIGHT_2IN))))
return cutted_photo
def resize_photo(photo,choice):
'''
缩放照片
:param photo: 待处理的照片
:param choice: <int> 1代表1寸,2代表2寸
:return: 处理后的照片
'''
if choice == 1:
resized_photo = photo.resize((WIDTH_1IN,HEIGHT_1IN))
return resized_photo
if choice == 2:
resized_photo = photo.resize((WIDTH_2IN, HEIGHT_2IN))
return resized_photo
def layout_photo_5_1(photo):
"""
在5寸照片上排版1寸照片
:param photo: 待处理照片1寸
:return: 处理后的照片
"""
bk = Image.new("RGB", [WIDTH_5IN,HEIGHT_5IN], (255,255,255))
draw = ImageDraw.Draw(bk)# 创建画笔
draw.line([(0,HEIGHT_5IN/2),(WIDTH_5IN,HEIGHT_5IN/2)],fill=128) # 横线
draw.line([(WIDTH_5IN*0.25,0),(WIDTH_5IN*0.25,HEIGHT_5IN)],fill=128) # 第1条竖线
draw.line([(WIDTH_5IN*0.5,0),(WIDTH_5IN*0.5,HEIGHT_5IN)],fill=128) # 第2条竖线
draw.line([(WIDTH_5IN*0.75,0),(WIDTH_5IN*0.75,HEIGHT_5IN)],fill=128) # 第3条竖线
focus_point = [0.125 * WIDTH_5IN,0.25 * HEIGHT_5IN]
start_point = [focus_point[0] - 0.5 * WIDTH_1IN, focus_point[1] - 0.5 * HEIGHT_1IN]
for i in range(0,2):
for k in range(0,4):
bk.paste(photo, (int(start_point[0] + (k * WIDTH_5IN / 4)), int(start_point[1] + 0.5 * i * HEIGHT_5IN)))
return bk
def layout_photo_5_2(photo):
"""
在5寸照片上排版2寸照片
:param photo: 待处理照片2寸
:return: 处理后的照片
"""
bk = Image.new("RGB", [HEIGHT_5IN,WIDTH_5IN], (255,255,255)) # 竖版排版
# 创建画笔
draw = ImageDraw.Draw(bk)
draw.line([(0,WIDTH_5IN/2),(WIDTH_5IN,WIDTH_5IN/2)],fill=128) # 横线
draw.line([(HEIGHT_5IN*0.5,0),(HEIGHT_5IN*0.5,WIDTH_5IN)],fill=128) # 竖线
focus_point = [0.25 * HEIGHT_5IN, 0.25 * WIDTH_5IN]
start_point = [focus_point[0] - 0.5 * WIDTH_2IN, focus_point[1] - 0.5 * HEIGHT_2IN]
#print(focus_point,start_point)
for i in range(0,2):
for k in range(0,2):
bk.paste(photo, (int(start_point[0] + (k * HEIGHT_5IN / 2)), int(start_point[1] + 0.5* i * WIDTH_5IN)))
return bk
def layout_photo_5_mix(photo1,photo2):
"""
在5寸照片上混合排版1寸、2寸照片
:param photo1: 待处理照片1寸
:param photo1: 待处理照片2寸
:return: 处理后的照片
"""
bk = Image.new("RGB", [WIDTH_5IN,HEIGHT_5IN], (255,255,255))
# 创建画笔
draw = ImageDraw.Draw(bk)
draw.line([(0,HEIGHT_5IN/2),(WIDTH_5IN,HEIGHT_5IN/2)],fill=128) # 横线
draw.line([(WIDTH_5IN*0.25,0),(WIDTH_5IN*0.25,HEIGHT_5IN)],fill=128) # 第1条竖线
draw.line([(WIDTH_5IN*0.5,0),(WIDTH_5IN*0.5,HEIGHT_5IN)],fill=128) # 第2条竖线
focus_point = [0.125 * WIDTH_5IN,0.25 * HEIGHT_5IN]
start_point = [focus_point[0] - 0.5 * WIDTH_1IN, focus_point[1] - 0.5 * HEIGHT_1IN]
focus_point2 = [0.75 * WIDTH_5IN, 0.25 * HEIGHT_5IN]
start_point2 = [focus_point2[0] - 0.5 * HEIGHT_2IN, focus_point2[1] - 0.5 * WIDTH_2IN]
for i in range(0,2):
for k in range(0,2):
bk.paste(photo1, (int(start_point[0] + (k * WIDTH_5IN / 4)), int(start_point[1] + 0.5 * i * HEIGHT_5IN)))
bk.paste(photo2,(int(start_point2[0]),int(start_point2[1])))
bk.paste(photo2,(int(start_point2[0]),int(start_point2[1] + 0.5 * HEIGHT_5IN)))
return bk
def layout_photo_6_1(photo):
"""
在6寸照片上排版2寸照片
:param photo: 待处理照片1寸
:return: 处理后的照片
"""
bk = Image.new("RGB", [HEIGHT_6IN,WIDTH_6IN], (255,255,255)) # 竖版排版
# 创建画笔
draw = ImageDraw.Draw(bk)
draw.line([(0,WIDTH_6IN*0.25),(WIDTH_6IN,WIDTH_6IN*0.25)],fill=128) # 横线
draw.line([(0,WIDTH_6IN*0.5),(WIDTH_6IN,WIDTH_6IN*0.5)],fill=128) # 横线
draw.line([(0,WIDTH_6IN*0.75),(WIDTH_6IN,WIDTH_6IN*0.75)],fill=128) # 横线
draw.line([(HEIGHT_6IN*0.25,0),(HEIGHT_6IN*0.25,WIDTH_6IN)],fill=128) # 竖线
draw.line([(HEIGHT_6IN*0.5,0),(HEIGHT_6IN*0.5,WIDTH_6IN)],fill=128) # 竖线
draw.line([(HEIGHT_6IN*0.75,0),(HEIGHT_6IN*0.75,WIDTH_6IN)],fill=128) # 竖线
focus_point = [0.125 * HEIGHT_6IN, 0.125 * WIDTH_6IN]
start_point = [focus_point[0] - 0.5 * WIDTH_1IN, focus_point[1] - 0.5 * HEIGHT_1IN]
#print(focus_point,start_point)
for i in range(0,4):
for k in range(0,4):
bk.paste(photo, (int(start_point[0] + (k * HEIGHT_6IN / 4)), int(start_point[1] + i * 0.25 * WIDTH_6IN )))
return bk
def layout_photo_6_2(photo):
"""
在6寸照片上排版2寸照片
:param photo: 待处理照片2寸
:return: 处理后的照片
"""
bk = Image.new("RGB", [WIDTH_6IN,HEIGHT_6IN], (255,255,255))
# 创建画笔
draw = ImageDraw.Draw(bk)
draw.line([(0,HEIGHT_6IN/2),(WIDTH_6IN,HEIGHT_6IN/2)],fill=128) # 横线
draw.line([(WIDTH_6IN*0.25,0),(WIDTH_6IN*0.25,HEIGHT_6IN)],fill=128) # 第1条竖线
draw.line([(WIDTH_6IN*0.5,0),(WIDTH_6IN*0.5,HEIGHT_6IN)],fill=128) # 第2条竖线
draw.line([(WIDTH_6IN*0.75,0),(WIDTH_6IN*0.75,HEIGHT_6IN)],fill=128) # 第3条竖线
focus_point = [0.125 * WIDTH_6IN,0.25 * HEIGHT_6IN]
start_point = [focus_point[0] - 0.5 * WIDTH_2IN, focus_point[1] - 0.5 * HEIGHT_2IN]
for i in range(0,2):
for k in range(0,4):
bk.paste(photo, (int(start_point[0] + (k * WIDTH_6IN / 4)), int(start_point[1] + 0.5 * i * HEIGHT_6IN)))
return bk
def layout_photo_6_mix1(photo1,photo2):
"""
在6寸照片上混合排版1寸、2寸照片
:param photo1: 待处理照片1寸
:param photo1: 待处理照片2寸
:return: 处理后的照片
"""
bk = Image.new("RGB", [WIDTH_6IN,HEIGHT_6IN], (255,255,255))
# 创建画笔
draw = ImageDraw.Draw(bk)
draw.line([(0,HEIGHT_6IN*0.5),(WIDTH_6IN,HEIGHT_6IN/2)],fill=128) # 横线
draw.line([(0,HEIGHT_6IN*0.25),(WIDTH_6IN*0.5,HEIGHT_6IN*0.25)],fill=128) # 短横线
draw.line([(0,HEIGHT_6IN*0.75),(WIDTH_6IN*0.5,HEIGHT_6IN*0.75)],fill=128) # 短横线
draw.line([(WIDTH_6IN*0.25,0),(WIDTH_6IN*0.25,HEIGHT_6IN)],fill=128) # 第1条竖线
draw.line([(WIDTH_6IN*0.5,0),(WIDTH_6IN*0.5,HEIGHT_6IN)],fill=128) # 第2条竖线
draw.line([(WIDTH_6IN*0.75,0),(WIDTH_6IN*0.75,HEIGHT_6IN)],fill=128) # 第3条竖线
focus_point = [0.125 * WIDTH_6IN, 0.125 * HEIGHT_6IN]
start_point = [focus_point[0] - 0.5 * HEIGHT_1IN, focus_point[1] - 0.5 * WIDTH_1IN]
for i in range(0,4):
for k in range(0,2):
bk.paste(photo1, (int(start_point[0] + (0.25 * k * WIDTH_6IN )), int(start_point[1] + 0.25 * i * HEIGHT_6IN)))
focus_point2 = [0.625 * WIDTH_6IN, 0.25 * HEIGHT_6IN]
start_point2 = [focus_point2[0] - 0.5 * WIDTH_2IN, focus_point2[1] - 0.5 * HEIGHT_2IN]
for i in range(0,2):
for k in range(0,2):
bk.paste(photo2,(int(start_point2[0] + (0.25 * k * WIDTH_6IN)), int(start_point2[1] + 0.5 * i * HEIGHT_6IN)))
# 显示图片
# bk.show()
return bk
def layout_photo_6_mix2(photo1,photo2):
"""
在6寸照片上混合排版1寸、2寸照片
:param photo1: 待处理照片1寸
:param photo1: 待处理照片2寸
:return: 处理后的照片
"""
bk = Image.new("RGB", [HEIGHT_6IN,WIDTH_6IN], (255,255,255)) # 竖版排版
# 创建画笔
draw = ImageDraw.Draw(bk)
draw.line([(350,0),(350,WIDTH_6IN)],fill=128) # 竖线
draw.line([(700,0),(700,WIDTH_6IN)],fill=128) # 竖线
draw.line([(0,WIDTH_6IN*0.25),(700,WIDTH_6IN*0.25)],fill=128) # 横线1
draw.line([(0,WIDTH_6IN*0.5),(700,WIDTH_6IN*0.5)],fill=128) # 横线2
draw.line([(0,WIDTH_6IN*0.75),(700,WIDTH_6IN*0.75)],fill=128) # 横线3
draw.line([(700,WIDTH_6IN/3),(HEIGHT_6IN,WIDTH_6IN/3)],fill=128) # 横线4
draw.line([(700,WIDTH_6IN*2/3),(HEIGHT_6IN,WIDTH_6IN*2/3)],fill=128) # 横线5
focus_point = [0.5 * 350, 0.125 * WIDTH_6IN]
start_point = [focus_point[0] - 0.5 * WIDTH_1IN, focus_point[1] - 0.5 * HEIGHT_1IN]
#print(focus_point,start_point)
for i in range(0,4):
for k in range(0,2):
bk.paste(photo1, (int(start_point[0] + (k * 350)), int(start_point[1] + i * 0.25 * WIDTH_6IN )))
focus_point2 = [0.5 * HEIGHT_6IN+350, WIDTH_6IN/6]
start_point2 = [focus_point2[0] - 0.5 * WIDTH_2IN, focus_point2[1] - 0.5 * HEIGHT_2IN]
for i in range(0,3):
bk.paste(photo2, (int(start_point2[0]), int(start_point2[1] + i * WIDTH_6IN /3)))
return bk
im = Image.open('beautysmall.jpg')
width = im.size[0]
height = im.size[1]
rate = height / width
layout_photo_5_1(resize_photo(cut_photo(im,1),1)).save('5_1.jpg')
layout_photo_5_2(resize_photo(cut_photo(im,2),2)).save('5_2.jpg')
layout_photo_6_1(resize_photo(cut_photo(im,1),1)).save('6_1.jpg')
layout_photo_6_2(resize_photo(cut_photo(im,2),2)).save('6_2.jpg')
layout_photo_5_mix(resize_photo(cut_photo(im,1),1),resize_photo(cut_photo(im,2),2).rotate(90,expand=True)).save('5_1_mix.jpg')
layout_photo_6_mix1(resize_photo(cut_photo(im,1),1).rotate(90,expand=True),resize_photo(cut_photo(im,2),2)).save('6_mix1.jpg')
layout_photo_6_mix2(resize_photo(cut_photo(im,1),1),resize_photo(cut_photo(im,2),2)).save('6_mix2.jpg')
将该文件命名为printpic.py存盘到work目录,并调试调用。
发现每个函数需要单独import,否则报错。
from work.printpic import cut_photo
from work.printpic import resize_photo
from work.printpic import layout_photo_5_1
from work.printpic import layout_photo_5_2
from work.printpic import layout_photo_6_1
from work.printpic import layout_photo_6_2
from work.printpic import layout_photo_5_mix
from work.printpic import layout_photo_6_mix1
from work.printpic import layout_photo_6_mix2
from PIL import Image,ImageDraw
im = Image.open('visualized_result_replaced_bg.jpg')
layout_photo_5_1(resize_photo(cut_photo(im,1),1)).save('5_1.jpg')
layout_photo_5_2(resize_photo(cut_photo(im,2),2)).save('5_2.jpg')
layout_photo_6_1(resize_photo(cut_photo(im,1),1)).save('6_1.jpg')
layout_photo_6_2(resize_photo(cut_photo(im,2),2)).save('6_2.jpg')
layout_photo_5_mix(resize_photo(cut_photo(im,1),1),resize_photo(cut_photo(im,2),2).rotate(90,expand=True)).save('5_1_mix.jpg')
layout_photo_6_mix1(resize_photo(cut_photo(im,1),1).rotate(90,expand=True),resize_photo(cut_photo(im,2),2)).save('6_mix1.jpg')
layout_photo_6_mix2(resize_photo(cut_photo(im,1),1),resize_photo(cut_photo(im,2),2)).save('6_mix2.jpg')
6、使用PaddleSeg里面的pp-matting(尝试过,未入选)
# !git clone https://github.com/PaddlePaddle/PaddleSeg
# %%writefile pipinstall.sh
# cd PaddleSeg
# pip install -r requirements.txt
# pip install -e .
# cd Matting
# pip install -r requirements.txt
# !sh pipinstall.sh
# !cd ~/work/ && wget https://paddleseg.bj.bcebos.com/matting/models/deploy/pp-matting-hrnet_w18-human_1024.zip && unzip pp-matting-hrnet_w18-human_1024.zip
背景替换
export CUDA_VISIBLE_DEVICES=0
python bg_replace.py \
--config configs/modnet/modnet-mobilenetv2.yml \
--model_path output/best_model/model.pdparams \
--image_path path/to/your/image \
--background path/to/your/background/image \
--save_dir ./output/results \
--fg_estimate True
如模型需要trimap信息,需要通过--trimap_path
传入trimap路径。
--background
可以传入背景图片路劲,或选择(‘r’,‘g’,‘b’,‘w’)中的一种,代表红,绿,蓝,白背景, 若不提供则采用绿色作为背景。
--fg_estimate False
可关闭前景估计功能,可提升预测速度,但图像质量会有所降低
注意: --image_path
必须是一张图片的具体路径。
你可以直接下载我们提供的模型进行背景替换。
# !cd PaddleSeg/Matting && python tools/bg_replace.py \
# --config configs/modnet/modnet-mobilenetv2.yml \
# --model_path ~/work/pp-matting-hrnet_w18-human_1024/model.pdiparams \
# --image_path ~/work/beautysmall.jpg \
# --background "b" \
# --save_dir ~/work/ \
# --fg_estimate True
三、应用创建工具
点击新建-应用创建工具,生成应用文件模版,我这里改名为:app.streamlit.py。刚开始看见满屏的代码,可能有点不知所措,可以参考这个项目大头贴拍照机:https://aistudio.baidu.com/aistudio/projectdetail/5045676
1、将前面跑通的notebook代码写入app.streamlit.py
主要是注意代码中涉及到目录文件的代码,因为最终部署的时候需要打包到一个文件夹中,所以没法像传统项目那样在根目录下放好几个目录。当然可以在打包目录里面放几个目录。这个项目中,我们把打包目录设定为~/work目录 。
2、本机运行测试
根据报错信息,哪里出错调哪里。
3、应用部署调试
因为使用了FastDeploy库,所以需要在打包目录写一个requirements.txt文件。
文件内容为:fastdeploy-python -f https://www.paddlepaddle.org.cn/whl/fastdeploy.html
调试
fastdeploy部署报错error: the following arguments are required: --recipe, --mode
usage: infer.py [-h] --recipe RECIPE --mode MODE [--queue_dir QUEUE_DIR]
[--base BASE] [--docker_args DOCKER_ARGS]
infer.py: error: the following arguments are required: --recipe, --mode
修改成这样报错:
pwdpath = !pwd
!cd ~/FastDeploy/examples/vision/matting/ppmatting/python && python infer.py --recipe $pwdpath --mode MODE --model PP-Matting-512 --image matting_input.jpg --bg matting_bgr.jpg --device cpu
报错
usage: infer.py [-h] --recipe RECIPE --mode MODE [--queue_dir QUEUE_DIR]
[--base BASE] [--docker_args DOCKER_ARGS]
infer.py: error: unrecognized arguments: --model PP-Matting-512 --image matting_input.jpg --bg matting_bgr.jpg --device cpu
这样看全乱套了啊!
在按照手册安装好FastDeploy之后,终于正常了!pip install fastdeploy-gpu-python -f https://www.paddlepaddle.org.cn/whl/fastdeploy.html
照片后处理程序报错
在notebook下正常,赚到命令行下就报错
aistudio@jupyter-209599-1243758:~/work$ python printpic.py
Traceback (most recent call last):
File "printpic.py", line 267, in <module>
main(inputfile="testli.jpg")
File "printpic.py", line 259, in main
layout_photo_5_2(resize_photo(cut_photo(im,2),2)).save('5_2.jpg')
File "printpic.py", line 52, in cut_photo
cutted_photo = im.crop((x, y, x + (int(height / HEIGHT_2IN * WIDTH_2IN)), y + height))
NameError: name 'im' is not defined
刚开始以为是图片大小不合适导致的,后来发现是原代码有小bug,im确实没有在函数中定义,它使用了全局变量,在我将后处理程序放入main函数后,该变量就不是全局变量了,导致该bug暴露出来。
将第52行的im改成photo即可。 cutted_photo = photo.crop((x, y, x + (int(height / HEIGHT_2IN * WIDTH_2IN)), y + height))
期间在测试PP-Matting一运行就报错
用系统自带的代码测试一下,ok,参见手册:https://github.com/PaddlePaddle/FastDeploy/tree/develop/examples/vision/matting/ppmatting/python
于是查找前面的问题,发现是因为调用了错误的模型导致的的,应该是"/home/aistudio/work/PP-Matting-1024/",错误的用了work/pp-matting-hrnet_w18-human_1024
应用体验部署的时候报目录超过2G限制
只有一个100M大小的模型文件,其实没有超限,原来是应用体验部署只支持飞桨2.3.2版本,我的是2.4.0版本,所以会报错。
后来使用在python代码中下载模型的方式,绕过了这个问题。
No module named ‘keypoint’
Traceback (most recent call last):
File "infer.py", line 8, in <module>
from keypoint import FaceLandMark
ModuleNotFoundError: No module named 'keypoint'
经检查,发现是FastDeploy没有成功git clone下来,而根目录下正好有个infer.py文件,导致这种神奇的报错。
结束语
让我们荡起双桨,在AI的海洋乘风破浪!
飞桨官网:https://www.paddlepaddle.org.cn
因为水平有限,难免有不足之处,还请大家多多帮助。
作者:段春华, 网名skywalk 或 天马行空,济宁市极快软件科技有限公司的AI架构师,百度飞桨PPDE。
我在AI Studio上获得至尊等级,点亮10个徽章,来互关呀~ https://aistudio.baidu.com/aistudio/personalcenter/thirdview/141218
此文章为搬运
原项目链接
更多推荐
所有评论(0)