当前位置:   article > 正文

Flask部署YOLOv5_yolov5flask部署

yolov5flask部署

转自:Flask部署YOLOv5 - 知乎

YOLOv5的flask部署 - 迷途小书童的Note的个人空间 - OSCHINA - 中文开源技术交流社区

Flask是一种用python实现轻量级的web服务,也称为微服务,其灵活性较强而且效率高,在深度学习方面,也常常用来部署B/S模型。下面以yolov5s模型为例,介绍基于Flask的封装和部署过程。

  • 封装YOLOv5

编写yolov5.py,封装yolov5推理过程

  1. class YOLOv5(object):
  2. # 参数设置
  3. _defaults = {
  4. "weights": "./weights/yolov5s.pt",
  5. "imgsz": 640,
  6. "iou_thres":0.45,
  7. "conf_thres":0.25,
  8. "classes":0 #只检测人
  9. }
  10. @classmethod
  11. def get_defaults(cls,n):
  12. if n in cls._defaults:
  13. return cls._defaults[n]
  14. else:
  15. return "Unrecognized attribute name '" + n + "'"
  16. # 初始化操作,加载模型
  17. def __init__(self,device='0',**kwargs):
  18. self.__dict__.update(self._defaults)
  19. self.device = select_device(device)
  20. self.half = self.device != "cpu"
  21. self.model = attempt_load(self.weights, map_location=self.device) # load FP32 model
  22. self.imgsz = check_img_size(self.imgsz, s=self.model.stride.max()) # check img_size
  23. if self.half:
  24. self.model.half() # to FP16
  25. # 推理部分
  26. def infer(self,inImg):
  27. # 使用letterbox方法将图像大小调整为640大小
  28. img = letterbox(inImg, new_shape=self.imgsz)[0]
  29. # 归一化与张量转换
  30. img = img[:, :, ::-1].transpose(2, 0, 1) # BGR to RGB, to 3x416x416
  31. img = np.ascontiguousarray(img)
  32. img = torch.from_numpy(img).to(self.device)
  33. img = img.half() if self.half else img.float() # uint8 to fp16/32
  34. img /= 255.0 # 0 - 255 to 0.0 - 1.0
  35. if img.ndimension() == 3:
  36. img = img.unsqueeze(0)
  37. # 推理
  38. pred = self.model(img, augment=True)[0]
  39. # NMS
  40. pred = non_max_suppression(pred, self.conf_thres, self.iou_thres, classes=self.classes, agnostic=True)
  41. bbox_xyxy = []
  42. confs = []
  43. cls_ids = []
  44. # 解析检测结果
  45. for i, det in enumerate(pred): # detections per image
  46. if det is not None and len(det):
  47. # 将检测框映射到原始图像大小
  48. det[:, :4] = scale_coords(img.shape[2:], det[:, :4], inImg.shape).round()
  49. # 保存结果
  50. for *xyxy, conf, cls in reversed(det):
  51. bbox_xyxy.append(xyxy)
  52. confs.append(conf.item())
  53. cls_ids.append(int(cls.item()))
  54. xyxys = torch.Tensor(bbox_xyxy)
  55. confss = torch.Tensor(confs)
  56. cls_ids = torch.Tensor(cls_ids)
  57. return xyxys, confss, cls_ids
  • 服务端程序

编写server.py文件,封装服务端程序

  1. app = Flask(__name__)
  2. det = YOLOv5()
  3. @app.route("/infer", methods=["POST"])
  4. def predict():
  5. result = {"success": False}
  6. if request.method == "POST":
  7. if request.files.get("image") is not None:
  8. try:
  9. # 得到客户端传输的图像
  10. start = time.time()
  11. input_image = request.files["image"].read()
  12. imBytes = np.frombuffer(input_image, np.uint8)
  13. iImage = cv2.imdecode(imBytes, cv2.IMREAD_COLOR)
  14. # 执行推理
  15. outs = det.infer(iImage)
  16. print("duration: ",time.time()-start)
  17. if (outs is None) and (len(outs) < 0):
  18. result["success"] = False
  19. # 将结果保存为json格式
  20. result["box"] = outs[0].tolist()
  21. result["conf"] = outs[1].tolist()
  22. result["classid"] = outs[2].tolist()
  23. result['success'] = True
  24. except Exception:
  25. pass
  26. return jsonify(result)
  27. if __name__ == "__main__":
  28. print(("* Loading yolov5 model and Flask starting server..."
  29. "please wait until server has fully started"))
  30. app.run(host='127.0.0.1', port=7000)

编写client.py,封装客户端程序

  1. # 将图像以jpg编码,并转换为字节流
  2. def get_img_bytes(img):
  3. img_str = cv2.imencode('.jpg',img)[1].tobytes() if img is not None else None
  4. return img_str
  5. # 定义工具方法,在原始图像上画框
  6. def plot_one_box(x, img, color=None, label="person", line_thickness=None):
  7. """ 画框,引自 YoLov5 工程.
  8. 参数:
  9. x: 框, [x1,y1,x2,y2]
  10. img: opencv图像
  11. color: 设置矩形框的颜色, 比如 (0,255,0)
  12. label: str
  13. line_thickness: int
  14. return:
  15. no return
  16. """
  17. tl = (
  18. line_thickness or round(0.002 * (img.shape[0] + img.shape[1]) / 2) + 1
  19. ) # line/font thickness
  20. color = color or [random.randint(0, 255) for _ in range(3)]
  21. c1, c2 = (int(x[0]), int(x[1])), (int(x[2]), int(x[3]))
  22. cv2.rectangle(img, c1, c2, color, thickness=tl, lineType=cv2.LINE_AA)
  23. if label:
  24. tf = max(tl - 1, 1) # font thickness
  25. t_size = cv2.getTextSize(label, 0, fontScale=tl / 3, thickness=tf)[0]
  26. c2 = c1[0] + t_size[0], c1[1] - t_size[1] - 3
  27. cv2.rectangle(img, c1, c2, color, -1, cv2.LINE_AA) # filled
  28. cv2.putText(
  29. img,
  30. label,
  31. (c1[0], c1[1] - 2),
  32. 0,
  33. tl / 3,
  34. [225, 255, 255],
  35. thickness=tf,
  36. lineType=cv2.LINE_AA,
  37. )
  38. def main():
  39. img = cv2.imread("./bus.jpg")
  40. bFrame = get_img_bytes(img)
  41. request_input = {'image': bFrame}
  42. result = requests.post('http://127.0.0.1:7000/infer', files=request_input).json()
  43. if result['success']:
  44. boxs = result["box"]
  45. confs = result["conf"]
  46. ids = result["classid"]
  47. if boxs is not None:
  48. for i,box in enumerate(boxs):
  49. plot_one_box(toInt(box),img,label=str(ids[i])
  50. cv2.imshow("image",img)
  51. cv2.waitKey(0)
  • 效果展示
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/292175
推荐阅读
相关标签
  

闽ICP备14008679号