YOLOv5从入门到部署之:模型部署

1,781次阅读
没有评论

共计 3776 个字符,预计需要花费 10 分钟才能阅读完成。

本文记录了 YOLOv5 的部署过程,包含以下代码,下载方式在文末。

(1)onnxruntime 部署代码;

(2)flask 部署代码;

(3)ncnn 部署代码;

1 ONNX
在模型部署之前,先介绍如何把训练好的 YOLOv5 模型从 PyTorch 导出到 ONNX。为后续端上部署做准备。

Setp1:安装环境,前面我们已经安装好了 yolov5 需要的环境 pip install -r requirements.txt现在我们还需要再安装 onnx 和 coremltools。

pip install onnx>=1.7.0 
# for ONNX export
pip installcoremltools==4.0  
# for CoreMLexport

Setp2:将预先训练的 YOLOv5s 模型导出为 ONNX、TorchScript 和 CoreML 格式

export PYTHONPATH="$PWD" && python models/export.py --weights ./weights/yolov5s.pt --img 640 --batch 1

转换过程会有如下日志输出:

YOLOv5 从入门到部署之:模型部署

导出的 3 种模型与原始 PyTorch 模型一起保存

YOLOv5 从入门到部署之:模型部署

需要注意的是,export.py 导出可以导出两种 YOLOv5 的 ONNX 模型,一种是无解码的模型,一种是有解码的模型,可以通过 Detect 层进行配置,如下:

model.model[-1].export = True  
# set Detect() 
layer export=True

Setp3:检测

ONNX 模型的推理有多种框架可以选择,这里我们参考了一些资料,使用 onnxruntime 进行推理。

首先,先加载模型:

session = onnxruntime.InferenceSession('runs/train/exp1/weights/best.onnx')
print("The model expects input shape:", session.get_inputs()[0].shape)
batch_size = session.get_inputs()[0].shape[0]
img_size_h = session.get_inputs()[0].shape[2]
img_size_w = session.get_inputs()[0].shape[3]

然后,对图像做好预处理后,进行模型的推理:

image_src = Image.open(image_path)
resized = letterbox_image(image_src, (img_size_w, img_size_h))
img_in = np.transpose(resized, (2, 0, 1)).astype(np.float32)  
# HWC -> CHW
img_in = np.expand_dims(img_in, axis=0)
img_in /= 255.0
# inferenceinput_name = session.get_inputs()[0].name
outputs = session.run(None, {input_name: img_in})

最后,对包含解码的 ONNX 模型,只需要进行 MNS 操作即可,对没有后处理的 ONNX 模型,还需要先进行解码再进行 MNS。

2 Flask 部署

首先确保安装了 pytorch,因为需要使用 flask 这个 web 框架,所以当然需要安装 flask,非常简单,使用下面的命令进行安装。

pip install flask

每次启动模型,加载模型是一件非常费时间的事情,所以最好的办法就是 load 一次模型。我们直接使用 YOLOv5 里面的 attempt_load 函数进行加载。

model = attempt_load(weights, map_location=device) # load FP32 model

接着,就是 YOLOv5 中标准的预处理流程,首先将图片 resize 到固定的大小,然后转换成 tensor,接着做标准化。

if webcam:    
view_img = True   
cudnn.benchmark = True  # set True to speed up constant image size inference    
dataset = LoadStreams(source, img_size=imgsz)else:    
save_img = True    
dataset = LoadImages(source, img_size=imgsz)

然后,定义请求方式为 POST,表示向服务器传输数据,接着定义一个 predict 函数来进行模型的前向传播。

def detect(): 
   save_img = False    
form_data = request.json    
print(form_data)    ...

最后我们在 main 函数中调用

if __name__ == '__main__':    
app.run()

测试时,需要先启动 flask 服务:

python flask_detect.py <path-to-your-model>
python flask_detect.py <path-to-your-model> <GPU-device-number(s)>

然后,使用 curl 命令或者提供的 python 脚本去访问服务器:

python client_flask.py
curl -X POST -H "Content-Type: application/json" -d @api_data.json http://localhost:5000/detect

测试结果如下

YOLOv5 从入门到部署之:模型部署

3 NCNN 部署

以无解码部分的模型为例,先要编译好 ncnn,建议在 Linux 环境下编译。
Setp1:先用 onnxsim 进行模型简化:

python3 -m onnxsim best.onnx best-sim.onnx

Step2 简化后的 onnx 模型转化为 ncnn 的模型

onnx2ncnn best-sim.onnx best.param best.bin

Setp3推理

加载放在 example/yolov5 目录下的模型:

yolov5.load_param("../examples/yolov5/yolov5b.param");yolov5.load_model("../examples/yolov5/yolov5b.bin");

然后进行 YOLOv5 中标准的 预处理流

const int target_size = 640;
float r_w = input_size / (img_w*1.0);
float r_h = input_size/ (img_h*1.0);
int true_w, true_h, x, y;if (r_h > r_w) {true_w = input_size;true_h = r_w * img_h;x = 0;y = (input_size - true_h) / 2;} 
else {true_w = r_h* img_w;true_h = input_size;x = (input_size - true_w) / 2;y = 0;}
//ncnn::Mat in = ncnn::Mat::
from_pixels_resize(bgr.data, ncnn::Mat::PIXEL_BGR2RGB, bgr.cols, bgr.rows, target_size, target_size);
ncnn::Mat in = ncnn::Mat::
from_pixels(bgr.data, ncnn::Mat::PIXEL_BGR2RGB, bgr.cols, bgr.rows);
const float mean_vals[3] = {0, 0, 0};
const float norm_vals[3] = {1 / 255.f, 1 / 255.f, 1 / 255.f};
in.substract_mean_normalize(mean_vals, norm_vals);

最后进行解码和 NMS 操作:

ncnn::Extractor ex = yolov5.create_extractor();ex.set_num_threads(4);
ex.input(0, in);std::
vector<BoxInfo> result;for(auto& 
layer: layers){ncnn::Mat blob;    ex.extract(layer.name.c_str(),blob);
auto boxes = decode_infer(blob,layer.stride,{img_w, img_h},true_w, 
true_h,num_class,layer.anchors,threshold, x, y);    
result.insert(result.begin(),boxes.begin(),boxes.end());}
nms(result,nms_threshold);

测试结果如下:

YOLOv5 从入门到部署之:模型部署

总结

Yolov5 从它出现以来就饱受争议,大家认为它的创新不足更应该叫做 yolov4 的 pytorch 版本。但是不可否认的是 yolov5 是一个优秀的目标检测框架,yolov5 大量整合了计算机视觉领域的 State-of-the-art,它相对于 yolov4 更方便我们的使用,我们可以在 yaml 文件简单的修改网络结构,代码的可读性更高,能够更方便修改代码。

正文完
 0
一诺
版权声明:本站原创文章,由 一诺 于2021-02-17发表,共计3776字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
验证码