当前位置:   article > 正文

Yolov7如期而至,奉上ONNXRuntime的推理部署流程(CPU/GPU)_yolov7 onnx

yolov7 onnx

一、V7效果真的的v587,识别率和速度都有了极大的提升,这里先放最新鲜的github链接:

https://github.com/WongKinYiu/yolov7

二、v7的训练我这里就不做过多的赘述了,这里主要是进行讲解怎么把.pt文件转为onnx和后续的推理问题:

 2.1首先是pip的版本非常重要,博主亲自测试了,发现确实只有对应版本,ONNX才能成功,以至于后续的onnxruntime才能正常的ReadLoad~~

  1. pip install onnx==1.12.0
  2. pip install onnx-simplifier==0.4.0
  3. pip install coloredlogs==15.0.1
  4. pip install humanfriendly==10.0
  5. pip install onnxruntime-gpu==1.12.0
  6. pip isntall onnxsim-no-ort==0.4.0
  7. pip install opencv-python==4.5.2.52(注意cv2一定不能用4.6.0)
  8. pip install protobuf==3.19.4
  9. pip install setuptools==63.2.0

我进行运行的torch和torchvision版本是:

torch1.12.0+cu113  +  torchvision 0.13.0+cu113 + python3.8

这里值得注意的是,在v7的requirements.txt中备注了不要使用这个版本训练,但是做推理的时候我发现,就这个版本可以完成推理,太难了QAQ。。。。

这里推荐一个下载torch的.whl文件的链接:https://download.pytorch.org/whl/torch_stable.html

在里面找到对应的版本就行了(PS:只要torch与torchvison版本对应上就行,cu前缀其实限制没那么多,我的cuda是11.0,但是我pip install 的torch轮子的cu113的O(∩_∩)O):

2.2 有了转换环境之后我们进行export.py的关键步骤:

在V7项目的根目录下有export.py文件,这里不对文件内部做修改,可以直接执行命令语句:

python export.py --grid --end2end --simplify --topk-all 100 --iou-thres 0.3 --conf-thres 0.8 --img-size 640 640 --max-wh 640 --weights weights/onnxruntime.pt

 切记需要将这些超参数打上,看了下解释因该是做了模型剪枝simple啥的,所以相关的参数必须齐全,--weights这里写你们自己的模型pt文件就可以了,其它参数根据自己的模型进行修改就好了,我这里拿V7官方的预训练好的模型(yolov7-tiny.pt)进行演示:

 忽略一些警告,如下图所示就这么轻松转换成功啦:

 我们在netro(https://netron.app/)中打开这个onnx看一看,发现在输出已经处理好变为7维的向量了:

 三、关于推理部署

有了onnx文件,我们需要放在onnxruntime工具包下做推理

3.1 加载推理模型:

  1. def init_engine(self):
  2. providers = ['CUDAExecutionProvider', 'CPUExecutionProvider'] if self.device else ['CPUExecutionProvider']
  3. self.session = ort.InferenceSession(self.weights, providers=providers)

3.2 对输入图像进行前处理(做灰条填充)+变为tensor能认的4维:

  1. def letterbox(self, im, color=(114, 114, 114), auto=True, scaleup=True, stride=32):
  2. # 调整大小和垫图像,同时满足跨步多约束
  3. shape = im.shape[:2] # current shape [height, width]
  4. new_shape = self.img_new_shape
  5. # 如果是单个size的话,就在这里变成一双
  6. if isinstance(new_shape, int):
  7. new_shape = (new_shape, new_shape)
  8. # 尺度比 (new / old)
  9. r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
  10. if not scaleup: # 只缩小,不扩大(为了更好的val mAP)
  11. r = min(r, 1.0)
  12. # 计算填充
  13. new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
  14. dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1] # wh padding
  15. if auto: # 最小矩形区域
  16. dw, dh = np.mod(dw, stride), np.mod(dh, stride) # wh padding
  17. dw /= 2 # divide padding into 2 sides
  18. dh /= 2
  19. if shape[::-1] != new_unpad: # resize
  20. im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
  21. top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
  22. left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
  23. im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color) # add border
  24. im = im.transpose((2, 0, 1))
  25. im = np.expand_dims(im, 0)
  26. im = np.ascontiguousarray(im)
  27. im = im.astype(np.float32)
  28. im /= 255
  29. return im, r, (dw, dh)

3.3 然后就可以放如onnxruntime中得到那7维的输出结果了:

  1. def preprocess(self, image_path):
  2. self.img = cv2.imread(image_path)
  3. self.img = cv2.cvtColor(self.img, cv2.COLOR_BGR2RGB)
  4. image = self.img.copy()
  5. im, ratio, dwdh = self.letterbox(image, auto=False)
  6. t1 = time.time()
  7. outputs = self.predict(im)
  8. print("推理时间", (time.time() - t1) * 1000, ' ms')
  9. ori_images = [self.img.copy()]
  10. for i, (batch_id, x0, y0, x1, y1, cls_id, score) in enumerate(outputs):
  11. image = ori_images[int(batch_id)]
  12. box = np.array([x0, y0, x1, y1])
  13. box -= np.array(dwdh * 2)
  14. box /= ratio
  15. box = box.round().astype(np.int32).tolist()
  16. cls_id = int(cls_id)
  17. score = round(float(score), 3)
  18. name = self.names[cls_id]
  19. color = self.colors[name]
  20. name += ' ' + str(score)
  21. cv2.rectangle(image, box[:2], box[2:], color, 2)
  22. cv2.putText(image, name, (box[0], box[1] - 2), cv2.FONT_HERSHEY_SIMPLEX, 0.75, [225, 255, 255], thickness=2)
  23. a = Image.fromarray(ori_images[0])
  24. return a

3.4 pre的部分比较简单基本onnx都处理过了,直接拿字典结果就可以

  1. def predict(self, im):
  2. outname = [i.name for i in self.session.get_outputs()]
  3. inname = [i.name for i in self.session.get_inputs()]
  4. inp = {inname[0]: im}
  5. outputs = self.session.run(outname, inp)[0]
  6. return outputs

3.5 可以看看推理时间还是非常快的,单帧在10ms左右,真是100FPS!!!!!

3.6 放一张马的传统,哈哈:

2022年9月21日 最后补充下,其实上面就是源码,把它拼接到一起就是一个整体脚本了呀

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/295609
推荐阅读
相关标签