参考,这几份资源非常有用,有时间一定要仔细看一下
手工优化ncnn模型结构
详细记录u版YOLOv5目标检测ncnn实现
参考工程
- onnx to ncnn
模型 yolov5-5.0
转换脚本是 yolov5-6.0
第一步
D:\model\yolov5-6.1>python export.py --weights D:\model\best-s-shudian.pt --include onnx --train
export: data=data\coco128.yaml, weights=['D:\\model\\best-s-shudian.pt'], imgsz=[640, 640], batch_size=1, device=cpu, half=False, inplace=False, train=True, optimize=False, int8=False, dynamic=False, simplify=False, opset=12, verbose=False, workspace=4, nms=False, agnostic_nms=False, topk_per_class=100, topk_all=100, iou_thres=0.45, conf_thres=0.25, include=['onnx']
YOLOv5 2022-2-22 torch 1.8.0+cpu CPU
Fusing layers...
Model Summary: 224 layers, 7083577 parameters, 0 gradients
PyTorch: starting from D:\model\best-s-shudian.pt with output shape (1, 3, 80, 80, 17) (14.4 MB)
ONNX: starting export with onnx 1.15.0...
ONNX: export success, saved as D:\model\best-s-shudian.onnx (28.4 MB)
Export complete (3.72s)
Results saved to D:\model
Detect: python detect.py --weights D:\model\best-s-shudian.onnx
PyTorch Hub: model = torch.hub.load('ultralytics/yolov5', 'custom', 'D:\model\best-s-shudian.onnx')
Validate: python val.py --weights D:\model\best-s-shudian.onnx
Visualize: https://netron.app
第二步
D:\model>python -m onnxsim best-s-shudian.onnx best-s-shudian-sim.onnx
Simplifying...
Finish! Here is the difference:
┌────────────┬────────────────┬──────────────────┐
│ │ Original Model │ Simplified Model │
├────────────┼────────────────┼──────────────────┤
│ Add │ 7 │ 7 │
│ Concat │ 19 │ 14 │
│ Constant │ 177 │ 136 │
│ Conv │ 62 │ 62 │
│ Gather │ 9 │ 0 │
│ MaxPool │ 3 │ 3 │
│ Mul │ 59 │ 59 │
│ Reshape │ 3 │ 3 │
│ Resize │ 2 │ 2 │
│ Shape │ 9 │ 0 │
│ Sigmoid │ 59 │ 59 │
│ Slice │ 8 │ 4 │
│ Transpose │ 3 │ 3 │
│ Unsqueeze │ 15 │ 0 │
│ Model Size │ 27.0MiB │ 27.0MiB │
└────────────┴────────────────┴──────────────────┘
第三步
C:\Users\ncnn-20230816-windows-vs2022\x64\bin>onnx2ncnn.exe best-s-shudian-sim.onnx yolov5.param yolov5.bin
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
Unsupported slice step !
输出很多 Unsupported slice step,这是focus模块转换的报错。
用自定义op YoloV5Focus代替掉focus
将reshape的6400 1600 400 都更改为-1即可
C:\Users\ncnn-20230816-windows-vs2022\x64\bin>ncnnoptimize.exe yolov5.param yolov5.bin yolov5-opt.param yolov5-opt.bin 0
create_custom_layer YoloV5Focus
model has custom layer, shape_inference skipped
model has custom layer, estimate_memory_footprint skipped
- 代码
把nuihui大神的CPP代码拷贝过来即可,修改以下3个地方
再一个就是确认anchor ,正如注释【// anchor setting from yolov5/models/yolov5s.yaml】所说,确认CPP中的anchor和训练模式时一样,我的模式 yolov5-5.0,和代码中的一样,不用改。
- 运行问题记录
输入图片,发现有的检测正常,有的检测异常,整张图上布满密密麻麻的检测框,原因不明,观察输入图片特性,发现结果正常的图片长/宽=1.3333333,例如1440 * 1080,或者2048 * 1536,结果异常的图片长/宽=1.7777777,例如1920 * 1080,具体原因可以参考这篇文章图像Resize对深度模型效果的影响。大概就是说,原始图片尺寸不一,需要resize为模型输入大小,例如yolov5是640*640。resize的时候可以直接拉伸为模型输入尺寸,也可以保持宽高比例(保持宽高比例的做法一般是用增加padding的方式),一般来说,和模型训练时图片的处理方式一致即可。我的模型训练时是直接resize的,但是nuihui的代码是padding的,所以有些图片结果异常严重,去掉代码中的padding操作,改为直接拉伸,测试OK。