《PaddlePaddle从⼊门到炼丹》⼗四——把预测模型部署在服务器
前⾔
如果读者使⽤过百度等的⼀些图像识别的接⼝,⽐如百度的细粒度图像识别接⼝,应该了解这个过程,省略其他的安全⽅⾯的考虑。这个接⼝⼤体的流程是,我们把图像上传到百度的⽹站上,然后服务器把这些图像转换成功⽮量数据,最后就是拿这些数据传给深度学习的预测接⼝,⽐如是PaddlePaddle的预测接⼝,获取到预测结果,返回给客户端。这个只是简单的流程,真实的复杂性远远不⽌这些,但是我们只需要了解这些,然后去搭建属于我们的图像识别接⼝。
了解Flask
安装flask很简单,只要⼀条命令就可以了:
pip install flask
同时我们也使⽤到flask_cors,所以我们也要安装这个库
pip install flask_cors
创建⼀个paddle_server.py⽂件,然后编写⼀个简单的程序,了解⼀些如何使⽤这个Flask框架,⾸先导⼊所需的依赖库:
import os
import uuid
import numpy as np
import paddle.fluid as fluid
from PIL import Image
from flask import Flask, request
from flask_cors import CORS
from werkzeug.utils import secure_filename
编写⼀个hello_world()函数,使⽤@ute('/')是指定访问的路径,该函数的返回值是⼀个字符串Welcome to PaddlePaddle:
# 根路径,返回⼀个字符串
@ute('/')
def hello_world():
return'Welcome to PaddlePaddle'
然后启动这个服务,如果是在Ubuntu的话,可能是需要在root下执⾏这个程序。
if __name__ =='__main__':
# 启动服务,并指定端⼝号
app.run(port=80)
Welcome to PaddlePaddle
要预测图⽚,上传图⽚是⾸要的,所以我们来学习如何使⽤Flask来上传图⽚。
secure_filename是为了能够正常获取到上传⽂件的⽂件名
/
upload指定该函数的访问地址
methods=['POST']指定该路径只能使⽤POST⽅法访问
ubuntu使用入门教程f = request.files['img']读取表单名称为img的⽂件
f.save(img_path)在指定路径保存该⽂件
@ute('/upload', methods=['POST'])
def upload_file():
f = request.files['img']
# 设置保存路径
save_father_path ='images'
img_path = os.path.join(save_father_path,str(uuid.uuid1())+ secure_filename(f.filename).split('.')[-1])
if not ists(save_father_path):
os.makedirs(save_father_path)
f.save(img_path)
return'success, save path: '+ img_path
然后再次启动服务
if __name__ =='__main__':
# 启动服务,并指定端⼝号
app.run(port=80)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>预测图像</title>
</head>
<body>
<!--上传图⽚的表单-->
<form action="127.0.0.1/upload"enctype="multipart/form-data"method="post">
选择上传的图像:<input type="file"name="img"><br>
<input type="submit"value="上传">
</form>
</body>
</html>
打开我们编写的⽹页,选择需要上传的图⽚,点击上传。成功后返回类似以下的字符串,图⽚会保存在images⽬录下。
success, save path: images/65d7661a-3892-11e9-a7b7-f44d30185f58jpg
预测服务
在paddle_server.py中添加⼀个图⽚⽂件预处理函数,这个函数的参数是根据已经上传并保存到服务器上图⽚的路径,根据处理对图⽚进⾏预处理,并返回处理否的图⽚数据:
# 预处理图⽚
def load_image(file):
img = Image.open(file)
# 统⼀图像⼤⼩
img = size((224,224), Image.ANTIALIAS)
# 转换成numpy值
img = np.array(img).astype(np.float32)
# 转换成CHW
img = anspose((2,0,1))
# 转换成BGR
img = img[(2,1,0),:,:]/255.0
img = np.expand_dims(img, axis=0)
return img
以下就是PaddlePaddle代码,这次我们使⽤训练保存的预测代码。
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())
# 保存预测模型路径
save_path ='infer_model/'
# 从模型中获取预测程序、输⼊数据名称列表、分类器
[infer_program, feeded_var_names, target_var]= fluid.io.load_inference_model(dirname=save_path, executor=exe)
以下就是这个后端服务项⽬的核⼼代码,该函数主要的功能是接受上传的图⽚,对图⽚进⾏预测,最后返回预测的结果。预测的⽅式和之前的图⽚预测的⽅式⼀样的。
@ute('/infer', methods=['POST'])
def infer():
f = request.files['img']
# 保存图⽚
save_father_path ='images'
img_path = os.path.join(save_father_path,str(uuid.uuid1())+'.'+ secure_filename(f.filename).split('.')[-1])
if not ists(save_father_path):
os.makedirs(save_father_path)
f.save(img_path)
# 开始预测图⽚
img = load_image(img_path)
result = exe.run(program=infer_program,
feed={feeded_var_names[0]: img},
fetch_list=target_var)
# 显⽰图⽚并输出结果最⼤的label
lab = np.argsort(result)[0][0][-1]
names =['苹果','哈密⽠','胡萝⼘','樱桃','黄⽠','西⽠']
# 打印和返回预测结果
r ='{"label":%d, "name":"%s", "possibility":%f}'%(lab, names[lab], result[0][0][lab])
print(r)
return r
启动服务
if __name__ =='__main__':
# 启动服务,并指定端⼝号
app.run(port=80)
在index.html⽂件增加⼀个表单,这个是访问的地址就是上⾯服务中的预测函数的访问路径:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>预测图像</title>
</head>
<body>
<!--调⽤服务器预测接⼝的表单-->
<form action="127.0.0.1/infer"enctype="multipart/form-data"method="post">
选择预测的图像:<input type="file"name="img"><br>
<input type="submit"value="预测">
</form>
</body>
</html>
打开我们刚才编写的⽹页,选择需要预测的图⽚,点击预测。成功后返回类似以下的字符串,识别类别的标签,名字,还有该类别的概率。
{"label":1, "name":"哈密⽠", "possibility":0.982786}
上⼀章:
下⼀章:
参考资料
1. blog.csdn/qq_33200967/article/details/79571511
2. blog.csdn/u011054333/article/details/70151857
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论