Faster R-CNN模型工程部署(pytorch)
前言
因为本人最近在做一个与目标检测有关的项目,最开始只是跑一跑模型,但是后来乙方提出要求需要有我们提出部署方案并实施,最开始在网上查了许多资料,发现现在有许多都是tensorflow的一些部署,而关于pytorch部署这方面实际的资料着实很少,鉴于自己最后调了出来,因而想着写一个博客和大家分享一下,相互学习学习。
1.FLask
Flask是一个 web 框架。也就是说 Flask 为你提供工具,库和技术来允许你构建一个 web 应用程序。这个 wdb 应用程序可以使一些 web 页面、博客、wiki、基于 web 的日历应用或商业网站。Flask 属于微框架(micro-framework)这一类别,微架构通常是很小的不依赖于外部库的框架。这既有优点也有缺点,优点是框架很轻量,更新时依赖少,并且专注安全方面的 bug,缺点是,你不得不自己做更多的工作,或通过添加插件增加自己的依赖列表。
Flask 的依赖如下:
维基百科 WSGI 的介绍:
Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口)。自从WSGI被开发出来以后,许多其它语言中也出现了类似接口。
flask中文资料参考网站:http://www.pythondoc.com/flask/index.html
2.实现
我们自己在做模型测试的过程中,不难发现每次加载模型都需要很多的时间,如果我们进行网络部署的话,每次得到一次申请,每次都加载模型的话就会显得很不必要,因而在服务器上我们需要这样一种机制:将模型在服务器上load好,方便我们不断去调用模型做图像预测,而不需要多次load模型,那么怎么能够达到这个目的呢?在此处,我们可以使用flask来建立一个REST API来达到这一目的。REST 是Representational State Transfer的缩写,这是一种架构风格,这里就不再过多描述,感兴趣的同学可以自己去google一下。
代码:https://github.com/xinyu-ch/Faster_RCNN_Deloy
2.1 服务器
下面看一下利用flask启动REST API服务:
载入模型
app = flask.Flask(__name__)
model = None
use_gpu = True
def load_model():
"""Load the pre-trained model, you can use your model just as easily.
"""
global model
model = resnet50(pretrained=True) # 模型加载程序,可以根据自己需要进行更改
model.eval()
if use_gpu:
model.cuda() # 使用GPU加速
在load_model()函数中,我们需要完成对模型的加载,此处用得到的思想主要是全局变量的形式,我们把在其他函数中需要的一些参数进行全局化,在python利用global方式进行操作,此处假设我们在其他函数只需要模型的参数,就只需 global model,便可。
启动REST API
在定义载入模型之后,便可以开启flask服务了。
@app.route("/predict", methods=["POST"])
def predict():
# 初始化一个字典,状态为False,以在客户端进行判断数据是否完整
data = {"success": False}
# 判断是否受到POST
if flask.request.method == 'POST':
# 判断是否收到image
if flask.request.files.get("image"):
# 读取图像PIL,网络传输中一般选择二进制传输
image = flask.request.files["image"].read()
image = Image.open(io.BytesIO(image))
# 此处是我的目标检测的具体函数,你可以替换成自己的函数
box_re = raber_detection(np.array(image))
data['predictions'] = list()
l = {"BoxNumber": box_re.shape[0]}
data['predictions'].append(str(l))
# Loop over the results and add them to the list of returned predictions
for box in box_re:
r = {"BoxList": [str(i) for i in np.rint(box[:4]).astype(int)]}
data['predictions'].append(r)
# Indicate that the request was a success.
data["success"] = True
# Return the data dictionary as a JSON response.
return flask.jsonify(data)
首先定义请求方式为 POST,表示向服务器传输数据,接着定义一个 predict 函数来进行结果的传输。在利用自己的函数得到结果之后,便通过flask.jsonify(data)返回json格式数据给客户端。
最后在主函数中调用:
load_model()
app.run()
这样便可以启动 flask 服务了。通过上面的代码,我们知道了如何处理传过来的图片并输出预测的结果,那么我们如何传图片呢?这就是下面会讲的如何发起数据请求。
修改server地址,接口:
app.run(
host='172.**.**.**', # your IP
port=5000,
debug=False
)
2.2 客户端
在发送数据前,需要知道上面定义好的 flask server 的地址,默认为本地接口,所以地址是
PyTorch_REST_API_URL = 'http://127.0.0.1:5000/predict'
上面的 /predict 和前文的 @app.route("/predict", methods=[“POST”])定义相同。
接下来便可以定义发送函数了:
def predict_result(image_path):
# Initialize image path
image = open(image_path, 'rb').read()
payload = {'image': image}
# Submit the request.
r = requests.post(PyTorch_REST_API_URL, files=payload).json()
# Ensure the request was successful.
if r['success']:
det_box = []
for (i, result) in enumerate(r['predictions']):
box = []
if i > 0:
[box.append(int(j)) for j in result["BoxList"]]
det_box.append(box)
del[det_box[0]]
im2show = vis_detections(cv2.imread(image_path), np.array(det_box))
result_path = os.path.join(image_path[:-4] + "_det.jpg")
cv2.imwrite(result_path, im2show)
# cv2.imwrite('./result.jpg', im2show)
# cv2.imshow('imshow', im2show)
cv2.destroyAllWindows()
else:
print('Request failed')
此处,是接收服务器传回的Box结果,并将Box绘制到原图,进行保存,image_path是图像的路径 。
3.测试
我使用了自己训练的fasterR-CNN模型,传入下图作为测试:
首先在一个终端中运行服务器端程序:
python run_pytorch_server.py
可以看到效果如下:
待服务器程序运行成功后,再在客户端运行:
python simple_request.py --file=./0C006B5C.jpg
可以得到如下的效果图:
注意:因为我是在学校测试的,用的是学校的内网,若要在外网进行访问的话,需要进行外网穿透或搭建v*n
参考
1.https://blog.****.net/dou3516/article/details/82912458
2.https://www.cnblogs.com/mrchige/p/6387674.html