|
本帖最后由 z13228604287 于 2022-8-9 09:27 编辑
对于https://github.com/ultralytics/yolov5 在更新的v6.1版本的
使用易语言部署yolov5-v6.1目标检测,支持yolov5s,yolov5m,yolov5l,yolov5n,yolov5x, yolov5s6,yolov5m6,yolov5l6,yolov5n6,yolov5x6的十种结构的yolov5-v6.1
测试模型地址是:
链接:https://pan.baidu.com/s/1VSYkILerRQsoDiIhl-6eTQ?pwd=4ypk
在这里特别讲解一下转换生成onnx文件的方法,首先下载yolov5-v6.1的源码和模型.pt文件之后,在程序主目录里,打开models/yolo.py,进入到Detect类的forward函数里,插入代码,示例截图如下:
插入的代码片段是:
[Python] 纯文本查看 复制代码 if torch.onnx.is_in_onnx_export():
for i in range(self.nl): # 分别对三个输出层处理
x = self.m(x) # conv
bs, _, ny, nx = x.shape # x(bs,255,20,20) to x(bs,3,20,20,85)
x = x.view(bs, self.na, self.no, ny, nx).permute(0, 1, 3, 4, 2).contiguous()
y = x.sigmoid()
z.append(y.view(bs, -1, self.no))
return torch.cat(z, 1)
不过需要注意的是,y = x.sigmoid()这一步并不是必须的,例如在yolov5车牌检测项目里,4个关键点的x, y值没有做sigmoid()
接下来,尝试运行python export.py --weights=yolov5s.pt --include=onnx,但是生成onnx文件失败了。这时在export.py里,我自定义了一个导出onnx文件的函数,代码片段如下:
[Python] 纯文本查看 复制代码 def my_export_onnx(model, im, file, opset, train, dynamic, simplify, prefix=colorstr('ONNX:')):
print('anchors:', model.yaml['anchors'])
wtxt = open('class.names', 'w')
for name in model.names:
wtxt.write(name+'\n')
wtxt.close()
# YOLOv5 ONNX export
print(im.shape)
if not dynamic:
f = os.path.splitext(file)[0] + '.onnx'
torch.onnx.export(model, im, f, verbose=False, opset_version=12, input_names=['images'], output_names=['output'])
else:
f = os.path.splitext(file)[0] + '_dynamic.onnx'
torch.onnx.export(model, im, f, verbose=False, opset_version=12, input_names=['images'],
output_names=['output'], dynamic_axes={'images': {0: 'batch', 2: 'height', 3: 'width'}, # shape(1,3,640,640)
'output': {0: 'batch', 1: 'anchors'} # shape(1,25200,85)
})
try:
import cv2
net = cv2.dnn.readNet(f)
except:
exit(f'export {f} failed')
exit(f'export {f} sucess')
接下来在官方定义的export_onnx函数里插入调用这个函数,代码截图如下:
这时运行
[Python] 纯文本查看 复制代码 python export.py --weights=yolov5s.pt --include=onnx --imgsz=640
python export.py --weights=yolov5s6.pt --include=onnx --imgsz=1280
就能成功生成.onnx文件,并且使用opencv模块能读取onnx文件做推理。
易语言调用源码如下:
1.类
窗口程序集名 | 保 留 | 保 留 | 备 注 | YOLO5, , 公开, 6.1 | | | | 变量名 | 类 型 | 数组 | 备 注 | 锚_640 | 小数型 | 3,6 | 锚_1280 | 小数型 | 4,6 | 锚指针 | 小数型指针类 | | 数_步 | 整数型 | | 输入宽 | 整数型 | | 输入高 | 整数型 | | 类_名数组 | 字节集 | 0 | 类数 | 整数型 | | 置信阈值 | 小数型 | | 抑制阈值 | 小数型 | | 对象阈值 | 小数型 | | 保持比率 | 逻辑型 | | DNN网络 | 网络类 | |
类_名数组 = 分割字节集 ( #类名, { 10 }, )类数 = 取数组成员数 (类_名数组 )锚_640 [1 ] [1 ] = 10 锚_640 [1 ] [2 ] = 13 锚_640 [1 ] [3 ] = 16 锚_640 [1 ] [4 ] = 30 锚_640 [1 ] [5 ] = 33 锚_640 [1 ] [6 ] = 23 锚_640 [2 ] [1 ] = 30 锚_640 [2 ] [2 ] = 61 锚_640 [2 ] [3 ] = 62 锚_640 [2 ] [4 ] = 45 锚_640 [2 ] [5 ] = 59 锚_640 [2 ] [6 ] = 119 锚_640 [3 ] [1 ] = 116 锚_640 [3 ] [2 ] = 90 锚_640 [3 ] [3 ] = 156 锚_640 [3 ] [4 ] = 198 锚_640 [3 ] [5 ] = 373 锚_640 [3 ] [6 ] = 326 锚_1280 [1 ] [1 ] = 19 锚_1280 [1 ] [2 ] = 27 锚_1280 [1 ] [3 ] = 44 锚_1280 [1 ] [4 ] = 40 锚_1280 [1 ] [5 ] = 38 锚_1280 [1 ] [6 ] = 94 锚_1280 [2 ] [1 ] = 96 锚_1280 [2 ] [2 ] = 68 锚_1280 [2 ] [3 ] = 86 锚_1280 [2 ] [4 ] = 152 锚_1280 [2 ] [5 ] = 180 锚_1280 [2 ] [6 ] = 137 锚_1280 [3 ] [1 ] = 140 锚_1280 [3 ] [2 ] = 301 锚_1280 [3 ] [3 ] = 303 锚_1280 [3 ] [4 ] = 264 锚_1280 [3 ] [5 ] = 238 锚_1280 [3 ] [6 ] = 542 锚_1280 [4 ] [1 ] = 436 锚_1280 [4 ] [2 ] = 615 锚_1280 [4 ] [3 ] = 739 锚_1280 [4 ] [4 ] = 380 锚_1280 [4 ] [5 ] = 925 锚_1280 [4 ] [6 ] = 792 保持比率 = 真 判断 (寻找文本 (s, sub, , 假) = 取文本长度 (s ) - 取文本长度 (sub ) + 1 )返回 (真)返回 (假)|
初始化YOLO | | | |
参_置信阈值 | 小数型 | | | | 参_抑制阈值 | 小数型 | | | | 参_对象阈值 | 小数型 | | | | 模型路径 | 文本型 | | | |
置信阈值 = 参_置信阈值 抑制阈值 = 参_抑制阈值 对象阈值 = 参_对象阈值 DNN网络 = 视觉_读取网络 (模型路径, , “”)判断 (结束对比 (模型路径, “6.onnx”)) 锚指针.指针 = 取变量数据地址 (锚_1280 )数_步 = 4 输入高 = 1280 输入宽 = 1280 锚指针.指针 = 取变量数据地址 (锚_640 )数_步 = 3 输入高 = 640 输入宽 = 640 |
图片尺寸调整 | 多维矩阵类 | | |
输入图片 | 多维矩阵类 | | | | 新高 | 整数型 | | | | 新宽 | 整数型 | | | | 顶 | 整数型 | | | | 左 | 整数型 | | | |
变量名 | 类 型 | 静态 | 数组 | 备 注 | 输入高 | 整数型 | | | 输入宽 | 整数型 | | | 结果图 | 多维矩阵类 | | | 高宽_比率 | 小数型 | | |
输入高 = 输入图片. 行数 ()输入宽 = 输入图片. 列数 ()新高 = 输入高 新宽 = 输入宽 判断 (保持比率 且 输入高 ≠ 输入宽 )高宽_比率 = 输入高 ÷ 输入宽 如果 (高宽_比率 > 1 )新高 = 输入高 新宽 = 输入宽 ÷ 高宽_比率 视觉_调整尺寸 (输入图片, 结果图, 尺寸2i (新宽, 新高 ), #插值_面积, 0, 1 )左 = (输入宽 - 新宽 ) × 0.5 视觉_复制边框 (结果图, 结果图, 0, 0, 左, 输入宽 - 新宽 - 左, #边框_不变, 标量 (114 )) 新高 = 输入高 × 高宽_比率 新宽 = 输入宽 视觉_调整尺寸 (输入图片, 结果图, 尺寸2i (新宽, 新高 ), #插值_面积, 0, 1 )顶 = (输入高 - 新高 ) × 0.5 视觉_复制边框 (结果图, 结果图, 顶, 输入高 - 新高 - 顶, 0, 0, #边框_不变, 标量 (114 )) 视觉_调整尺寸 (输入图片, 结果图, 尺寸2i (新宽, 新高 ), #插值_面积, 0, 1 )返回 (结果图 )变量名 | 类 型 | 静态 | 数组 | 备 注 | 新高 | 整数型 | | | 新宽 | 整数型 | | | 新顶 | 整数型 | | | 新左 | 整数型 | | | 结果图 | 多维矩阵类 | | | 连通对象 | 多维矩阵类 | | | 输出数组 | 多维矩阵类 | | 0 | 数_proposal | 整数型 | | | 维度 | 整数型 | | | 置信数组 | 小数型 | | 0 | 框数组 | 矩形2i类 | | 0 | 类ID数组 | 整数型 | | 0 | 高比率 | 小数型 | | | 宽比率 | 小数型 | | | 数据指针 | 小数型指针类 | | | n | 整数型 | | | q | 整数型 | | | i | 整数型 | | | j | 整数型 | | | 行_计数 | 整数型 | | | 尺度 | 小数型 | | | 数_网络_宽 | 小数型 | | | 数_网络_高 | 小数型 | | | 锚_宽 | 小数型 | | | 锚_高 | 小数型 | | | 框_分数 | 小数型 | | | 分数 | 多维矩阵类 | | | 类ID位置 | 点2i类 | | | 最大_类_得分 | 双精度小数型 | | | 类_IDx | 整数型 | | | 中心X | 小数型 | | | 中心Y | 小数型 | | | 宽 | 小数型 | | | 高 | 小数型 | | | 左 | 整数型 | | | 顶 | 整数型 | | | 指数 | 整数型 | | 0 | IDx | 整数型 | | | 框 | 矩形2i类 | | |
结果图 = 图片尺寸调整 (输入图片, 新高, 新宽, 新顶, 新左 )连通对象 = 视觉_图像前景目标 (结果图, 1 ÷ 255, 尺寸2i (输入宽, 输入高 ), 标量 (0, 0, 0 ), 真, 假, 5 )DNN网络. 设置输入 (连通对象, “”, 1, )DNN网络. 前向计算V (输出数组, DNN网络. 获取未连接的输出层名称 ()) 数_proposal = 输出数组 [1 ]. 维度元素数 (1 )维度 = 输出数组 [1 ]. 维度元素数 (2 )如果真 (输出数组 [1 ]. 维度 () > 2 )输出数组 [1 ] = 输出数组 [1 ]. 重塑 (0, 数_proposal )高比率 = 输入图片.行数 () ÷ 新高宽比率 = 输入图片. 列数 () ÷ 新宽 数据指针.指针 = 输出数组 [1 ]. 数据指针 ()变量循环首 (0, 数_步 - 1, 1, n )尺度 = 求次方 (2, n + 3 )数_网络_宽 = 视觉_向上取整 (输入宽 ÷ 尺度 )数_网络_高 = 视觉_向上取整 (输入高 ÷ 尺度 )变量循环首 (0, 2, 1, q )锚_宽 = 锚指针. 读 (n × 6 + q × 2 )锚_高 = 锚指针. 读 (n × 6 + q × 2 + 1 )变量循环首 (0, 数_网络_高 - 1, 1, i )变量循环首 (0, 数_网络_宽 - 1, 1, j )框_分数 = 数据指针. 读 (4 )如果真 (框_分数 > 对象阈值 )分数 = 输出数组 [1 ]. 行 (行_计数 ). 列范围 (5, 维度 )视觉_最小最大位置 (分数, , 最大_类_得分, , 类ID位置, )最大_类_得分 = 最大_类_得分 × 框_分数 如果真 (最大_类_得分 > 置信阈值 )类_IDx = 类ID位置.左边 中心X = (数据指针. 读 (0 ) × 2 - 0.5 + j ) × 尺度 中心Y = (数据指针. 读 (1 ) × 2 - 0.5 + i ) × 尺度 宽 = 求次方 (数据指针. 读 (2 ) × 2, 2 ) × 锚_宽 高 = 求次方 (数据指针. 读 (3 ) × 2, 2 ) × 锚_高 左 = (中心X - 新左 - 0.5 × 宽 ) × 宽比率 顶 = (中心Y - 新顶 - 0.5 × 高 ) × 高比率 加入成员 (置信数组, 最大_类_得分 )加入成员 (框数组, 矩形2i (左, 顶, 宽 × 宽比率, 高 × 高比率 )) 加入成员 (类ID数组, 类_IDx )行_计数 = 行_计数 + 1数据指针. 偏移 (维度 )变量循环尾 ()变量循环尾 ()变量循环尾 ()变量循环尾 ()视觉_非最大抑制 (框数组, 置信数组, 置信阈值, 抑制阈值, 指数, 1, 0 )计次循环首 (取数组成员数 (指数 ), i )IDx = 指数 [i ] + 1 框 = 框数组 [IDx ]绘制预测 (置信数组 [IDx ], 框.左边, 框.顶边, 框.左边 + 框.宽度, 框.顶边 + 框.高度, 输入图片, 类ID数组 [IDx ])计次循环尾 ()|
绘制预测 | | | |
分数 | 小数型 | | | | 左边 | 整数型 | | | | 顶边 | 整数型 | | | | 右边 | 整数型 | | | | 底边 | 整数型 | | | | 画板 | 多维矩阵类 | | | | 类ID | 整数型 | | | |
变量名 | 类 型 | 静态 | 数组 | 备 注 | 标签 | 文本型 | | | 标签尺寸 | 尺寸2i类 | | | 视觉_矩形1 (画板, 点2i (左边, 顶边 ), 点2i (右边, 底边 ), 标量 (0, 0, 255 ), 2, 0, 0 ) 标签 = 到文本 (类_名数组 [类ID + 1 ]) + “:” + 到文本 (分数 ) 标签尺寸 = 视觉_获取文本尺寸 (标签, #字体_衬线_简单, 0.5, 1, )顶边 = 视觉_取最大值 (顶边, 标签尺寸.高 )视觉_放置文本 (画板, 标签, 点2i (左边, 顶边 ), #字体_衬线_简单, 0.75, 标量 (0, 255, 0 ), 1, 8, 假)
2.调用
变量名 | 类 型 | 静态 | 数组 | 备 注 | YOLO | YOLO5 | | | 输入图片 | 多维矩阵类 | | | 标题 | 文本型 | | |
YOLO. 初始化YOLO (0.3, 0.5, 0.3, “C:\Users\hanyo\Desktop\yolov5s.onnx”)输入图片 = 视觉_图像解码 ( #图片1, #读图_彩色 )YOLO. 检测识别 (输入图片 )标题 = “小白鼠 YOLO5 V6.1 深度学习对象检测。”视觉_创建窗口 (标题, #窗口_标准 )视觉_显示图像 (标题, 输入图片 )视觉_等待按键 (0 )视觉_销毁所有窗口 ()返回 (0 )
效果展示:
|
评分
-
查看全部评分
|